字符驱动设计----mini2440 LED驱动设计之路


大多数书籍在介绍字符驱动过于理论化,纵览一章都是些文字,再附上一些零碎的代码,看的人头晕,时间长了自然就不想看了。 对于驱动的学习,刚开始不能过于理论化,一定要结合实际,要不然像空中楼台,住在上面,心里老感觉不踏实。那么如何入手呢?我觉得三点是很重要的:

1  驱动设计的总体框架(对于每种类型的驱动设计,最好画出模型图)

2  参考现有实例化的驱动

3  针对某一具体硬件,自己写驱动来实现

 接下来以字符驱动设计为例,也是mini2440led驱动实现。

1 字符设备驱动模型如下图所示,这是一个总体调用框架图,具体的字符设备驱动模型参照另外一篇引用的文章【字符设备驱动模型】,驱动层主要做的工作是file_operations结构体中一些关键函数的实现,包括open,read,ioctl。本例中主要实现open,ioctl。

2 现有驱动模型实例

  1. #include <linux/module.h>   
  2. #include <linux/kernel.h>   
  3. #include <linux/fs.h>   
  4. #include <linux/init.h>   
  5. #include <linux/delay.h>   
  6. #include <asm/irq.h>   
  7. #include <asm/arch/regs-gpio.h>   
  8. #include <asm/hardware.h>   
  9.   
  10. #define DEVICE_NAME     "leds"  /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称 */   
  11. #define LED_MAJOR       231     /* 主设备号 */   
  12.   
  13. /* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数 */  
  14. #define IOCTL_LED_ON    0   
  15. #define IOCTL_LED_OFF   1   
  16.   
  17. /* 用来指定LED所用的GPIO引脚 */  
  18. static unsigned long led_table [] = {  
  19.     S3C2410_GPB5,  
  20.     S3C2410_GPB6,  
  21.     S3C2410_GPB7,  
  22.     S3C2410_GPB8,  
  23. };  
  24.   
  25. /* 用来指定GPIO引脚的功能:输出 */  
  26. static unsigned int led_cfg_table [] = {  
  27.     S3C2410_GPB5_OUTP,  
  28.     S3C2410_GPB6_OUTP,  
  29.     S3C2410_GPB7_OUTP,  
  30.     S3C2410_GPB8_OUTP,  
  31. };  
  32.   
  33. /* 应用程序对设备文件/dev/leds执行open(...)时, 
  34.  * 就会调用s3c24xx_leds_open函数 
  35.  */  
  36. static int s3c24xx_leds_open(struct inode *inode, struct file *file)  
  37. {  
  38.     int i;  
  39.       
  40.     for (i = 0; i < 4; i++) {  
  41.         // 设置GPIO引脚的功能:本驱动中LED所涉及的GPIO引脚设为输出功能   
  42.         s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);  
  43.     }  
  44.     return 0;  
  45. }  
  46.   
  47. /* 应用程序对设备文件/dev/leds执行ioclt(...)时, 
  48.  * 就会调用s3c24xx_leds_ioctl函数 
  49.  */  
  50. static int s3c24xx_leds_ioctl(  
  51.     struct inode *inode,   
  52.     struct file *file,   
  53.     unsigned int cmd,   
  54.     unsigned long arg)  
  55. {  
  56.     if (arg > 4) {  
  57.         return -EINVAL;  
  58.     }  
  59.       
  60.     switch(cmd) {  
  61.     case IOCTL_LED_ON:  
  62.         // 设置指定引脚的输出电平为0   
  63.         s3c2410_gpio_setpin(led_table[arg], 0);  
  64.         return 0;  
  65.   
  66.     case IOCTL_LED_OFF:  
  67.         // 设置指定引脚的输出电平为1   
  68.         s3c2410_gpio_setpin(led_table[arg], 1);  
  69.         return 0;  
  70.   
  71.     default:  
  72.         return -EINVAL;  
  73.     }  
  74. }  
  75.   
  76. /* 这个结构是字符设备驱动程序的核心 
  77.  * 当应用程序操作设备文件时所调用的open、read、write等函数, 
  78.  * 最终会调用这个结构中指定的对应函数 
  79.  */  
  80. static struct file_operations s3c24xx_leds_fops = {  
  81.     .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */  
  82.     .open   =   s3c24xx_leds_open,       
  83.     .ioctl  =   s3c24xx_leds_ioctl,  
  84. };  
  85.   
  86. /* 
  87.  * 执行“insmod s3c24xx_leds.ko”命令时就会调用这个函数 
  88.  */  
  89. static int __init s3c24xx_leds_init(void)  
  90. {  
  91.     int ret;  
  92.   
  93.     /* 注册字符设备驱动程序 
  94.      * 参数为主设备号、设备名字、file_operations结构; 
  95.      * 这样,主设备号就和具体的file_operations结构联系起来了, 
  96.      * 操作主设备为LED_MAJOR的设备文件时,就会调用s3c24xx_leds_fops中的相关成员函数 
  97.      * LED_MAJOR可以设为0,表示由内核自动分配主设备号 
  98.      */  
  99.     ret = register_chrdev(LED_MAJOR, DEVICE_NAME, &s3c24xx_leds_fops);  
  100.     if (ret < 0) {  
  101.       printk(DEVICE_NAME " can't register major number\n");  
  102.       return ret;  
  103.     }  
  104.       
  105.     printk(DEVICE_NAME " initialized\n");  
  106.     return 0;  
  107. }  
  108.   
  109. /* 
  110.  * 执行”rmmod s3c24xx_leds.ko”命令时就会调用这个函数  
  111.  */  
  112. static void __exit s3c24xx_leds_exit(void)  
  113. {  
  114.     /* 卸载驱动程序 */  
  115.     unregister_chrdev(LED_MAJOR, DEVICE_NAME);  
  116. }  
  117.   
  118. /* 这两行指定驱动程序的初始化函数和卸载函数 */  
  119. module_init(s3c24xx_leds_init);  
  120. module_exit(s3c24xx_leds_exit);  
  121.   
  122. /* 描述驱动程序的一些信息,不是必须的 */  
  123. MODULE_AUTHOR("http://my.csdn.net/czxyhll.");        // 驱动程序的作者  
  124. MODULE_DESCRIPTION("S3C2410/S3C2440 LED Driver");   // 一些描述信息   
  125. MODULE_LICENSE("GPL");                              // 遵循的协议  
  • 1
  • 2
  • 下一页

相关内容