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");
- mini2440之led的几种驱动方式
- mini2440驱动分析之LED
- mini2440 led驱动代码 基于kernel2.6.32.2 之led
- MINI2440 LED驱动的汇编语言实现
- MINI2440 LED灯驱动
- mini2440 led驱动
- mini2440 led驱动
- 【复习】linux之LED驱动的设备树方式
- LED驱动分析(mini2440)
- mini2440 按键控制LED 驱动
- 基于mini2440的led驱动编写的总结
- 基于platform总线的mini2440的led设备驱动例子
- 用虚拟总线来实现的MINI2440 LED驱动
- 基于linux的mini2440 led驱动及应用程序
- LED数码管的驱动方式:静态驱动和动态驱动
- mini2440 led驱动及 应用程序注释
- mini2440 led驱动问题及代码
- 数码管的几种驱动方式汇总
- 网络编程
- 如果用IE无法连接VPN,则删除Microsoft Update KB2736233
- MBA学什么
- winarm下载
- Compound Words 10391
- mini2440之led的几种驱动方式
- silverlight 在ScrollViewer中动态添加控件时ScrollViewer滚动条始终至底
- iOS开发——加载、滑动翻阅大量图片解决方案详解
- SRM 563 比赛总结
- Nginx配置文件详细说明
- 存储过程返回新增数据的主键id值
- Quartz 2D 裁剪
- 如何给vb的UserControl添加属性、方法和事件?
- GCC中的堆栈编译器保护技术