interrupt.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. * Copyright (c) 2006-2024, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2024/01/11 flyingcys The first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include "interrupt.h"
  13. #include "encoding.h"
  14. #include "mmio.h"
  15. extern rt_uint32_t rt_interrupt_nest;
  16. extern rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
  17. extern rt_uint32_t rt_thread_switch_interrupt_flag;
  18. struct rt_irq_desc isr_table[INTERRUPTS_MAX];
  19. static void plic_enable_irq(int irq)
  20. {
  21. uint32_t mask = (irq);
  22. uint32_t value = 0;
  23. if(irq < 16) {
  24. rt_kprintf("unmask irq_num is %d\n",irq);
  25. return;
  26. }
  27. value = mmio_read_32(PLIC_ENABLE1 + 4 * (mask / 32));
  28. value |= (0x1 << (mask % 32));
  29. mmio_write_32((PLIC_ENABLE1 + (mask / 32) * 4), value);
  30. }
  31. static void plic_disable_irq(int irq)
  32. {
  33. uint32_t mask = (irq);
  34. uint32_t value = 0;
  35. if(irq < 16) {
  36. rt_kprintf("mask irq_num is %d\n", irq);
  37. return;
  38. }
  39. value = mmio_read_32(PLIC_ENABLE1 + 4 * (mask / 32));
  40. value &= ~(0x1 << (mask % 32));
  41. mmio_write_32((PLIC_ENABLE1 + (mask / 32) * 4), value);
  42. }
  43. static void plic_set_priority(int irq, int priority)
  44. {
  45. mmio_write_32((PLIC_PRIORITY0 + irq * 4), priority);
  46. }
  47. static void plic_set_threshold(uint32_t threshold)
  48. {
  49. mmio_write_32((PLIC_THRESHOLD), threshold);
  50. }
  51. void plic_init(void)
  52. {
  53. int i;
  54. for (i = 0; i < IRQ_MAX_NR / 4; i = i + 4)
  55. {
  56. mmio_write_32(((uintptr_t) PLIC_PRIORITY0 + i), 0);
  57. }
  58. for ( i = 0; i < IRQ_MAX_NR / 32; i ++)
  59. {
  60. mmio_write_32((PLIC_PENDING1 + i * 4), 0);
  61. mmio_write_32((PLIC_ENABLE1 + i * 4), 0);
  62. }
  63. plic_set_threshold(0);
  64. /* Enable machine external interrupts. */
  65. set_csr(mie, MIP_MEIP);
  66. }
  67. static void rt_hw_interrupt_handler(int vector, void *param)
  68. {
  69. rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
  70. }
  71. /**
  72. * This function will initialize hardware interrupt
  73. */
  74. void rt_hw_interrupt_init(void)
  75. {
  76. /* init interrupt controller */
  77. plic_init();
  78. rt_int32_t idx;
  79. rt_memset(isr_table, 0x00, sizeof(isr_table));
  80. for (idx = 0; idx < INTERRUPTS_MAX; idx++)
  81. {
  82. isr_table[idx].handler = rt_hw_interrupt_handler;
  83. }
  84. /* init interrupt nest, and context in thread sp */
  85. rt_interrupt_nest = 0;
  86. rt_interrupt_from_thread = 0;
  87. rt_interrupt_to_thread = 0;
  88. rt_thread_switch_interrupt_flag = 0;
  89. }
  90. /**
  91. * This function will mask a interrupt.
  92. * @param vector the interrupt number
  93. */
  94. void rt_hw_interrupt_mask(int vector)
  95. {
  96. if ((vector < 0) || (vector > IRQ_MAX_NR))
  97. {
  98. return;
  99. }
  100. plic_disable_irq(vector);
  101. }
  102. /**
  103. * This function will un-mask a interrupt.
  104. * @param vector the interrupt number
  105. */
  106. void rt_hw_interrupt_umask(int vector)
  107. {
  108. if ((vector < 0) || (vector > IRQ_MAX_NR))
  109. {
  110. return;
  111. }
  112. plic_enable_irq(vector);
  113. }
  114. /**
  115. * This function will install a interrupt service routine to a interrupt.
  116. * @param vector the interrupt number
  117. * @param handler the interrupt service routine to be installed
  118. * @param param the interrupt service function parameter
  119. * @param name the interrupt name
  120. * @return old handler
  121. */
  122. rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
  123. void *param, const char *name)
  124. {
  125. rt_isr_handler_t old_handler = RT_NULL;
  126. if ((vector < 0) || (vector > IRQ_MAX_NR))
  127. {
  128. return old_handler;
  129. }
  130. old_handler = isr_table[vector].handler;
  131. #ifdef RT_USING_INTERRUPT_INFO
  132. rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX);
  133. #endif /* RT_USING_INTERRUPT_INFO */
  134. isr_table[vector].handler = handler;
  135. isr_table[vector].param = param;
  136. // set highest priority
  137. plic_set_priority(vector, 7);
  138. return old_handler;
  139. }
  140. void rt_hw_irq_isr(void)
  141. {
  142. int irq = mmio_read_32(PLIC_CLAIM);
  143. rt_isr_handler_t isr;
  144. void *param;
  145. if (irq < 0 || irq >= IRQ_MAX_NR)
  146. {
  147. rt_kprintf("bad irq number %d!\n", irq);
  148. return;
  149. }
  150. if (!irq) // irq = 0 => no irq
  151. {
  152. rt_kprintf("no irq!\n");
  153. return;
  154. }
  155. isr = isr_table[irq].handler;
  156. param = isr_table[irq].param;
  157. if (isr != RT_NULL)
  158. {
  159. isr(irq, param);
  160. }
  161. mmio_write_32(PLIC_CLAIM, irq);
  162. // clear external interrupt pending
  163. clear_csr(mip, MIP_MEIP);
  164. }