歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 字符驅動設計----mini2440 LED驅動設計之路

字符驅動設計----mini2440 LED驅動設計之路

日期:2017/3/1 10:12:05   编辑:Linux編程

大多數書籍在介紹字符驅動過於理論化,縱覽一章都是些文字,再附上一些零碎的代碼,看的人頭暈,時間長了自然就不想看了。 對於驅動的學習,剛開始不能過於理論化,一定要結合實際,要不然像空中樓台,住在上面,心裡老感覺不踏實。那麼如何入手呢?我覺得三點是很重要的:

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. #define DEVICE_NAME "leds" /* 加載模式後,執行”cat /proc/devices”命令看到的設備名稱 */
  10. #define LED_MAJOR 231 /* 主設備號 */
  11. /* 應用程序執行ioctl(fd, cmd, arg)時的第2個參數 */
  12. #define IOCTL_LED_ON 0
  13. #define IOCTL_LED_OFF 1
  14. /* 用來指定LED所用的GPIO引腳 */
  15. static unsigned long led_table [] = {
  16. S3C2410_GPB5,
  17. S3C2410_GPB6,
  18. S3C2410_GPB7,
  19. S3C2410_GPB8,
  20. };
  21. /* 用來指定GPIO引腳的功能:輸出 */
  22. static unsigned int led_cfg_table [] = {
  23. S3C2410_GPB5_OUTP,
  24. S3C2410_GPB6_OUTP,
  25. S3C2410_GPB7_OUTP,
  26. S3C2410_GPB8_OUTP,
  27. };
  28. /* 應用程序對設備文件/dev/leds執行open(...)時,
  29. * 就會調用s3c24xx_leds_open函數
  30. */
  31. static int s3c24xx_leds_open(struct inode *inode, struct file *file)
  32. {
  33. int i;
  34. for (i = 0; i < 4; i++) {
  35. // 設置GPIO引腳的功能:本驅動中LED所涉及的GPIO引腳設為輸出功能
  36. s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
  37. }
  38. return 0;
  39. }
  40. /* 應用程序對設備文件/dev/leds執行ioclt(...)時,
  41. * 就會調用s3c24xx_leds_ioctl函數
  42. */
  43. static int s3c24xx_leds_ioctl(
  44. struct inode *inode,
  45. struct file *file,
  46. unsigned int cmd,
  47. unsigned long arg)
  48. {
  49. if (arg > 4) {
  50. return -EINVAL;
  51. }
  52. switch(cmd) {
  53. case IOCTL_LED_ON:
  54. // 設置指定引腳的輸出電平為0
  55. s3c2410_gpio_setpin(led_table[arg], 0);
  56. return 0;
  57. case IOCTL_LED_OFF:
  58. // 設置指定引腳的輸出電平為1
  59. s3c2410_gpio_setpin(led_table[arg], 1);
  60. return 0;
  61. default:
  62. return -EINVAL;
  63. }
  64. }
  65. /* 這個結構是字符設備驅動程序的核心
  66. * 當應用程序操作設備文件時所調用的open、read、write等函數,
  67. * 最終會調用這個結構中指定的對應函數
  68. */
  69. static struct file_operations s3c24xx_leds_fops = {
  70. .owner = THIS_MODULE, /* 這是一個宏,推向編譯模塊時自動創建的__this_module變量 */
  71. .open = s3c24xx_leds_open,
  72. .ioctl = s3c24xx_leds_ioctl,
  73. };
  74. /*
  75. * 執行“insmod s3c24xx_leds.ko”命令時就會調用這個函數
  76. */
  77. static int __init s3c24xx_leds_init(void)
  78. {
  79. int ret;
  80. /* 注冊字符設備驅動程序
  81. * 參數為主設備號、設備名字、file_operations結構;
  82. * 這樣,主設備號就和具體的file_operations結構聯系起來了,
  83. * 操作主設備為LED_MAJOR的設備文件時,就會調用s3c24xx_leds_fops中的相關成員函數
  84. * LED_MAJOR可以設為0,表示由內核自動分配主設備號
  85. */
  86. ret = register_chrdev(LED_MAJOR, DEVICE_NAME, &s3c24xx_leds_fops);
  87. if (ret < 0) {
  88. printk(DEVICE_NAME " can't register major number\n");
  89. return ret;
  90. }
  91. printk(DEVICE_NAME " initialized\n");
  92. return 0;
  93. }
  94. /*
  95. * 執行”rmmod s3c24xx_leds.ko”命令時就會調用這個函數
  96. */
  97. static void __exit s3c24xx_leds_exit(void)
  98. {
  99. /* 卸載驅動程序 */
  100. unregister_chrdev(LED_MAJOR, DEVICE_NAME);
  101. }
  102. /* 這兩行指定驅動程序的初始化函數和卸載函數 */
  103. module_init(s3c24xx_leds_init);
  104. module_exit(s3c24xx_leds_exit);
  105. /* 描述驅動程序的一些信息,不是必須的 */
  106. MODULE_AUTHOR("http://my.csdn.net/czxyhll."); // 驅動程序的作者
  107. MODULE_DESCRIPTION("S3C2410/S3C2440 LED Driver"); // 一些描述信息
  108. MODULE_LICENSE("GPL"); // 遵循的協議
Copyright © Linux教程網 All Rights Reserved