歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 第一個Linux驅動-流水燈

第一個Linux驅動-流水燈

日期:2017/3/1 10:18:01   编辑:Linux編程

本節介紹如何利用板載的Led和Linux的內核定時器實現一個簡單的流水燈的驅動,所使用的開發板是TQ2440,內核版本2.6.30.4。

程序比較簡單,也沒涉及到什麼機制,直接上代碼了!關於定時器的使用模板可以參考<<Linux設備驅動開發詳解>>(見http://www.linuxidc.com/Linux/2011-07/38211.htm).

驅動程序:

  1. #include<linux/module.h>
  2. #include<linux/init.h>
  3. #include<linux/types.h>
  4. #include<linux/fs.h>
  5. #include<linux/mm.h>
  6. #include<linux/cdev.h>
  7. #include<linux/slab.h>
  8. #include<linux/timer.h>
  9. #include<linux/jiffies.h>
  10. #include<asm/io.h>
  11. #include<asm/uaccess.h>
  12. #include<mach/regs-gpio.h>
  13. #define LED_MAJOR 244
  14. #define LED_ON 0
  15. #define LED_OFF 1
  16. #define LED1_PIN S3C2410_GPB5
  17. #define LED2_PIN S3C2410_GPB6
  18. #define LED3_PIN S3C2410_GPB7
  19. #define LED4_PIN S3C2410_GPB8
  20. static unsigned long led_major = LED_MAJOR;
  21. struct led_dev
  22. {
  23. struct cdev cdev;
  24. struct timer_list s_timer;
  25. atomic_t led_no; //LED編號
  26. atomic_t sec_counter; //秒計時數
  27. };
  28. struct led_dev *led_devp;
  29. void led_control(int led_no)
  30. {
  31. switch(led_no)
  32. {
  33. case 1:s3c2410_gpio_setpin(LED1_PIN,LED_ON);
  34. s3c2410_gpio_setpin(LED2_PIN,LED_OFF);
  35. s3c2410_gpio_setpin(LED3_PIN,LED_OFF);
  36. s3c2410_gpio_setpin(LED4_PIN,LED_OFF);
  37. break;
  38. case 2:s3c2410_gpio_setpin(LED1_PIN,LED_OFF);
  39. s3c2410_gpio_setpin(LED2_PIN,LED_ON);
  40. s3c2410_gpio_setpin(LED3_PIN,LED_OFF);
  41. s3c2410_gpio_setpin(LED4_PIN,LED_OFF);
  42. break;
  43. case 3:s3c2410_gpio_setpin(LED1_PIN,LED_OFF);
  44. s3c2410_gpio_setpin(LED2_PIN,LED_OFF);
  45. s3c2410_gpio_setpin(LED3_PIN,LED_ON);
  46. s3c2410_gpio_setpin(LED4_PIN,LED_OFF);
  47. break;
  48. case 4:s3c2410_gpio_setpin(LED1_PIN,LED_OFF);
  49. s3c2410_gpio_setpin(LED2_PIN,LED_OFF);
  50. s3c2410_gpio_setpin(LED3_PIN,LED_OFF);
  51. s3c2410_gpio_setpin(LED4_PIN,LED_ON);
  52. break;
  53. default:break;
  54. }
  55. }
  56. //定時器處理函數
  57. static void sec_timer_handler(unsigned long arg)
  58. {
  59. int num;
  60. mod_timer(&led_devp->s_timer,jiffies+HZ);
  61. num = atomic_read(&led_devp->led_no);
  62. if(num == 4)
  63. {
  64. atomic_set(&led_devp->led_no,1);
  65. }
  66. else
  67. {
  68. atomic_inc(&led_devp->led_no);
  69. }
  70. num = atomic_read(&led_devp->led_no);
  71. led_control(num);
  72. atomic_inc(&led_devp->sec_counter);
  73. num = atomic_read(&led_devp->sec_counter);
  74. printk(KERN_INFO "sec_count:%d\n",num);
  75. }
  76. static int led_open(struct inode *inode,struct file *filp)
  77. {
  78. struct timer_list *timer;
  79. timer = &led_devp->s_timer;
  80. init_timer(timer);
  81. timer->function = sec_timer_handler;
  82. timer->expires = jiffies+HZ; //計時頻率為HZ
  83. add_timer(timer);
  84. atomic_set(&led_devp->sec_counter,0);
  85. atomic_set(&led_devp->led_no,0);
  86. return 0;
  87. }
  88. static int led_release(struct inode *inode, struct file *filp)
  89. {
  90. del_timer(&led_devp->s_timer);
  91. return 0;
  92. }
  93. static ssize_t led_read(struct file *filp, char __user *buf,
  94. size_t size, loff_t *ppos)
  95. {
  96. int count,led_no;
  97. int result;
  98. count = atomic_read(&led_devp->sec_counter);
  99. led_no = atomic_read(&led_devp->led_no);
  100. result = (count<<3)+led_no;
  101. if(put_user(result,(int*)buf))
  102. {
  103. return -EFAULT;
  104. }
  105. else
  106. {
  107. return sizeof(int);
  108. }
  109. }
  110. static const struct file_operations led_fops =
  111. {
  112. .owner = THIS_MODULE,
  113. .read = led_read,
  114. .open = led_open,
  115. .release = led_release,
  116. };
  117. static void led_setup_cdev(struct led_dev *dev, int index)
  118. {
  119. int err,devno = MKDEV(led_major,index);
  120. cdev_init(&dev->cdev,&led_fops);
  121. dev->cdev.owner = THIS_MODULE;
  122. err = cdev_add(&dev->cdev,devno,1);
  123. if(err)
  124. {
  125. printk(KERN_NOTICE "Error %d adding %d\n",err,index);
  126. }
  127. }
  128. static int led_init(void)
  129. {
  130. int result;
  131. dev_t devno = MKDEV(led_major,0); //獲取設備號
  132. /*注冊設備*/
  133. if(led_major)
  134. result = register_chrdev_region(devno,1,"led");
  135. else
  136. {
  137. result = alloc_chrdev_region(&devno,0,1,"led");
  138. led_major = MAJOR(devno);
  139. }
  140. if(result<0)
  141. {
  142. printk("register failed!");
  143. return result;
  144. }
  145. led_devp =(struct led_dev*)kmalloc(sizeof(struct led_dev),GFP_KERNEL);
  146. if(!led_devp)
  147. {
  148. result = -ENOMEM;
  149. unregister_chrdev_region(devno,1);
  150. }
  151. memset(led_devp, 0 ,sizeof(struct led_dev));
  152. led_setup_cdev(led_devp,0);
  153. /*配置IO口*/
  154. s3c2410_gpio_cfgpin(LED1_PIN,S3C2410_GPIO_OUTPUT);
  155. s3c2410_gpio_cfgpin(LED2_PIN,S3C2410_GPIO_OUTPUT);
  156. s3c2410_gpio_cfgpin(LED3_PIN,S3C2410_GPIO_OUTPUT);
  157. s3c2410_gpio_cfgpin(LED4_PIN,S3C2410_GPIO_OUTPUT);
  158. /*初始化IO電平*/
  159. s3c2410_gpio_setpin(LED1_PIN,LED_OFF);
  160. s3c2410_gpio_setpin(LED2_PIN,LED_OFF);
  161. s3c2410_gpio_setpin(LED3_PIN,LED_OFF);
  162. s3c2410_gpio_setpin(LED4_PIN,LED_OFF);
  163. return 0;
  164. }
  165. static void led_exit(void)
  166. {
  167. cdev_del(&led_devp->cdev);
  168. kfree(led_devp);
  169. unregister_chrdev_region(MKDEV(led_major,0),1);
  170. }
  171. MODULE_LICENSE("GPL");
  172. MODULE_AUTHOR("Vanbreaker");
  173. module_init(led_init);
  174. module_exit(led_exit);
Copyright © Linux教程網 All Rights Reserved