linux驱动按键控制led灯

来源:互联网 发布:strcpy函数 指针 数组 编辑:程序博客网 时间:2024/04/30 21:02
IO端口操作

1.基本概念
机器的组成:
.处理器
.总线
.IO外设

2.IO映射及使用
1)申请IO
<linux/ioport.h>
struct resource *request_mem_region(resource_size_t start,resource_size_t n,const char *name)
void release_mem_region(resource_size_t start,resource_size_t n)

2)映射IO
<linux/io.h>
void __iomem *ioremap(unsigned long phys_addr,size_t size)
void  iounmap(void __iomem);

3)使用端口
int ioread32(void __iomem *)

iowrite32(value,void __iomem *)

实例:

driver.c

#include <linux/kernel.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/kdev_t.h>#include <linux/cdev.h>#include <asm/uaccess.h>#include <linux/errno.h>#include "myioctl.h"#include <linux/ioport.h>#include <linux/io.h>struct resource *ptr = NULL;unsigned long *gpj2con = NULL;//ledunsigned long *gph2con = NULL;//keystatic dev_t dev_num=0;static struct cdev *cdev_p;int led_open(struct inode *inode,struct file *file){printk("led kernel open func init\n");// led initint val;val = ioread32(gpj2con);val &=~(0xF<<0);val |=(0x1<<0);iowrite32(val,gpj2con);val = ioread32(gpj2con+1);val |=(0x1<<0);iowrite32(val,gpj2con+1);// key initval = ioread32(gph2con);val &=~(0xf<<0);iowrite32(val,gph2con);return 0;}int led_close(struct inode *inode,struct file *file){printk("led kernel close func init\n");return 0;}char kbuf[100];ssize_t led_write(struct file *file, char __user *buf, size_t count, loff_t *offset){//memcpy(kbuf,buf,count);if(copy_from_user(kbuf,buf,count)){printk("copy data form user fail\n");return -EFAULT;}return 0;}//获取key值ssize_t led_read(struct file *file, char __user *buf, size_t count, loff_t *offset){int kbuf = (*(gph2con + 1) & (0x1));printk("gph2dat[0] = %d\n",kbuf);if(copy_to_user(buf,&kbuf,count)){printk("copy data to user fail\n");return -EFAULT;}return 0;}int led_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){printk("cmd=%d;arg=%d\n",cmd,arg);if (_IOC_NR(cmd)>=MAGIC_MAX)return -1;if (_IOC_TYPE(cmd)!=TYPE)return -1;int val;switch(_IOC_NR(cmd)){case 0:printk("led on \n");//*(vaddr + 1) &=~(0x1<<0);val = ioread32(gpj2con+1);val &=~(0x1<<0);iowrite32(val,gpj2con+1);break;case 1:printk("led off\n");//*(vaddr + 1) |=(0x1<<0);val = ioread32(gpj2con+1);val |=(0x1<<0);iowrite32(val,gpj2con+1);break;case 2://led on or offval = ioread32(gpj2con+1);val ^= (0x1<<0);iowrite32(val,gpj2con+1);break;}return 0;}struct file_operations led_fops={.owner=THIS_MODULE,.open = led_open,.release = led_close,.write = led_write,.read = led_read,.ioctl = led_ioctl,};int __init led_init(){printk("led init\n");int ret;ret = alloc_chrdev_region(&dev_num,0,1,"led-xx");if (ret < 0){printk("chrdev num fail\n");return -1;}printk("dev num=%d ; major = %d ; minor = %d ;",dev_num,MAJOR(dev_num),MINOR(dev_num));cdev_p = cdev_alloc();cdev_init(cdev_p,&led_fops);ret = cdev_add( cdev_p,dev_num,1 );if (ret){printk("cdev add fail\n");return -1;}//申请io端口,请求分配指定的I/O内存资源。led-xx可以改?ptr = request_mem_region(0xe0200280,0x1000,"led-xx");if (ptr == NULL){printk("request_mem_region fail\n");return -1;}//映射iogpj2con = (unsigned long *)ioremap(0xe0200280,0x1000);if (gpj2con == NULL){printk("ioremap fail\n");return -1;}//这里不用申请io?gph2con = (unsigned long *)ioremap(0xe0200c40,0x1000);if (gph2con == NULL){printk("ioremap fail\n");return -1;}return 0;}void __exit led_exit(){iounmap(gpj2con);iounmap(gph2con);release_mem_region(0xe0200280,0x1000);release_mem_region(0xe0200c40,0x1000);cdev_del(cdev_p);unregister_chrdev_region(dev_num,1);printk("led exit\n");}module_init(led_init);module_exit(led_exit);MODULE_LICENSE("LEDxx");MODULE_AUTHOR("XX");MODULE_DESCRIPTION("xx test");

myioctl.h

#define LED_NUM11#define LED_NUM22#define STEP_MOTO   3#define MOTO_ON 0#define MOTO_OFF1#define TYPE'K'#define MAGIC_MAX3#define LED_ON _IO(TYPE,0)#define LED_OFF _IO(TYPE,1)#define LED_EOR_IO(TYPE,2)
app.c

#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/ioctl.h>#include <stdio.h>#include "myioctl.h"int key_val;int main(int argc,char **argv){int fd = open("/dev/xxled",O_RDWR);if(fd < 0){printf("open fail\n");return -1;}while(1){//循环read读取key的值read(fd,&key_val,4);//读4个字节,32位if(key_val == 0){// 按下去抖do{usleep(100000);read(fd,&key_val,4);}while(key_val == 0);//读取到按下就ioctl修改led灯状态ioctl(fd,LED_EOR);}//300毫秒读一次usleep(300000);}close(fd);return 0;}

makefile

obj-m += led.oKERNEL_DIR := /usr/mkdrv/src/android-kernel-samsung-devall:make modules -C $(KERNEL_DIR) M=`pwd`arm-linux-gcc app.c -o appcp led.ko app /nfs  make cleanclean:make modules clean -C $(KERNEL_DIR) M=`pwd` 




0 0
原创粉丝点击