interrupt.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. /*
  2. * File : interrupt.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2011-01-13 weety first version
  23. */
  24. #include <rthw.h>
  25. #include "at91sam9g45.h"
  26. #include "interrupt.h"
  27. #define AIC_IRQS 32
  28. #define MAX_HANDLERS (AIC_IRQS + PIN_IRQS)
  29. extern rt_uint32_t rt_interrupt_nest;
  30. /* exception and interrupt handler table */
  31. struct rt_irq_desc irq_desc[MAX_HANDLERS];
  32. rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
  33. rt_uint32_t rt_thread_switch_interrupt_flag;
  34. /* --------------------------------------------------------------------
  35. * Interrupt initialization
  36. * -------------------------------------------------------------------- */
  37. rt_uint32_t at91_extern_irq;
  38. #define is_extern_irq(irq) ((1 << (irq)) & at91_extern_irq)
  39. /*
  40. * The default interrupt priority levels (0 = lowest, 7 = highest).
  41. */
  42. static rt_uint32_t at91sam9g45_default_irq_priority[MAX_HANDLERS] = {
  43. 7, /* Advanced Interrupt Controller - FIQ */
  44. 7, /* System Controller Interrupt */
  45. 1, /* Parallel I/O Controller A, */
  46. 1, /* Parallel I/O Controller B */
  47. 1, /* Parallel I/O Controller C */
  48. 0, /* Parallel I/O Controller D/E */
  49. 5, /* True Random Number Generator */
  50. 5, /* USART 0 */
  51. 5, /* USART 1 */
  52. 0, /* USART 2 */
  53. 2, /* USART 3 */
  54. 6, /* High Speed Multimedia Card Interface 0 */
  55. 5, /* Two-Wire Interface 0 */
  56. 5, /* Two-Wire Interface 1 */
  57. 5, /* Serial Peripheral Interface */
  58. 0, /* Serial Peripheral Interface */
  59. 0, /* Synchronous Serial Controller 0 */
  60. 0, /* Synchronous Serial Controller 1 */
  61. 0, /* Timer Counter 0,1,2,3,4,5 */
  62. 0, /* Pulse Width Modulation Controller */
  63. 2, /* Touch Screen ADC Controller */
  64. 3, /* DMA Controller */
  65. 0, /* USB Host High Speed */
  66. 5, /* LCD Controller */
  67. 5, /* AC97 Controller */
  68. 5, /* Ethernet MAC */
  69. 0, /* Image Sensor Interface */
  70. 0, /* USB Device High Speed */
  71. 0, /* N/A */
  72. 0, /* High Speed Multimedia Card Interface 1 */
  73. 0, /* Reserved */
  74. 0, /* Advanced Interrupt Controller - IRQ */
  75. };
  76. /**
  77. * @addtogroup AT91SAM9G45
  78. */
  79. /*@{*/
  80. void rt_hw_interrupt_mask(int irq);
  81. void rt_hw_interrupt_umask(int irq);
  82. rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector, void *param)
  83. {
  84. rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
  85. return RT_NULL;
  86. }
  87. rt_isr_handler_t at91_gpio_irq_handle(rt_uint32_t bank, void *param)
  88. {
  89. rt_uint32_t isr, irq_n;
  90. AT91PS_PIO pio;
  91. void *parameter;
  92. switch (bank)
  93. {
  94. case 0: pio = AT91C_BASE_PIOA; break;
  95. case 1: pio = AT91C_BASE_PIOB; break;
  96. case 2: pio = AT91C_BASE_PIOC; break;
  97. case 3: pio = AT91C_BASE_PIOD; break;
  98. case 4: pio = AT91C_BASE_PIOE; break;
  99. default: return RT_NULL;
  100. }
  101. irq_n = AIC_IRQS + 32*bank;
  102. isr = readl(pio->PIO_ISR);
  103. isr &= readl(pio->PIO_IMR);
  104. while (isr)
  105. {
  106. if (isr & 1)
  107. {
  108. parameter = irq_desc[irq_n].param;
  109. irq_desc[irq_n].handler(irq_n, parameter);
  110. }
  111. isr >>= 1;
  112. irq_n++;
  113. }
  114. return RT_NULL;
  115. }
  116. unsigned int SpuriousCount = 0;
  117. static void DefaultSpuriousHandler( void )
  118. {
  119. SpuriousCount++;
  120. rt_kprintf("Spurious interrupt %d occured!!!\n", SpuriousCount);
  121. return ;
  122. }
  123. static void DefaultFiqHandler(void)
  124. {
  125. rt_kprintf("Unhandled FIQ occured!!!\n");
  126. while (1);
  127. }
  128. static void DefaultIrqHandler(void)
  129. {
  130. rt_kprintf("Unhandled IRQ %d occured!!!\n", AT91C_BASE_AIC->AIC_ISR);
  131. while (1);
  132. }
  133. /*
  134. * Initialize the AIC interrupt controller.
  135. */
  136. void at91_aic_init(rt_uint32_t *priority)
  137. {
  138. rt_uint32_t i;
  139. /*
  140. * The IVR is used by macro get_irqnr_and_base to read and verify.
  141. * The irq number is NR_AIC_IRQS when a spurious interrupt has occurred.
  142. */
  143. AT91C_BASE_AIC->AIC_SVR[0] = (rt_uint32_t)DefaultFiqHandler;
  144. for (i = 1; i < AIC_IRQS; i++) {
  145. /* Put irq number in Source Vector Register: */
  146. AT91C_BASE_AIC->AIC_SVR[i] = (rt_uint32_t)DefaultIrqHandler; // no-used
  147. /* Active Low interrupt, with the specified priority */
  148. AT91C_BASE_AIC->AIC_SMR[i] = AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE | priority[i];
  149. //AT91C_AIC_SRCTYPE_FALLING
  150. }
  151. /*
  152. * Spurious Interrupt ID in Spurious Vector Register is NR_AIC_IRQS
  153. * When there is no current interrupt, the IRQ Vector Register reads the value stored in AIC_SPU
  154. */
  155. AT91C_BASE_AIC->AIC_SPU = (rt_uint32_t)DefaultSpuriousHandler;
  156. /* Perform 8 End Of Interrupt Command to make sure AIC will not Lock out nIRQ */
  157. for (i = 0; i < 8; i++)
  158. AT91C_BASE_AIC->AIC_EOICR = 0;
  159. /* No debugging in AIC: Debug (Protect) Control Register */
  160. AT91C_BASE_AIC->AIC_DCR = 0;
  161. /* Disable and clear all interrupts initially */
  162. AT91C_BASE_AIC->AIC_IDCR = 0xFFFFFFFF;
  163. AT91C_BASE_AIC->AIC_ICCR = 0xFFFFFFFF;
  164. }
  165. static void at91_gpio_irq_init()
  166. {
  167. int i, idx;
  168. char *name[] = {"PIOA", "PIOB", "PIOC", "PIODE"};
  169. rt_uint32_t aic_pids[] = { AT91C_ID_PIOA, AT91C_ID_PIOB, AT91C_ID_PIOC, AT91C_ID_PIOD_E };
  170. AT91C_BASE_PIOA->PIO_IDR = 0xffffffff;
  171. AT91C_BASE_PIOB->PIO_IDR = 0xffffffff;
  172. AT91C_BASE_PIOC->PIO_IDR = 0xffffffff;
  173. AT91C_BASE_PIOD->PIO_IDR = 0xffffffff;
  174. AT91C_BASE_PIOE->PIO_IDR = 0xffffffff;
  175. for (i = 0; i < 4; i++)
  176. {
  177. idx = aic_pids[i];
  178. irq_desc[idx].handler = (rt_isr_handler_t)at91_gpio_irq_handle;
  179. irq_desc[idx].param = RT_NULL;
  180. #ifdef RT_USING_INTERRUPT_INFO
  181. rt_snprintf(irq_desc[idx].name, RT_NAME_MAX - 1, name[i]);
  182. irq_desc[idx].counter = 0;
  183. #endif
  184. rt_hw_interrupt_umask(idx);
  185. }
  186. }
  187. /**
  188. * This function will initialize hardware interrupt
  189. */
  190. void rt_hw_interrupt_init(void)
  191. {
  192. register rt_uint32_t idx;
  193. rt_uint32_t *priority = at91sam9g45_default_irq_priority;
  194. at91_extern_irq = (1UL << AT91C_ID_IRQ0);
  195. /* Initialize the AIC interrupt controller */
  196. at91_aic_init(priority);
  197. /* init exceptions table */
  198. for(idx=0; idx < MAX_HANDLERS; idx++)
  199. {
  200. irq_desc[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle;
  201. irq_desc[idx].param = RT_NULL;
  202. #ifdef RT_USING_INTERRUPT_INFO
  203. rt_snprintf(irq_desc[idx].name, RT_NAME_MAX - 1, "default");
  204. irq_desc[idx].counter = 0;
  205. #endif
  206. }
  207. at91_gpio_irq_init();
  208. /* init interrupt nest, and context in thread sp */
  209. rt_interrupt_nest = 0;
  210. rt_interrupt_from_thread = 0;
  211. rt_interrupt_to_thread = 0;
  212. rt_thread_switch_interrupt_flag = 0;
  213. }
  214. static void at91_gpio_irq_mask(int irq)
  215. {
  216. rt_uint32_t pin, bank;
  217. AT91PS_PIO pio;
  218. bank = (irq - AIC_IRQS)>>5;
  219. switch (bank)
  220. {
  221. case 0: pio = AT91C_BASE_PIOA; break;
  222. case 1: pio = AT91C_BASE_PIOB; break;
  223. case 2: pio = AT91C_BASE_PIOC; break;
  224. case 3: pio = AT91C_BASE_PIOD; break;
  225. case 4: pio = AT91C_BASE_PIOE; break;
  226. default: return;
  227. }
  228. pin = 1 << ((irq - AIC_IRQS) & 31);
  229. pio->PIO_IDR = pin;
  230. }
  231. /**
  232. * This function will mask a interrupt.
  233. * @param irq the interrupt number
  234. */
  235. void rt_hw_interrupt_mask(int irq)
  236. {
  237. if (irq >= AIC_IRQS)
  238. {
  239. at91_gpio_irq_mask(irq);
  240. }
  241. else
  242. {
  243. /* Disable interrupt on AIC */
  244. AT91C_BASE_AIC->AIC_IDCR = 1 << irq;
  245. }
  246. }
  247. static void at91_gpio_irq_umask(int irq)
  248. {
  249. rt_uint32_t pin, bank;
  250. AT91PS_PIO pio;
  251. bank = (irq - AIC_IRQS)>>5;
  252. switch (bank)
  253. {
  254. case 0: pio = AT91C_BASE_PIOA; break;
  255. case 1: pio = AT91C_BASE_PIOB; break;
  256. case 2: pio = AT91C_BASE_PIOC; break;
  257. case 3: pio = AT91C_BASE_PIOD; break;
  258. case 4: pio = AT91C_BASE_PIOE; break;
  259. default: return;
  260. }
  261. pin = 1 << ((irq - AIC_IRQS) & 31);
  262. pio->PIO_IER = pin;
  263. }
  264. /**
  265. * This function will un-mask a interrupt.
  266. * @param vector the interrupt number
  267. */
  268. void rt_hw_interrupt_umask(int irq)
  269. {
  270. if (irq >= AIC_IRQS)
  271. {
  272. at91_gpio_irq_umask(irq);
  273. }
  274. else
  275. {
  276. /* Enable interrupt on AIC */
  277. AT91C_BASE_AIC->AIC_IECR = 1 << irq;
  278. }
  279. }
  280. /**
  281. * This function will install a interrupt service routine to a interrupt.
  282. * @param vector the interrupt number
  283. * @param handler the interrupt service routine to be installed
  284. * @param param the interrupt service function parameter
  285. * @param name the interrupt name
  286. * @return old handler
  287. */
  288. rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
  289. void *param, const char *name)
  290. {
  291. rt_isr_handler_t old_handler = RT_NULL;
  292. if (vector < MAX_HANDLERS)
  293. {
  294. old_handler = irq_desc[vector].handler;
  295. if (handler != RT_NULL)
  296. {
  297. irq_desc[vector].handler = (rt_isr_handler_t)handler;
  298. irq_desc[vector].param = param;
  299. #ifdef RT_USING_INTERRUPT_INFO
  300. rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name);
  301. irq_desc[vector].counter = 0;
  302. #endif
  303. }
  304. }
  305. return old_handler;
  306. }
  307. /*@}*/
  308. /*
  309. static int at91_aic_set_type(unsigned irq, unsigned type)
  310. {
  311. unsigned int smr, srctype;
  312. switch (type) {
  313. case AT91C_AIC_SRCTYPE_EXT_HIGH_LEVEL:
  314. srctype = AT91C_AIC_SRCTYPE_HIGH;
  315. break;
  316. case AT91C_AIC_SRCTYPE_EXT_POSITIVE_EDGE:
  317. srctype = AT91C_AIC_SRCTYPE_RISING;
  318. break;
  319. case AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE:
  320. // only supported on external interrupts
  321. if ((irq == AT91C_ID_FIQ) || is_extern_irq(irq))
  322. srctype = AT91C_AIC_SRCTYPE_LOW;
  323. else
  324. return -1;
  325. break;
  326. case AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED:
  327. // only supported on external interrupts
  328. if ((irq == AT91C_ID_FIQ) || is_extern_irq(irq))
  329. srctype = AT91C_AIC_SRCTYPE_FALLING;
  330. else
  331. return -1;
  332. break;
  333. default:
  334. return -1;
  335. }
  336. smr = readl(AT91C_AIC_SMR(irq)) & ~AT91C_AIC_SRCTYPE;
  337. AT91C_BASE_AIC->AIC_SMR[irq] = smr | srctype;
  338. return 0;
  339. }
  340. */
  341. rt_uint32_t rt_hw_interrupt_get_active(rt_uint32_t fiq_irq)
  342. {
  343. //volatile rt_uint32_t irqstat;
  344. rt_uint32_t id;
  345. if (fiq_irq == INT_FIQ)
  346. return 0;
  347. //IRQ
  348. /* AIC need this dummy read */
  349. readl(AT91C_AIC_IVR);
  350. /* clear pending register */
  351. id = readl(AT91C_AIC_ISR);
  352. return id;
  353. }
  354. void rt_hw_interrupt_ack(rt_uint32_t fiq_irq, rt_uint32_t id)
  355. {
  356. /* new FIQ generation */
  357. if (fiq_irq == INT_FIQ)
  358. return;
  359. /* new IRQ generation */
  360. // EIOCR must be write any value after interrupt,
  361. // or else can't response next interrupt
  362. AT91C_BASE_AIC->AIC_EOICR = 0x0;
  363. }
  364. void rt_interrupt_dispatch(rt_uint32_t fiq_irq)
  365. {
  366. rt_isr_handler_t isr_func;
  367. rt_uint32_t irq;
  368. void *param;
  369. /* get irq number */
  370. irq = rt_hw_interrupt_get_active(fiq_irq);
  371. /* get interrupt service routine */
  372. isr_func = irq_desc[irq].handler;
  373. param = irq_desc[irq].param;
  374. /* turn to interrupt service routine */
  375. isr_func(irq, param);
  376. rt_hw_interrupt_ack(fiq_irq, irq);
  377. #ifdef RT_USING_INTERRUPT_INFO
  378. irq_desc[irq].counter ++;
  379. #endif
  380. }
  381. #ifdef RT_USING_FINSH
  382. #ifdef RT_USING_INTERRUPT_INFO
  383. void list_irq(void)
  384. {
  385. int irq;
  386. rt_kprintf("number\tcount\tname\n");
  387. for (irq = 0; irq < MAX_HANDLERS; irq++)
  388. {
  389. if (rt_strncmp(irq_desc[irq].name, "default", sizeof("default")))
  390. {
  391. rt_kprintf("%02ld: %10ld %s\n", irq, irq_desc[irq].counter, irq_desc[irq].name);
  392. }
  393. }
  394. }
  395. #include <finsh.h>
  396. FINSH_FUNCTION_EXPORT(list_irq, list system irq);
  397. #ifdef FINSH_USING_MSH
  398. int cmd_list_irq(int argc, char** argv)
  399. {
  400. list_irq();
  401. return 0;
  402. }
  403. FINSH_FUNCTION_EXPORT_ALIAS(cmd_list_irq, __cmd_list_irq, list system irq.);
  404. #endif
  405. #endif
  406. #endif