interrupt.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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. * 2018/10/01 Bernard The first version
  9. * 2018/12/27 Jesven Change irq enable/disable to cpu0
  10. */
  11. #include "tick.h"
  12. #include <plic.h>
  13. #include "encoding.h"
  14. #include "riscv.h"
  15. #include "interrupt.h"
  16. #define CPU_NUM 2
  17. #define MAX_HANDLERS 128
  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(int irq_number)
  37. {
  38. plic_irq_enable(irq_number);
  39. return 0;
  40. }
  41. int rt_hw_plic_irq_disable(int irq_number)
  42. {
  43. plic_irq_disable(irq_number);
  44. return 0;
  45. }
  46. /**
  47. * This function will initialize hardware interrupt
  48. */
  49. void rt_hw_interrupt_init(void)
  50. {
  51. int idx = 0;
  52. /* init exceptions table */
  53. for (idx = 0; idx < MAX_HANDLERS; idx++)
  54. {
  55. //rt_hw_interrupt_mask(idx);
  56. irq_desc[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle;
  57. irq_desc[idx].param = RT_NULL;
  58. #ifdef RT_USING_INTERRUPT_INFO
  59. rt_snprintf(irq_desc[idx].name, RT_NAME_MAX - 1, "default");
  60. irq_desc[idx].counter = 0;
  61. #endif
  62. }
  63. }
  64. /**
  65. * This function will mask a interrupt.
  66. * @param vector the interrupt number
  67. */
  68. void rt_hw_interrupt_mask(int vector)
  69. {
  70. rt_hw_plic_irq_disable(vector);
  71. }
  72. /**
  73. * This function will un-mask a interrupt.
  74. * @param vector the interrupt number
  75. */
  76. void rt_hw_interrupt_umask(int vector)
  77. {
  78. plic_set_priority(vector, 1);
  79. plic_set_threshold(0);
  80. rt_hw_plic_irq_enable(vector);
  81. }
  82. /**
  83. * This function will install a interrupt service routine to a interrupt.
  84. * @param vector the interrupt number
  85. * @param new_handler the interrupt service routine to be installed
  86. * @param old_handler the old interrupt service routine
  87. */
  88. rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
  89. void *param, const char *name)
  90. {
  91. rt_isr_handler_t old_handler = RT_NULL;
  92. if(vector < MAX_HANDLERS)
  93. {
  94. old_handler = irq_desc[vector].handler;
  95. if (handler != RT_NULL)
  96. {
  97. irq_desc[vector].handler = (rt_isr_handler_t)handler;
  98. irq_desc[vector].param = param;
  99. #ifdef RT_USING_INTERRUPT_INFO
  100. rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name);
  101. irq_desc[vector].counter = 0;
  102. #endif
  103. }
  104. }
  105. return old_handler;
  106. }
  107. RT_WEAK
  108. void plic_irq_handle(int irq)
  109. {
  110. rt_kprintf("UN-handled interrupt %d occurred!!!\n", irq);
  111. return ;
  112. }
  113. void dump_regs(struct rt_hw_stack_frame *regs)
  114. {
  115. rt_kprintf("--------------Dump Registers-----------------\n");
  116. rt_kprintf("Function Registers:\n");
  117. rt_kprintf("\tra(x1) = 0x%p\tuser_sp = 0x%p\n",regs -> ra,regs -> user_sp_exc_stack);
  118. rt_kprintf("\tgp(x3) = 0x%p\ttp(x4) = 0x%p\n",regs -> gp,regs -> tp);
  119. rt_kprintf("Temporary Registers:\n");
  120. rt_kprintf("\tt0(x5) = 0x%p\tt1(x6) = 0x%p\n",regs -> t0,regs -> t1);
  121. rt_kprintf("\tt2(x7) = 0x%p\n",regs -> t2);
  122. rt_kprintf("\tt3(x28) = 0x%p\tt4(x29) = 0x%p\n",regs -> t3,regs -> t4);
  123. rt_kprintf("\tt5(x30) = 0x%p\tt6(x31) = 0x%p\n",regs -> t5,regs -> t6);
  124. rt_kprintf("Saved Registers:\n");
  125. rt_kprintf("\ts0/fp(x8) = 0x%p\ts1(x9) = 0x%p\n",regs -> s0_fp,regs -> s1);
  126. rt_kprintf("\ts2(x18) = 0x%p\ts3(x19) = 0x%p\n",regs -> s2,regs -> s3);
  127. rt_kprintf("\ts4(x20) = 0x%p\ts5(x21) = 0x%p\n",regs -> s4,regs -> s5);
  128. rt_kprintf("\ts6(x22) = 0x%p\ts7(x23) = 0x%p\n",regs -> s6,regs -> s7);
  129. rt_kprintf("\ts8(x24) = 0x%p\ts9(x25) = 0x%p\n",regs -> s8,regs -> s9);
  130. rt_kprintf("\ts10(x26) = 0x%p\ts11(x27) = 0x%p\n",regs -> s10,regs -> s11);
  131. rt_kprintf("Function Arguments Registers:\n");
  132. rt_kprintf("\ta0(x10) = 0x%p\ta1(x11) = 0x%p\n",regs -> a0,regs -> a1);
  133. rt_kprintf("\ta2(x12) = 0x%p\ta3(x13) = 0x%p\n",regs -> a2,regs -> a3);
  134. rt_kprintf("\ta4(x14) = 0x%p\ta5(x15) = 0x%p\n",regs -> a4,regs -> a5);
  135. rt_kprintf("\ta6(x16) = 0x%p\ta7(x17) = 0x%p\n",regs -> a6,regs -> a7);
  136. rt_kprintf("xstatus = 0x%p\n",regs -> xstatus);
  137. rt_kprintf("\t%s\n",(regs -> xstatus & SSTATUS_SIE) ? "Supervisor Interrupt Enabled" : "Supervisor Interrupt Disabled");
  138. rt_kprintf("\t%s\n",(regs -> xstatus & SSTATUS_SPIE) ? "Last Time Supervisor Interrupt Enabled" : "Last Time Supervisor Interrupt Disabled");
  139. rt_kprintf("\t%s\n",(regs -> xstatus & SSTATUS_SPP) ? "Last Privilege is Supervisor Mode" : "Last Privilege is User Mode");
  140. rt_kprintf("\t%s\n",(regs -> xstatus & SSTATUS_PUM) ? "Permit to Access User Page" : "Not Permit to Access User Page");
  141. rt_kprintf("\t%s\n",(regs -> xstatus & (1 << 19)) ? "Permit to Read Executable-only Page" : "Not Permit to Read Executable-only Page");
  142. rt_size_t satp_v = read_csr(satp);
  143. rt_kprintf("satp = 0x%p\n",satp_v);
  144. const char *mode_str = "Unknown Address Translation/Protection Mode";
  145. switch(__MASKVALUE(satp_v >> 60,__MASK(4)))
  146. {
  147. case 0:
  148. mode_str = "No Address Translation/Protection Mode";
  149. break;
  150. case 8:
  151. mode_str = "Page-based 39-bit Virtual Addressing Mode";
  152. break;
  153. case 9:
  154. mode_str = "Page-based 48-bit Virtual Addressing Mode";
  155. break;
  156. }
  157. rt_kprintf("\tMode = %s\n",mode_str);
  158. rt_kprintf("-----------------Dump OK---------------------\n");
  159. }
  160. void handle_trap(rt_size_t xcause,rt_size_t xtval,rt_size_t xepc,struct rt_hw_stack_frame *sp)
  161. {
  162. int cause = (xcause & 0xFFFFFFFF);
  163. int plic_irq = 0;
  164. if (xcause & (1UL << 63))
  165. {
  166. switch (cause)
  167. {
  168. case IRQ_M_SOFT:
  169. {
  170. }
  171. break;
  172. case IRQ_M_TIMER:
  173. tick_isr();
  174. break;
  175. case IRQ_S_TIMER:
  176. tick_isr();
  177. break;
  178. case IRQ_S_EXT:
  179. plic_irq = plic_claim();
  180. plic_complete(plic_irq);
  181. irq_desc[plic_irq].handler(plic_irq, irq_desc[plic_irq].param);
  182. break;
  183. case IRQ_M_EXT:
  184. plic_irq = plic_claim();
  185. plic_complete(plic_irq);
  186. irq_desc[plic_irq].handler(plic_irq, irq_desc[plic_irq].param);
  187. break;
  188. }
  189. }
  190. else
  191. {
  192. rt_thread_t tid;
  193. #if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
  194. extern long list_thread();
  195. #endif
  196. rt_hw_interrupt_disable();
  197. rt_kprintf("xcause = %08x,xtval = %08x,xepc = %08x\n", xcause, xtval, xepc);
  198. tid = rt_thread_self();
  199. rt_kprintf("\nException:\n");
  200. switch (cause)
  201. {
  202. case CAUSE_MISALIGNED_FETCH:
  203. rt_kprintf("Instruction address misaligned");
  204. break;
  205. case CAUSE_FAULT_FETCH:
  206. rt_kprintf("Instruction access fault");
  207. break;
  208. case CAUSE_ILLEGAL_INSTRUCTION:
  209. rt_kprintf("Illegal instruction");
  210. break;
  211. case CAUSE_BREAKPOINT:
  212. rt_kprintf("Breakpoint");
  213. break;
  214. case CAUSE_MISALIGNED_LOAD:
  215. rt_kprintf("Load address misaligned");
  216. break;
  217. case CAUSE_FAULT_LOAD:
  218. rt_kprintf("Load access fault");
  219. break;
  220. case CAUSE_MISALIGNED_STORE:
  221. rt_kprintf("Store address misaligned");
  222. break;
  223. case CAUSE_FAULT_STORE:
  224. rt_kprintf("Store access fault");
  225. break;
  226. case CAUSE_USER_ECALL:
  227. rt_kprintf("Environment call from U-mode");
  228. break;
  229. case CAUSE_SUPERVISOR_ECALL:
  230. rt_kprintf("Environment call from S-mode");
  231. break;
  232. case CAUSE_HYPERVISOR_ECALL:
  233. rt_kprintf("Environment call from H-mode");
  234. break;
  235. case CAUSE_MACHINE_ECALL:
  236. rt_kprintf("Environment call from M-mode");
  237. break;
  238. default:
  239. rt_kprintf("Uknown exception : %08lX", cause);
  240. break;
  241. }
  242. rt_kprintf("\n");
  243. dump_regs(sp);
  244. rt_kprintf("exception pc => 0x%08x\n", xepc);
  245. rt_kprintf("current thread: %.*s\n", RT_NAME_MAX, tid->name);
  246. #if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
  247. list_thread();
  248. #endif
  249. while(1);
  250. }
  251. rt_hw_interrupt_enable(0);
  252. }