interrupt.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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. */
  10. #include <rthw.h>
  11. #include "tick.h"
  12. #include <plic.h>
  13. #include <clint.h>
  14. #include <interrupt.h>
  15. #define CPU_NUM 2
  16. #define MAX_HANDLERS IRQN_MAX
  17. static struct rt_irq_desc irq_desc[CPU_NUM][MAX_HANDLERS];
  18. static rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector, void *param)
  19. {
  20. rt_kprintf("UN-handled interrupt %d occurred!!!\n", vector);
  21. return RT_NULL;
  22. }
  23. /**
  24. * This function will initialize hardware interrupt
  25. */
  26. void rt_hw_interrupt_init(void)
  27. {
  28. int idx;
  29. int cpuid;
  30. cpuid = current_coreid();
  31. /* Disable all interrupts for the current core. */
  32. for (idx = 0; idx < ((PLIC_NUM_SOURCES + 32u) / 32u); idx ++)
  33. plic->target_enables.target[cpuid].enable[idx] = 0;
  34. /* Set priorities to zero. */
  35. for (idx = 0; idx < PLIC_NUM_SOURCES; idx++)
  36. plic->source_priorities.priority[idx] = 0;
  37. /* Set the threshold to zero. */
  38. plic->targets.target[cpuid].priority_threshold = 0;
  39. /* init exceptions table */
  40. for (idx = 0; idx < MAX_HANDLERS; idx++)
  41. {
  42. rt_hw_interrupt_mask(idx);
  43. irq_desc[cpuid][idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle;
  44. irq_desc[cpuid][idx].param = RT_NULL;
  45. #ifdef RT_USING_INTERRUPT_INFO
  46. rt_snprintf(irq_desc[cpuid][idx].name, RT_NAME_MAX - 1, "default");
  47. irq_desc[idx][cpuid].counter = 0;
  48. #endif
  49. }
  50. /* Enable machine external interrupts. */
  51. set_csr(mie, MIP_MEIP);
  52. }
  53. /**
  54. * This function will mask a interrupt.
  55. * @param vector the interrupt number
  56. */
  57. void rt_hw_interrupt_mask(int vector)
  58. {
  59. plic_irq_disable(vector);
  60. }
  61. /**
  62. * This function will un-mask a interrupt.
  63. * @param vector the interrupt number
  64. */
  65. void rt_hw_interrupt_umask(int vector)
  66. {
  67. plic_set_priority(vector, 1);
  68. plic_irq_enable(vector);
  69. }
  70. /**
  71. * This function will install a interrupt service routine to a interrupt.
  72. * @param vector the interrupt number
  73. * @param new_handler the interrupt service routine to be installed
  74. * @param old_handler the old interrupt service routine
  75. */
  76. rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
  77. void *param, const char *name)
  78. {
  79. int cpuid;
  80. rt_isr_handler_t old_handler = RT_NULL;
  81. cpuid = current_coreid();
  82. if(vector < MAX_HANDLERS)
  83. {
  84. old_handler = irq_desc[cpuid][vector].handler;
  85. if (handler != RT_NULL)
  86. {
  87. irq_desc[cpuid][vector].handler = (rt_isr_handler_t)handler;
  88. irq_desc[cpuid][vector].param = param;
  89. #ifdef RT_USING_INTERRUPT_INFO
  90. rt_snprintf(irq_desc[cpuid][vector].name, RT_NAME_MAX - 1, "%s", name);
  91. irq_desc[cpuid][vector].counter = 0;
  92. #endif
  93. }
  94. }
  95. return old_handler;
  96. }
  97. RT_WEAK
  98. void plic_irq_handle(plic_irq_t irq)
  99. {
  100. rt_kprintf("UN-handled interrupt %d occurred!!!\n", irq);
  101. return ;
  102. }
  103. uintptr_t handle_irq_m_ext(uintptr_t cause, uintptr_t epc)
  104. {
  105. /*
  106. * After the highest-priority pending interrupt is claimed by a target
  107. * and the corresponding IP bit is cleared, other lower-priority
  108. * pending interrupts might then become visible to the target, and so
  109. * the PLIC EIP bit might not be cleared after a claim. The interrupt
  110. * handler can check the local meip/heip/seip/ueip bits before exiting
  111. * the handler, to allow more efficient service of other interrupts
  112. * without first restoring the interrupted context and taking another
  113. * interrupt trap.
  114. */
  115. if (read_csr(mip) & MIP_MEIP)
  116. {
  117. /* Get current core id */
  118. uint64_t core_id = current_coreid();
  119. /* Get primitive interrupt enable flag */
  120. uint64_t ie_flag = read_csr(mie);
  121. /* Get current IRQ num */
  122. uint32_t int_num = plic->targets.target[core_id].claim_complete;
  123. /* Get primitive IRQ threshold */
  124. uint32_t int_threshold = plic->targets.target[core_id].priority_threshold;
  125. /* Set new IRQ threshold = current IRQ threshold */
  126. plic->targets.target[core_id].priority_threshold = plic->source_priorities.priority[int_num];
  127. /* Disable software interrupt and timer interrupt */
  128. clear_csr(mie, MIP_MTIP | MIP_MSIP);
  129. if (irq_desc[core_id][int_num].handler == (rt_isr_handler_t)rt_hw_interrupt_handle)
  130. {
  131. /* default handler, route to kendryte bsp plic driver */
  132. plic_irq_handle(int_num);
  133. }
  134. else if (irq_desc[core_id][int_num].handler)
  135. {
  136. irq_desc[core_id][int_num].handler(int_num, irq_desc[core_id][int_num].param);
  137. }
  138. /* Perform IRQ complete */
  139. plic->targets.target[core_id].claim_complete = int_num;
  140. /* Set MPIE and MPP flag used to MRET instructions restore MIE flag */
  141. set_csr(mstatus, MSTATUS_MPIE | MSTATUS_MPP);
  142. /* Restore primitive interrupt enable flag */
  143. write_csr(mie, ie_flag);
  144. /* Restore primitive IRQ threshold */
  145. plic->targets.target[core_id].priority_threshold = int_threshold;
  146. }
  147. else
  148. {
  149. rt_kprintf("unhandled trap!\n");
  150. }
  151. return epc;
  152. }
  153. uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc)
  154. {
  155. int cause = mcause & CAUSE_MACHINE_IRQ_REASON_MASK;
  156. if (mcause & (1UL << 63))
  157. {
  158. switch (cause)
  159. {
  160. case IRQ_M_SOFT:
  161. break;
  162. case IRQ_M_EXT:
  163. handle_irq_m_ext(mcause, epc);
  164. break;
  165. case IRQ_M_TIMER:
  166. tick_isr();
  167. break;
  168. }
  169. }
  170. else
  171. {
  172. rt_thread_t tid;
  173. extern long list_thread();
  174. rt_hw_interrupt_disable();
  175. tid = rt_thread_self();
  176. rt_kprintf("\n");
  177. rt_kprintf("unhandled trap, epc => 0x%08x, INT[%d]\n", epc, rt_interrupt_get_nest());
  178. rt_kprintf("current thread: %.*s\n", RT_NAME_MAX, tid->name);
  179. #ifdef RT_USING_FINSH
  180. list_thread();
  181. #endif
  182. while(1);
  183. }
  184. return epc;
  185. }