interrupt.c 12 KB

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