1、以下是扬创开发板给的 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.* 2007-6*/#include #include #include #include #include
2、#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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
3、*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 -EINVAL;s3
4、c2410_gpio_setpin(led_tablearg, !cmd);/*给寄存器赋值,使某一位置 1 或 0,led 亮,给寄存器置 0,因此对 cmd 取反*/*通过 s3c2410_gpio_setpin()来做,此函数为驱动函数的核心操作*/*case 0 和 case 1 操作一样*/default:return -EINVAL;return 0;/*设备驱动文件操作结构体*/static struct file_operations led_fops = .ioctl = led_ioctl,;static struct miscdevice led_dev = MISC_D
5、YNAMIC_MINOR,“led“,/*struct miscdevice int minor; /MISC_DYNAMIC_MINORconst char *name;/“led“const struct file_operations *fops; /struct device *parent;struct device *this_device;此结构体是注册混合设备所需要的参数。主要有:minor:次设备号,所有的 misc 设备共用一个主设备号,所以注册 misc 设备时只要次设备号就可以了。利用次设备号来区分设备的。name:misc 设备名。*fops:misc 设备文件操作结
6、构体。其它三个参数很少用*/static int led_init(void)pr_info(“%sn“, LED_DRIVER);/*printk(KERN_INFO fmt, #arg)#defineKERN_INFO“ 提示信息,如驱动程序启动时,打印硬件信息没有指定日志级别的 printk 语句默认采用的级别是 DEFAULT_ MESSAGE_LOGLEVEL(这个默认级别一般为,即与 KERN_WARNING 在一个级别上) ,其定义在 linux26/kernel/printk.c 中可以找到。下面是一个比较简单的使用printk(KERN_INFO “INFOn“); /这里可
7、以使用数字代替 KERN_INFO,即可以写成 printk( “INFOn“); 在这个格式的定义中,日志级别和信息文本之间不能够使用逗号隔开,因为系统在进行编译的时候,将日志级别转换成字符串于后面的文本信息进行连接。*/misc_register(/ misc 设备注册/*非标准设备使用 misc_register,即一些字符设备不符合预先确定的字符设备范畴,这些设备就用主编号 10 一起归于“其他类型“ ,misc_register()用主编号 10 调用 register_chrdev(),设备名称和函数表指针通过 miscdevice 数据结构获得。同样,miscdevice 数据结
8、构还保存设备驱动程序所使用的次要号码。*/return 0;static void _exit led_exit(void)misc_deregister(/*misc(混合,其他类型,不能严格划分的设备类型)类设备的注销函数,成功返回为 0,错误返回一个错误代码*/module_init(led_init);module_exit(led_exit);MODULE_AUTHOR(“lili “);MODULE_LICENSE(“GPL“);应用程序:#include /*标准输入输出库,像 sscanf 函数,fprintf 函数都是在这个库里*/#include #include /*一些
9、宏的定义在这里面,像 stderr*/#include /*文件操作控制库,像 ioctl 函数就在这里*/*执行:./led 1 1*/int main(int argc, char *argv)/*argc 表示参数的个数,而参数都存放在 argv 里,它是指针数组*/ int on; /*led 的开关状态,从第三个参数中获取*/int led_number; /*led 的编号 ,从第二个参数中获取*/ int fd; /*设备号,将从打开的 leds 设备获得*/ /*获取参数,并作参数的检验*/*scanf/sscanf 函数的返回值反映的是按照指定的格式符正确读入的数据的个数(s
10、scanf(argv1, “%d“, fprintf(stderr, “t led led_number on|offn“);fprintf(stderr, “Options:n“);fprintf(stderr, “t led_number from 0 to 3n“);fprintf(stderr, “t on 1 off 0n“);/*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 不亮,还不知为什么,望高手指点!