mini2440之led的几种驱动方式

来源:互联网 发布:防止自动安装软件 编辑:程序博客网 时间:2024/06/05 13:21

1.混杂设备驱动

#include <linux/miscdevice.h>#include <linux/delay.h>#include <asm/irq.h>#include <mach/regs-gpio.h>#include <mach/hardware.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/mm.h>#include <linux/fs.h>#include <linux/types.h>#include <linux/delay.h>#include <linux/moduleparam.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/ioctl.h>//#include <linux/cdev.h>#include <linux/string.h>#include <linux/list.h>#include <linux/pci.h>#include <linux/gpio.h>#include <asm/uaccess.h>#include <asm/atomic.h>#include <asm/unistd.h>//注意,结构体定义及声明,后面有;//函数末尾是没有;的#define DEVICE_NAME "leds"//用static表示,此函数/变量只在本文件中被调用//extern,可被外部文件调用static unsigned long led_table [] = {S3C2410_GPB(5),//端口引用S3C2410_GPB(6),S3C2410_GPB(7),S3C2410_GPB(8),};//端口输出状态static unsigned int led_cfg_table [] = {S3C2410_GPIO_OUTPUT,S3C2410_GPIO_OUTPUT,S3C2410_GPIO_OUTPUT,S3C2410_GPIO_OUTPUT,};static int sbc2440_leds_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){switch(cmd) {case 0:case 1:if (arg > 4) {return -EINVAL;}s3c2410_gpio_setpin(led_table[arg], !cmd);return 0;default:return -EINVAL;}}//应用程序函数接口和驱动程序函数接口映射static struct file_operations dev_fops = {.owner = THIS_MODULE,.ioctl = sbc2440_leds_ioctl,};static struct miscdevice misc = {.minor = MISC_DYNAMIC_MINOR,    //混杂设备次设备号动态分配.name = DEVICE_NAME,      //此设备的名字,生成的模块或者驱动都这个名字,应用程序调用这个节点.fops = &dev_fops,};static int __init dev_init(void){int ret;int i;for (i = 0; i < 4; i++) {s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);s3c2410_gpio_setpin(led_table[i], 0);}//misc_register调用了misc结构体,misc又调用了dev_fops结构体,dev_fops结构体又调用了各个文件控制函数//本文件主要是ioctl函数ret = misc_register(&misc);//混杂设备注册printk (DEVICE_NAME"\tinitialized\n");return ret;}static void __exit dev_exit(void){misc_deregister(&misc);//混杂设备注销}//驱动模块,先看module_init,module_exit,通过这两个宏名,往上看函数是怎么调用的module_init(dev_init);module_exit(dev_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("FriendlyARM Inc.");

2.一般字符设备 cdev+ioctl

#include <linux/module.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/types.h>#include <linux/gpio.h>#include <linux/ioctl.h>#include <linux/cdev.h>#include <linux/mm.h>#include <mach/regs-gpio.h>#include <mach/hardware.h>#include <asm/uaccess.h>#include <asm/atomic.h>#include <asm/unistd.h>#define DEVICE_NAME "myled"static struct cdev *cdevp=NULL;//定义及声明一个cdev结构static dev_t devno;//定义设备号static unsigned long led_table[] = {    S3C2410_GPB(5),    S3C2410_GPB(6),    S3C2410_GPB(7),    S3C2410_GPB(8),};static unsigned int led_cfg_table[] = {    S3C2410_GPIO_OUTPUT,    S3C2410_GPIO_OUTPUT,    S3C2410_GPIO_OUTPUT,    S3C2410_GPIO_OUTPUT,};static int s3c2440_leds_ioctl(struct inode *inode,struct file *filp,unsigned intcmd,unsigned long arg){    switch(cmd)    {        case 0:        case 1:            if(arg>3)            {                return -EINVAL;//无效的地址             }        s3c2410_gpio_setpin(led_table[arg],!cmd);        return 0;        default:            return -EINVAL;//无效的地址     }}static struct file_operations myled_fops = {    .owner = THIS_MODULE,    .ioctl = s3c2440_leds_ioctl,};static int __init myled_init_module(void){     int ret;    int i,err;                 //动态分配返回的设备号,起始次设备号,要注册的设备号个数,设备号(体现在/proc/devices)    ret = alloc_chrdev_region(&devno,0,1,DEVICE_NAME); //动态注册设备号    if(ret < 0)    {        printk(DEVICE_NAME "can't get the major number\n");        return ret;    }    cdevp = cdev_alloc();//动态分配cdev空间     cdev_init(cdevp,&myled_fops);//初始化struct cdev内核字符设备,//初始化cdev的成员,建立cdev和file_operation之间连接。     cdevp->owner = THIS_MODULE;                                //向系统添加一个cdev    err=cdev_add(cdevp,devno,1);//添加到内核系统,成功返回0,失败返回-1     if(err)    {     printk(KERN_NOTICE "Error %d adding cdev",err);     unregister_chrdev_region(devno,1);//函数原型void unregister_chrdev_region(dev_t first,unsigned int count);       return -EFAULT;    }    //初始化leds     for(i=0;i<4;i++)    {        s3c2410_gpio_cfgpin(led_table[i],led_cfg_table[i]);//配置对应的leds为输出状态         s3c2410_gpio_setpin(led_table[i],1);//初始化时全部熄灭    }    printk(DEVICE_NAME "\tinitialized!\n");    return 0;}static void __exit myled_exit_module(void){    cdev_del(cdevp);//向系统删除一个cdev    unregister_chrdev_region(devno,1);    printk(DEVICE_NAME "\tremove!\n");}module_init(myled_init_module);module_exit(myled_exit_module);MODULE_LICENSE("GPL");MODULE_AUTHOR("fedora");

