当前位置:文档之家› linux LED 驱动

linux LED 驱动

以下是扬创开发板给的led例程,将对应用程序和驱动程序进行详细注释和分析,并验证!/** LED interface driver for utu2440* This file is subject to the terms and conditions of the GNU General Public* License. See the file "COPYING" in the main directory of this archive* for more details.* bit.lili@ 2007-6*/#include <linux/types.h>#include <linux/ioport.h>#include <linux/fcntl.h>#include <linux/miscdevice.h>#include <linux/sched.h>#include <linux/spinlock.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/input.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/device.h>#include <asm/uaccess.h>#include <asm/system.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/arch/regs-gpio.h>#define LED_DRIVER "utu2440 LED Driver v1.00"static unsigned long led_table [] = {S3C2410_GPF4,S3C2410_GPF5,S3C2410_GPF6,S3C2410_GPF7,};static int led_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg);/*ioctl(fd, on, led_number);inode 和filp 指针是对应应用程序传递的文件描述符fd 的值,和传递给open 方法的相同参数*/static int led_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg){switch (cmd) {case 0:case 1:if (arg > 4) {return -EINV AL;}s3c2410_gpio_setpin(led_table[arg], !cmd);/*给寄存器赋值,使某一位置1或0,led亮,给寄存器置0,因此对cmd取反*/ /*通过s3c2410_gpio_setpin()来做,此函数为驱动函数的核心操作*//*case 0和case 1操作一样*/default:return -EINV AL;}return 0;}/*设备驱动文件操作结构体*/static struct file_operations led_fops = {.ioctl = led_ioctl,};static struct miscdevice led_dev = {MISC_DYNAMIC_MINOR,"led",&led_fops};/*struct miscdevice {int minor; //MISC_DYNAMIC_MINORconst char *name;//"led"const struct file_operations *fops; //&led_fopsstruct list_head list;struct device *parent;struct device *this_device;};此结构体是注册混合设备所需要的参数。

主要有:minor:次设备号,所有的misc设备共用一个主设备号,所以注册misc设备时只要次设备号就可以了。

利用次设备号来区分设备的。

name:misc设备名。

*fops:misc设备文件操作结构体。

其它三个参数很少用*/static int led_init(void){pr_info("%s\n", LED_DRIVER);/*printk(KERN_INFO fmt, ##arg)#defineKERN_INFO"<6>" 提示信息,如驱动程序启动时,打印硬件信息没有指定日志级别的printk语句默认采用的级别是DEFAULT_ MESSAGE_LOGLEVEL(这个默认级别一般为<4>,即与KERN_WARNING在一个级别上),其定义在linux26/kernel/printk.c中可以找到。

下面是一个比较简单的使用printk(KERN_INFO "INFO\n"); //这里可以使用数字代替KERN_INFO,即可以写成printk(<6> "INFO\n");在这个格式的定义中,日志级别和信息文本之间不能够使用逗号隔开,因为系统在进行编译的时候,将日志级别转换成字符串于后面的文本信息进行连接。

*/misc_register(&led_dev);// misc设备注册/*非标准设备使用misc_register,即一些字符设备不符合预先确定的字符设备范畴,这些设备就用主编号10一起归于"其他类型",misc_register()用主编号10调用register_chrdev(),设备名称和函数表指针通过miscdevice数据结构获得。

同样,miscdevice 数据结构还保存设备驱动程序所使用的次要号码。

*/ return 0;}static void __exit led_exit(void){misc_deregister(&led_dev);/*misc(混合,其他类型,不能严格划分的设备类型)类设备的注销函数,成功返回为0,错误返回一个错误代码*/}module_init(led_init);module_exit(led_exit);MODULE_AUTHOR("lili bit.lili@");MODULE_LICENSE("GPL");应用程序:#include <stdio.h> /*标准输入输出库,像sscanf函数,fprintf函数都是在这个库里*/#include <stdlib.h>#include <unistd.h> /*一些宏的定义在这里面,像stderr*/#include <sys/ioctl.h> /*文件操作控制库,像ioctl函数就在这里*//*执行:./led 1 1*/int main(int argc, char **argv)/*argc表示参数的个数,而参数都存放在argv里,它是指针数组*/{int on; /*led的开关状态,从第三个参数中获取*/int led_number; /*led的编号,从第二个参数中获取*/int fd; /*设备号,将从打开的leds设备获得*//*获取参数,并作参数的检验*//*scanf/sscanf 函数的返回值反映的是按照指定的格式符正确读入的数据的个数(sscanf(argv[1], "%d", &led_number)返回正确,应等于1)。

如果输入数据与指定格式不符,则会产生输入错误。

遇到输入错误,scanf函数会立即终止,返回已经成功读取的数据的个数。

所以,通过scanf函数的返回值和指定输入数据的个数(由格式符决定)的比较,可以判断数据输入是否成功。

*/if (argc != 3 || sscanf(argv[1], "%d", &led_number) != 1 || sscanf(argv[2],"%d", &on) != 1 ||on < 0 || on > 1 || led_number < 0 || led_number > 3) {fprintf(stderr, "Usage:\n");fprintf(stderr, "\t led led_number on|off\n");fprintf(stderr, "Options:\n");fprintf(stderr, "\t led_number from 0 to 3\n");fprintf(stderr, "\t on 1 off 0\n");/*stdout -- 标准输出设备(printf("..")) 同stdout。

stderr -- 标准错误输出设备两者默认向屏幕输出。

但如果用转向标准输出到磁盘文件,则可看出两者区别。

stdout输出到磁盘文件,stderr在屏幕*/exit(1);}fd = open("/dev/led", 0);/*驱动程序可以不实现open这个函数,在这种情况下,设备的打开操作永远成功。

*/if (fd < 0) {perror("open device /dev/led");exit(1);}ioctl(fd, on, led_number);close(fd);return 0;}总结:上面是点亮led的应用程序和驱动程序,在应用程序中,可以根据需要进行修改,比如让led闪烁等等,驱动程序和应用程序分别给了详细注释,如有错误欢迎指正!程序已在扬创开发板上验证,但验证中发现第二个led不亮,还不知为什么,望高手指点!。

相关主题