1
0

interrupt.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /**
  2. * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. ******************************************************************************
  6. * @file interrupt.c
  7. * @version V0.1
  8. * @brief interrupt interface for rt-thread
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2019-05-08 Cliff.Chen first implementation
  13. *
  14. ******************************************************************************
  15. */
  16. #include <rthw.h>
  17. #include "hal_base.h"
  18. #if defined(ARCH_ARM_CORTEX_M0) || defined(ARCH_ARM_CORTEX_M3) || defined(ARCH_ARM_CORTEX_M4) || defined(ARCH_ARM_CORTEX_M7)
  19. #if EXT_INTERRUPT
  20. struct rk_intc
  21. {
  22. void *intc_base;
  23. rt_isr_handler_t irq_handler;
  24. };
  25. static rt_isr_handler_t ext_vector[NUM_EXT_INTERRUPTS];
  26. static void intc_irq_dispatch(void *intc, uint32_t offset)
  27. {
  28. uint32_t i, irq_no;
  29. for (i = 0; i < NUM_EXT_INTERRUPTS; i++)
  30. {
  31. if (HAL_INTC_GetFinalStatus(intc, i))
  32. {
  33. irq_no = i + offset * NUM_INT_PER_CONTROLLER;
  34. ext_vector[irq_no](NUM_INTERRUPTS + irq_no, NULL);
  35. }
  36. }
  37. }
  38. #define DEFINE_RK_INTC_IRQ(ID) \
  39. static void rk_intc##ID##_irq_dispatch(int irq, void *param); \
  40. static struct rk_intc rk_intc##ID = \
  41. { \
  42. .intc_base = INTC##ID, \
  43. .irq_handler = rk_intc##ID##_irq_dispatch, \
  44. }; \
  45. static void rk_intc##ID##_irq_dispatch(int irq, void *param) \
  46. { \
  47. intc_irq_dispatch(INTC##ID, ID); \
  48. }
  49. #ifdef INTC0
  50. DEFINE_RK_INTC_IRQ(0);
  51. #endif
  52. #ifdef INTC1
  53. DEFINE_RK_INTC_IRQ(1);
  54. #endif
  55. #ifdef INTC2
  56. DEFINE_RK_INTC_IRQ(2);
  57. #endif
  58. #ifdef INTC3
  59. DEFINE_RK_INTC_IRQ(3);
  60. #endif
  61. static struct rk_intc *rk_intc_table[] =
  62. {
  63. #ifdef INTC0
  64. &rk_intc0,
  65. #endif
  66. #ifdef INTC1
  67. &rk_intc1,
  68. #endif
  69. #ifdef INTC2
  70. &rk_intc2,
  71. #endif
  72. #ifdef INTC3
  73. &rk_intc3,
  74. #endif
  75. };
  76. static void rk_intc_init(void)
  77. {
  78. uint32_t i;
  79. memset(ext_vector, 0, sizeof(ext_vector));
  80. for (i = 0; i < HAL_ARRAY_SIZE(rk_intc_table); i++)
  81. {
  82. HAL_NVIC_SetIRQHandler(INTC0_IRQn + i, (NVIC_IRQHandler)rk_intc_table[i]->irq_handler);
  83. HAL_NVIC_EnableIRQ(INTC0_IRQn + i);
  84. HAL_INTC_EnableAllRQ(rk_intc_table[i]->intc_base);
  85. }
  86. }
  87. static void rk_intc_mask(uint32_t vector)
  88. {
  89. uint32_t intc, irq;
  90. if (vector >= TOTAL_INTERRUPTS)
  91. return;
  92. if (vector < NUM_INTERRUPTS)
  93. HAL_NVIC_DisableIRQ(vector);
  94. else
  95. {
  96. intc = (vector - NUM_INTERRUPTS) / NUM_INT_PER_CONTROLLER;
  97. irq = (vector - NUM_INTERRUPTS) % NUM_INT_PER_CONTROLLER;
  98. if (intc >= HAL_ARRAY_SIZE(rk_intc_table))
  99. return;
  100. HAL_INTC_MaskIRQ(rk_intc_table[intc]->intc_base, irq);
  101. }
  102. }
  103. static void rk_intc_unmask(uint32_t vector)
  104. {
  105. uint32_t intc, irq;
  106. if (vector >= TOTAL_INTERRUPTS)
  107. return;
  108. if (vector < NUM_INTERRUPTS)
  109. HAL_NVIC_EnableIRQ(vector);
  110. else
  111. {
  112. intc = (vector - NUM_INTERRUPTS) / NUM_INT_PER_CONTROLLER;
  113. irq = (vector - NUM_INTERRUPTS) % NUM_INT_PER_CONTROLLER;
  114. if (intc >= HAL_ARRAY_SIZE(rk_intc_table))
  115. return;
  116. HAL_INTC_UnmaskIRQ(rk_intc_table[intc]->intc_base, irq);
  117. }
  118. }
  119. #endif /* end of EXT_INTERRUPT */
  120. #ifdef RT_USING_PROF_IRQ
  121. #define IRQ_AVG_COUNT 200
  122. struct irq_summry
  123. {
  124. uint32_t count;
  125. uint32_t start;
  126. uint32_t time_total;
  127. uint32_t time_avg;
  128. uint32_t time_max;
  129. };
  130. static struct irq_summry g_irq_prof[TOTAL_INTERRUPTS];
  131. static void irq_enter_hook(void)
  132. {
  133. uint32_t irq;
  134. irq = __get_IPSR() - 16;
  135. g_irq_prof[irq].count++;
  136. g_irq_prof[irq].start = HAL_TIMER_GetCount(SYS_TIMER);
  137. }
  138. static void irq_leave_hook(void)
  139. {
  140. uint32_t time_cur, end, irq;
  141. irq = __get_IPSR() - 16;
  142. end = HAL_TIMER_GetCount(SYS_TIMER);
  143. if (end < g_irq_prof[irq].start)
  144. end += PLL_INPUT_OSC_RATE;
  145. time_cur = end - g_irq_prof[irq].start;
  146. g_irq_prof[irq].time_total += time_cur;
  147. g_irq_prof[irq].time_max =
  148. g_irq_prof[irq].time_max > time_cur ? g_irq_prof[irq].time_max : time_cur;
  149. if (g_irq_prof[irq].count > 0 &&
  150. g_irq_prof[irq].count % IRQ_AVG_COUNT == 0)
  151. {
  152. g_irq_prof[irq].time_avg = g_irq_prof[irq].time_total / IRQ_AVG_COUNT;
  153. g_irq_prof[irq].time_total = 0;
  154. }
  155. }
  156. static void dump_irq_summry(int argc, char **argv)
  157. {
  158. uint32_t i;
  159. rt_kprintf("IRQ COUNT AVG MAX\n");
  160. for (i = 0; i < NUM_INTERRUPTS; i++)
  161. {
  162. rt_kprintf("%03d %08d %08d %08d\n", i, g_irq_prof[i].count,
  163. g_irq_prof[i].time_avg,
  164. g_irq_prof[i].time_max);
  165. }
  166. }
  167. #ifdef RT_USING_FINSH
  168. #include <finsh.h>
  169. MSH_CMD_EXPORT(dump_irq_summry, dump irq summry);
  170. #endif
  171. #endif /* end of RT_USING_PROF_IRQ */
  172. void rt_hw_interrupt_init(void)
  173. {
  174. uint32_t i;
  175. for (i = 0; i < NUM_INTERRUPTS; i++)
  176. {
  177. HAL_NVIC_SetPriority(i, NVIC_PERIPH_PRIO_DEFAULT, NVIC_PERIPH_SUB_PRIO_DEFAULT);
  178. }
  179. #if EXT_INTERRUPT
  180. rk_intc_init();
  181. #endif
  182. #ifdef RT_USING_PROF_IRQ
  183. rt_interrupt_enter_sethook(irq_enter_hook);
  184. rt_interrupt_leave_sethook(irq_leave_hook);
  185. #endif
  186. }
  187. void rt_hw_interrupt_mask(int vector)
  188. {
  189. #if EXT_INTERRUPT
  190. rk_intc_mask(vector);
  191. #else
  192. HAL_NVIC_DisableIRQ(vector);
  193. #endif
  194. }
  195. void rt_hw_interrupt_umask(int vector)
  196. {
  197. #if EXT_INTERRUPT
  198. rk_intc_unmask(vector);
  199. #else
  200. HAL_NVIC_EnableIRQ(vector);
  201. #endif
  202. }
  203. rt_isr_handler_t rt_hw_interrupt_install(int vector,
  204. rt_isr_handler_t handler,
  205. void *param,
  206. const char *name)
  207. {
  208. #if EXT_INTERRUPT
  209. if (vector < NUM_INTERRUPTS)
  210. HAL_NVIC_SetIRQHandler(vector, (NVIC_IRQHandler)handler);
  211. else
  212. ext_vector[vector - NUM_INTERRUPTS] = handler;
  213. #else
  214. HAL_NVIC_SetIRQHandler(vector, (NVIC_IRQHandler)handler);
  215. #endif
  216. return handler;
  217. }
  218. #endif /* end of defined(ARCH_ARM_CORTEX_M0) || defined(ARCH_ARM_CORTEX_M3) || defined(ARCH_ARM_CORTEX_M4) || defined(ARCH_ARM_CORTEX_M7) */