3.一般字符设备驱动cdev+write

#include <linux/module.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/errno.h>#include <linux/types.h>#include <linux/mm.h>#include <linux/cdev.h>#include <linux/gpio.h>#include <asm/io.h>#include <asm/uaccess.h>#include <asm/unistd.h>#include <mach/regs-gpio.h>#include <mach/hardware.h>#define DEVICE_NAME "leds" //设备名称struct cdev dev;    //定义内核内部的字符设备devdev_t devno;    //设备号static unsigned long led_table[] = {    S3C2410_GPB(5),  S3C2410_GPB(6),  S3C2410_GPB(7),  S3C2410_GPB(8),};static unsigned int led_cfg_table[] = {    //led的管脚配置为输出状态   S3C2410_GPIO_OUTPUT,  S3C2410_GPIO_OUTPUT,  S3C2410_GPIO_OUTPUT,  S3C2410_GPIO_OUTPUT,};//对led进行写操作static ssize_t myled_write(struct file *filp,const char __user *buf,size_t count,loff_t *f_pos){  char ch[2];//字符数组,用来存储用户空间的数据.   //函数原型:unsigned long copy_from_user(void *to,const void __user *from,unsigne long count);   copy_from_user(&ch,buf,2);//用户空间buf缓冲区的数据传给字符数组ch[2]中,2表示传送的字节数!   int ledno =(int)ch[0]-48;//第一个字符代表led的下标号,第二个字符代表对应的led状态.   int status =(int)ch[1]-48;//字符'0'的ASCII码值为48   s3c2410_gpio_setpin(led_table[ledno],!status);//调用内部函数来设置相应的led状态.   return 1;}//文件操作结构体static struct file_operations myled_fops = {  .owner = THIS_MODULE,  .write = myled_write,};static int __init myled_init(void){  int i,ret;  //动态分配设备号.函数的原型int alloc_chrdev_region(dev_t *dev,unsigned int firstminor,unsigned int count,char *name); firstminor是第一个要用的次设备号,一般为0,count是请求的连续设备编号的总数,这里为1  ret = alloc_chrdev_region(&devno,0,1,DEVICE_NAME);  if(ret<0)  {    printk(KERN_WARNING "myled: can't get major %d\n",MAJOR(devno));    return ret;  }  //初始化led   for(i=0;i<4;i++)    {     s3c2410_gpio_cfgpin(led_table[i],led_cfg_table[i]);     s3c2410_gpio_setpin(led_table[i],0);//初始化点亮4个led     }    //初始化cdev 并向系统注册.   //字符设备的注册,注册一个独立的cdev设备的步骤   //1,为struct cdev分配空间,可以直接声明struct cedv dev,也可以调用cdev_alloc()动态分配;2,初始化struct cdev,调用cdev_init();3,初始化cdev.owner;4,cdev设置完成后,通知内核struct cdev的信息,调用cdev_add();   //函数原型void cdev_init(struct cdev *cdev,const struct file_operations *fops);   cdev_init(&dev,&myled_fops);//将内核内部的cdev设备和led的文件操作结构联系起来.   dev.owner = THIS_MODULE;  int err;  //函数原型int cdev_add(struct cdev *p,dev_t dev,unsigned count);   err = cdev_add(&dev,devno,1);  if(err)    {     printk(KERN_NOTICE "Error %d adding cdev",err);     unregister_chrdev_region(devno,1);//函数原型void unregister_chrdev_region(dev_t first,unsigned int count);       return -EFAULT;    }  printk(DEVICE_NAME "\tinitialized 2010-6-23\n");  return 0;}static void __exit myled_exit(void){   cdev_del(&dev);//函数原型:void cdev_del(struct cdev *p);   unregister_chrdev_region(devno,1);//函数原型void unregister_chrdev_region(dev_t first,unsigned int count);   printk(DEVICE_NAME "\tremove\n");}module_init(myled_init);module_exit(myled_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("fedora");


原创粉丝点击