pcDuino Linux驱动开发四 -- 最简单的中断驱动

作者: tjcfeng
上传时间为: 2014-11-30 11:13 PM
2014-11-30
阅读:

基于前面提到的最精简的框架,中断程序只是多了一个irq注册和响应的代码。

需要增加的函数有:

request_irq //请求注册irq
free_irq //释放请求
和一个自定义的irq响应函数。

当然,为了程序能够真正完成工作,还需要一个阻塞响应机制,以便用户程序能够等到中断的到达。
这里同样使用了最简单的方式,增加的函数:

DECLARE_COMPLETION(MSG); //linux内核定义好的宏,给一个变量名称即可
init_completion(&MSG); //初始化
wait_for_completion(&MSG); //阻塞函数
complete(&MSG); //打断阻塞的函数

下面上代码,对照之前的GPIO框架,可以很清晰地看出区别:

  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/fs.h>
  4. #include <linux/cdev.h>
  5. #include <linux/device.h>
  6. #include <linux/wait.h>
  7. #include <linux/delay.h>
  8. #include <asm/io.h>
  9. #include <asm/uaccess.h>
  10. #include <linux/interrupt.h>
  11. #include "../A10.h"
  12. /**********************************************************************/
  13. #define KEY_IRQ 28
  14. #define KEY_BACK 17
  15. #define KEY_HOME 19
  16. #define KEY_MENU 18
  17. #define KEY_BACK_BIT 0x20000 //(0x1 << 17)
  18. #define KEY_MENU_BIT 0x40000 //(0x1 << 18)
  19. #define KEY_HOME_BIT 0x80000 //(0x1 << 19)
  20. #define KEY_DOWN 0
  21. #define KEY_UP 1
  22. volatile static unsigned long* REG_PH_CFG2;
  23. volatile static unsigned long* REG_PH_PULL1;
  24. volatile static unsigned long* REG_PIO_INT_CFG2;
  25. volatile static unsigned long* REG_PIO_INT_CTL;
  26. volatile static unsigned long* REG_PIO_INT_STATUS;
  27. volatile static unsigned long* REG_PH_DAT;
  28. /*volatile static unsigned long* REG_INTC_IRQ_PEND_REG0;
  29. volatile static unsigned long* REG_INTC_IRQ_TYPE_SEL0;
  30. volatile static unsigned long* REG_INTC_EN_REG0;
  31. volatile static unsigned long* REG_INTC_MASK_REG0;*/
  32. static int Inited = 0;
  33. DECLARE_COMPLETION(MSG);
  34. static unsigned char KeyFlag = 0;
  35. static unsigned char KeyHL = 255;
  36. static irqreturn_t KEY_ISR(int irq, void* dev_id)
  37. {
  38. unsigned int State, Data;
  39. State = *REG_PIO_INT_STATUS;
  40. *REG_PIO_INT_STATUS |= (KEY_HOME_BIT + KEY_MENU_BIT + KEY_BACK_BIT); //Clear INT Pending
  41. mdelay(1);
  42. *REG_PH_CFG2 &= ~((0x7 << 12) + (0x7 << 8) + (0x7 << 4)); //Input
  43. Data = *REG_PH_DAT;
  44. *REG_PH_CFG2 |= ((0x6 << 12) + (0x6 << 8) + (0x6 << 4)); //EINT
  45. //printk("IRQ State - %u ___ IRQ Data - %u\n", State, Data);
  46. if ((State & KEY_BACK_BIT) == KEY_BACK_BIT )
  47. {
  48. KeyFlag = KEY_BACK;
  49. if ((Data & KEY_BACK_BIT) == KEY_BACK_BIT) KeyHL = KEY_UP; else KeyHL = KEY_DOWN;
  50. }
  51. else
  52. if ((State & KEY_MENU_BIT) == KEY_MENU_BIT)
  53. {
  54. KeyFlag = KEY_MENU;
  55. if ((Data & KEY_MENU_BIT) == KEY_MENU_BIT) KeyHL = KEY_UP; else KeyHL = KEY_DOWN;
  56. }
  57. else
  58. if ((State & KEY_HOME_BIT) == KEY_HOME_BIT)
  59. {
  60. KeyFlag = KEY_HOME;
  61. if ((Data & KEY_HOME_BIT) == KEY_HOME_BIT) KeyHL = KEY_UP; else KeyHL = KEY_DOWN;
  62. }
  63. if ((KeyFlag != 0) && (KeyHL != 255)) complete(&MSG);
  64. return IRQ_HANDLED;
  65. }
  66. static int KEY_open(struct inode* n, struct file* f)
  67. {
  68. int Result = 0;
  69. Inited++;
  70. if (Inited > 1)
  71. {
  72. return 0;
  73. }
  74. REG_PH_CFG2 = (volatile unsigned long*) ioremap(PH_CFG2, 4);
  75. REG_PH_PULL1 = (volatile unsigned long*) ioremap(PH_PULL1, 4);
  76. REG_PIO_INT_CFG2 = (volatile unsigned long*) ioremap(PIO_INT_CFG2, 4);
  77. REG_PIO_INT_CTL= (volatile unsigned long*) ioremap(PIO_INT_CTL, 4);
  78. REG_PIO_INT_STATUS = (volatile unsigned long*) ioremap(PIO_INT_STATUS, 4);
  79. REG_PH_DAT = (volatile unsigned long*) ioremap(PH_DAT, 4);
  80. /*REG_INTC_IRQ_PEND_REG0 = (volatile unsigned long*) ioremap(INTC_IRQ_PEND_REG0, 4);
  81. REG_INTC_IRQ_TYPE_SEL0 = (volatile unsigned long*) ioremap(INTC_IRQ_TYPE_SEL0, 4);
  82. REG_INTC_EN_REG0 = (volatile unsigned long*) ioremap(INTC_EN_REG0, 4);
  83. REG_INTC_MASK_REG0 = (volatile unsigned long*) ioremap(INTC_MASK_REG0, 4);*/
  84. *REG_PH_CFG2 &= ~((0x7 << 12) + (0x7 << 8) + (0x7 << 4));
  85. *REG_PH_CFG2 |= ((0x6 << 12) + (0x6 << 8) + (0x6 << 4)); //EINT
  86. *REG_PH_PULL1 &= ~((0x3 << 6) + (0x3 << 4) + (0x3 << 2));
  87. *REG_PH_PULL1 |= ((0x1 << 6) + (0x1 << 4) + (0x1 << 2)); //Pull_UP
  88. *REG_PIO_INT_CFG2 &= ~((0xF << 12) + (0xF << 8) + (0xF << 4));
  89. *REG_PIO_INT_CFG2 |= ((0x4 << 12) + (0x4 << 8) + (0x4<< 4)); //Double Edge
  90. //*REG_PH_DAT |= KEY_HOME_BIT + KEY_MENU_BIT + KEY_BACK_BIT;
  91. //*REG_INTC_IRQ_TYPE_SEL0 &= ~((0x1 << KEY_MENU) + (0x1 << KEY_HOME) + (0x1 << KEY_BACK)); //Is IRQ, not FIQ
  92. //*REG_INTC_EN_REG0 |= ((0x1 << KEY_MENU) + (0x1 << KEY_HOME) + (0x1 << KEY_BACK)); //Enable INT
  93. *REG_PIO_INT_CTL |= ((0x1 << KEY_MENU) + (0x1 << KEY_HOME) + (0x1 << KEY_BACK)); //Enable INT
  94. Result = request_irq(KEY_IRQ, KEY_ISR, IRQF_DISABLED, "KEY", NULL);
  95. if (Result != 0)
  96. {
  97. //printk("Request IRQ file! ErrorCode: %d\n", Result);
  98. free_irq(KEY_IRQ, NULL);
  99. return Result;
  100. }
  101. init_completion(&MSG);
  102. //printk("Open Finished!\n");
  103. return Result;
  104. }
  105. static ssize_t KEY_write(struct file* f, const char __user* buf, size_t len, loff_t* l)
  106. {
  107. unsigned char Buf[2];
  108. if (copy_from_user(&Buf, buf, len)) return -1;
  109. //printk("Write Finished!\n");
  110. return len;
  111. }
  112. static ssize_t KEY_read(struct file* f, char __user* buf, size_t len, loff_t* l)
  113. {
  114. unsigned char Buf[2];
  115. int Len = sizeof(Buf);
  116. wait_for_completion(&MSG);
  117. Buf[0] = KeyFlag;
  118. Buf[1] = KeyHL;
  119. if (copy_to_user(buf, &Buf, sizeof(Buf))) return 0;
  120. KeyFlag = 0;
  121. KeyHL = 255;
  122. //printk("Read Finished!\n");
  123. return Len;
  124. }
  125. static int KEY_close(struct inode* n, struct file* f)
  126. {
  127. Inited--;
  128. if (Inited > 0)
  129. {
  130. return 0;
  131. }
  132. free_irq(KEY_IRQ, NULL);
  133. //remove_wait_queue(&MSG);
  134. iounmap(REG_PH_CFG2);
  135. iounmap(REG_PH_PULL1);
  136. iounmap(REG_PIO_INT_CFG2);
  137. iounmap(REG_PIO_INT_STATUS);
  138. iounmap(REG_PH_DAT);
  139. /*iounmap(REG_INTC_IRQ_PEND_REG0);
  140. iounmap(REG_INTC_IRQ_TYPE_SEL0);
  141. iounmap(REG_INTC_EN_REG0);
  142. iounmap(REG_INTC_MASK_REG0);*/
  143. //printk("Close Finished!\n");
  144. return 0;
  145. }
  146. /**********************************************************************/
  147. #define DEV_NAME "KEY"
  148. #define DEV_COUNT 1
  149. static struct class* pClass;
  150. int major;
  151. static struct file_operations fops =
  152. {
  153. .owner = THIS_MODULE,
  154. .open = KEY_open,
  155. .write = KEY_write,
  156. .read = KEY_read,
  157. .release = KEY_close,
  158. };
  159. static int __init KEY_init(void)
  160. {
  161. major = register_chrdev(0, DEV_NAME, &fops);
  162. pClass = class_create(THIS_MODULE, DEV_NAME);
  163. if (pClass == NULL)
  164. {
  165. unregister_chrdev(major, DEV_NAME);
  166. return -1;
  167. }
  168. device_create(pClass, NULL, MKDEV(major, 0), NULL, DEV_NAME);
  169. //printk("Init Finished!\n");
  170. return 0;
  171. }
  172. static void __exit KEY_exit(void)
  173. {
  174. unregister_chrdev(major, DEV_NAME);
  175. if (pClass)
  176. {
  177. device_destroy(pClass, MKDEV(major, 0));
  178. class_destroy(pClass);
  179. }
  180. //printk("Exit Finished!\n");
  181. }
  182. MODULE_LICENSE("GPL");
  183. MODULE_AUTHOR("LiuYang");
  184. module_init(KEY_init);
  185. module_exit(KEY_exit);

复制代码

Makefile文件同前,改一下文件名.o即可。

测试程序:

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <fcntl.h>
  4. int main(int argc, char **argv)
  5. {
  6. int f;
  7. int I;
  8. int Len;
  9. unsigned char Buf[2];
  10. f = open("/dev/KEY", O_RDWR);
  11. printf("File Handle: %d\n", f);
  12. if (f < 0)
  13. {
  14. printf("Open KEY fail!\n");
  15. return -1;
  16. }
  17. for (I = 0; I < 6; I++)
  18. {
  19. Len = read(f, &Buf, 2);
  20. printf("Len: %d -- Key: %d -- HL: %d\n", Len, Buf[0], Buf[1]);
  21. }
  22. close(f);
  23. return 0;
  24. }

复制代码

这样,测试程序在调用了read之后会阻塞在那里,等待驱动程序中中断的达到。每次按下按键后,程序就继续执行了。wait_for_completion有很多种,可以增加超时之类的来完成自己的要求。

顺便说一下,pcDuino已经占用了这个中断,测试的话,在启动后需要先rmmod sw_interrupt,以保证本程序的运行。

全部评论 ()
条评论
写评论

创建讨论帖子

登录 后参与评论
系统提示