interrupt.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018/10/01 Bernard The first version
  9. * 2018/12/27 Jesven Change irq enable/disable to cpu0
  10. */
  11. #include <rthw.h>
  12. #include "tick.h"
  13. #include <plic.h>
  14. #include <clint.h>
  15. #include <interrupt.h>
  16. #define CPU_NUM 2
  17. #define MAX_HANDLERS IRQN_MAX
  18. static struct rt_irq_desc irq_desc[MAX_HANDLERS];
  19. static rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector, void *param)
  20. {
  21. rt_kprintf("UN-handled interrupt %d occurred!!!\n", vector);
  22. return RT_NULL;
  23. }
  24. int rt_hw_clint_ipi_enable(void)
  25. {
  26. /* Set the Machine-Software bit in MIE */
  27. set_csr(mie, MIP_MSIP);
  28. return 0;
  29. }
  30. int rt_hw_clint_ipi_disable(void)
  31. {
  32. /* Clear the Machine-Software bit in MIE */
  33. clear_csr(mie, MIP_MSIP);
  34. return 0;
  35. }
  36. int rt_hw_plic_irq_enable(plic_irq_t irq_number)
  37. {
  38. unsigned long core_id = 0;
  39. /* Check parameters */
  40. if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
  41. return -1;
  42. /* Get current enable bit array by IRQ number */
  43. uint32_t current = plic->target_enables.target[core_id].enable[irq_number / 32];
  44. /* Set enable bit in enable bit array */
  45. current |= (uint32_t)1 << (irq_number % 32);
  46. /* Write back the enable bit array */
  47. plic->target_enables.target[core_id].enable[irq_number / 32] = current;
  48. return 0;
  49. }
  50. int rt_hw_plic_irq_disable(plic_irq_t irq_number)
  51. {
  52. unsigned long core_id = 0;
  53. /* Check parameters */
  54. if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
  55. return -1;
  56. /* Get current enable bit array by IRQ number */
  57. uint32_t current = plic->target_enables.target[core_id].enable[irq_number / 32];
  58. /* Clear enable bit in enable bit array */
  59. current &= ~((uint32_t)1 << (irq_number % 32));
  60. /* Write back the enable bit array */
  61. plic->target_enables.target[core_id].enable[irq_number / 32] = current;
  62. return 0;
  63. }
  64. /**
  65. * This function will initialize hardware interrupt
  66. */
  67. void rt_hw_interrupt_init(void)
  68. {
  69. int idx;
  70. int cpuid;
  71. cpuid = current_coreid();
  72. /* Disable all interrupts for the current core. */
  73. for (idx = 0; idx < ((PLIC_NUM_SOURCES + 32u) / 32u); idx ++)
  74. plic->target_enables.target[cpuid].enable[idx] = 0;
  75. /* Set priorities to zero. */
  76. for (idx = 0; idx < PLIC_NUM_SOURCES; idx++)
  77. plic->source_priorities.priority[idx] = 0;
  78. /* Set the threshold to zero. */
  79. plic->targets.target[cpuid].priority_threshold = 0;
  80. /* init exceptions table */
  81. for (idx = 0; idx < MAX_HANDLERS; idx++)
  82. {
  83. rt_hw_interrupt_mask(idx);
  84. irq_desc[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle;
  85. irq_desc[idx].param = RT_NULL;
  86. #ifdef RT_USING_INTERRUPT_INFO
  87. rt_snprintf(irq_desc[idx].name, RT_NAME_MAX - 1, "default");
  88. irq_desc[idx].counter = 0;
  89. #endif
  90. }
  91. /* Enable machine external interrupts. */
  92. set_csr(mie, MIP_MEIP);
  93. }
  94. void rt_hw_scondary_interrupt_init(void)
  95. {
  96. int idx;
  97. int cpuid;
  98. cpuid = current_coreid();
  99. /* Disable all interrupts for the current core. */
  100. for (idx = 0; idx < ((PLIC_NUM_SOURCES + 32u) / 32u); idx ++)
  101. plic->target_enables.target[cpuid].enable[idx] = 0;
  102. /* Set the threshold to zero. */
  103. plic->targets.target[cpuid].priority_threshold = 0;
  104. /* Enable machine external interrupts. */
  105. set_csr(mie, MIP_MEIP);
  106. }
  107. /**
  108. * This function will mask a interrupt.
  109. * @param vector the interrupt number
  110. */
  111. void rt_hw_interrupt_mask(int vector)
  112. {
  113. rt_hw_plic_irq_disable(vector);
  114. }
  115. /**
  116. * This function will un-mask a interrupt.
  117. * @param vector the interrupt number
  118. */
  119. void rt_hw_interrupt_umask(int vector)
  120. {
  121. plic_set_priority(vector, 1);
  122. rt_hw_plic_irq_enable(vector);
  123. }
  124. /**
  125. * This function will install a interrupt service routine to a interrupt.
  126. * @param vector the interrupt number
  127. * @param new_handler the interrupt service routine to be installed
  128. * @param old_handler the old interrupt service routine
  129. */
  130. rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
  131. void *param, const char *name)
  132. {
  133. rt_isr_handler_t old_handler = RT_NULL;
  134. if(vector < MAX_HANDLERS)
  135. {
  136. old_handler = irq_desc[vector].handler;
  137. if (handler != RT_NULL)
  138. {
  139. irq_desc[vector].handler = (rt_isr_handler_t)handler;
  140. irq_desc[vector].param = param;
  141. #ifdef RT_USING_INTERRUPT_INFO
  142. rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name);
  143. irq_desc[vector].counter = 0;
  144. #endif
  145. }
  146. }
  147. return old_handler;
  148. }
  149. RT_WEAK
  150. void plic_irq_handle(plic_irq_t irq)
  151. {
  152. rt_kprintf("UN-handled interrupt %d occurred!!!\n", irq);
  153. return ;
  154. }
  155. uintptr_t handle_irq_m_ext(uintptr_t cause, uintptr_t epc)
  156. {
  157. /*
  158. * After the highest-priority pending interrupt is claimed by a target
  159. * and the corresponding IP bit is cleared, other lower-priority
  160. * pending interrupts might then become visible to the target, and so
  161. * the PLIC EIP bit might not be cleared after a claim. The interrupt
  162. * handler can check the local meip/heip/seip/ueip bits before exiting
  163. * the handler, to allow more efficient service of other interrupts
  164. * without first restoring the interrupted context and taking another
  165. * interrupt trap.
  166. */
  167. if (read_csr(mip) & MIP_MEIP)
  168. {
  169. /* Get current core id */
  170. uint64_t core_id = current_coreid();
  171. /* Get primitive interrupt enable flag */
  172. uint64_t ie_flag = read_csr(mie);
  173. /* Get current IRQ num */
  174. uint32_t int_num = plic->targets.target[core_id].claim_complete;
  175. /* Get primitive IRQ threshold */
  176. uint32_t int_threshold = plic->targets.target[core_id].priority_threshold;
  177. /* Set new IRQ threshold = current IRQ threshold */
  178. plic->targets.target[core_id].priority_threshold = plic->source_priorities.priority[int_num];
  179. /* Disable software interrupt and timer interrupt */
  180. clear_csr(mie, MIP_MTIP | MIP_MSIP);
  181. if (irq_desc[int_num].handler == (rt_isr_handler_t)rt_hw_interrupt_handle)
  182. {
  183. /* default handler, route to kendryte bsp plic driver */
  184. plic_irq_handle(int_num);
  185. }
  186. else if (irq_desc[int_num].handler)
  187. {
  188. irq_desc[int_num].handler(int_num, irq_desc[int_num].param);
  189. }
  190. /* Perform IRQ complete */
  191. plic->targets.target[core_id].claim_complete = int_num;
  192. /* Set MPIE and MPP flag used to MRET instructions restore MIE flag */
  193. set_csr(mstatus, MSTATUS_MPIE | MSTATUS_MPP);
  194. /* Restore primitive interrupt enable flag */
  195. write_csr(mie, ie_flag);
  196. /* Restore primitive IRQ threshold */
  197. plic->targets.target[core_id].priority_threshold = int_threshold;
  198. }
  199. return epc;
  200. }
  201. uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc)
  202. {
  203. int cause = mcause & CAUSE_MACHINE_IRQ_REASON_MASK;
  204. if (mcause & (1UL << 63))
  205. {
  206. switch (cause)
  207. {
  208. case IRQ_M_SOFT:
  209. {
  210. uint64_t core_id = current_coreid();
  211. clint_ipi_clear(core_id);
  212. rt_schedule();
  213. }
  214. break;
  215. case IRQ_M_EXT:
  216. handle_irq_m_ext(mcause, epc);
  217. break;
  218. case IRQ_M_TIMER:
  219. tick_isr();
  220. break;
  221. }
  222. }
  223. else
  224. {
  225. rt_thread_t tid;
  226. extern long list_thread();
  227. rt_hw_interrupt_disable();
  228. tid = rt_thread_self();
  229. rt_kprintf("\nException:\n");
  230. switch (cause)
  231. {
  232. case CAUSE_MISALIGNED_FETCH:
  233. rt_kprintf("Instruction address misaligned");
  234. break;
  235. case CAUSE_FAULT_FETCH:
  236. rt_kprintf("Instruction access fault");
  237. break;
  238. case CAUSE_ILLEGAL_INSTRUCTION:
  239. rt_kprintf("Illegal instruction");
  240. break;
  241. case CAUSE_BREAKPOINT:
  242. rt_kprintf("Breakpoint");
  243. break;
  244. case CAUSE_MISALIGNED_LOAD:
  245. rt_kprintf("Load address misaligned");
  246. break;
  247. case CAUSE_FAULT_LOAD:
  248. rt_kprintf("Load access fault");
  249. break;
  250. case CAUSE_MISALIGNED_STORE:
  251. rt_kprintf("Store address misaligned");
  252. break;
  253. case CAUSE_FAULT_STORE:
  254. rt_kprintf("Store access fault");
  255. break;
  256. case CAUSE_USER_ECALL:
  257. rt_kprintf("Environment call from U-mode");
  258. break;
  259. case CAUSE_SUPERVISOR_ECALL:
  260. rt_kprintf("Environment call from S-mode");
  261. break;
  262. case CAUSE_HYPERVISOR_ECALL:
  263. rt_kprintf("Environment call from H-mode");
  264. break;
  265. case CAUSE_MACHINE_ECALL:
  266. rt_kprintf("Environment call from M-mode");
  267. break;
  268. default:
  269. rt_kprintf("Uknown exception : %08lX", cause);
  270. break;
  271. }
  272. rt_kprintf("\n");
  273. rt_kprintf("exception pc => 0x%08x\n", epc);
  274. rt_kprintf("current thread: %.*s\n", RT_NAME_MAX, tid->name);
  275. #ifdef RT_USING_FINSH
  276. list_thread();
  277. #endif
  278. while(1);
  279. }
  280. return epc;
  281. }