interrupt.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2013-07-06 Bernard first version
  9. * 2018-11-22 Jesven add smp support
  10. */
  11. #include <rthw.h>
  12. #include <rtthread.h>
  13. #include "interrupt.h"
  14. #include "gic.h"
  15. #include "gicv3.h"
  16. /* exception and interrupt handler table */
  17. struct rt_irq_desc isr_table[MAX_HANDLERS];
  18. #ifndef RT_USING_SMP
  19. /* Those variables will be accessed in ISR, so we need to share them. */
  20. rt_ubase_t rt_interrupt_from_thread = 0;
  21. rt_ubase_t rt_interrupt_to_thread = 0;
  22. rt_ubase_t rt_thread_switch_interrupt_flag = 0;
  23. #endif
  24. #ifndef RT_CPUS_NR
  25. #define RT_CPUS_NR 1
  26. #endif
  27. const unsigned int VECTOR_BASE = 0x00;
  28. extern void rt_cpu_vector_set_base(void *addr);
  29. extern void *system_vectors;
  30. #ifdef RT_USING_SMP
  31. #define rt_interrupt_nest rt_cpu_self()->irq_nest
  32. #else
  33. extern volatile rt_uint8_t rt_interrupt_nest;
  34. #endif
  35. #ifdef SOC_BCM283x
  36. static void default_isr_handler(int vector, void *param)
  37. {
  38. #ifdef RT_USING_SMP
  39. rt_kprintf("cpu %d unhandled irq: %d\n", rt_hw_cpu_id(),vector);
  40. #else
  41. rt_kprintf("unhandled irq: %d\n",vector);
  42. #endif
  43. }
  44. #endif
  45. void rt_hw_vector_init(void)
  46. {
  47. rt_cpu_vector_set_base(&system_vectors);
  48. }
  49. /**
  50. * This function will initialize hardware interrupt
  51. */
  52. void rt_hw_interrupt_init(void)
  53. {
  54. #ifdef SOC_BCM283x
  55. rt_uint32_t index;
  56. /* initialize vector table */
  57. rt_hw_vector_init();
  58. /* initialize exceptions table */
  59. rt_memset(isr_table, 0x00, sizeof(isr_table));
  60. /* mask all of interrupts */
  61. IRQ_DISABLE_BASIC = 0x000000ff;
  62. IRQ_DISABLE1 = 0xffffffff;
  63. IRQ_DISABLE2 = 0xffffffff;
  64. for (index = 0; index < MAX_HANDLERS; index ++)
  65. {
  66. isr_table[index].handler = default_isr_handler;
  67. isr_table[index].param = RT_NULL;
  68. #ifdef RT_USING_INTERRUPT_INFO
  69. rt_strncpy(isr_table[index].name, "unknown", RT_NAME_MAX);
  70. isr_table[index].counter = 0;
  71. #endif
  72. }
  73. /* init interrupt nest, and context in thread sp */
  74. rt_interrupt_nest = 0;
  75. rt_interrupt_from_thread = 0;
  76. rt_interrupt_to_thread = 0;
  77. rt_thread_switch_interrupt_flag = 0;
  78. #else
  79. rt_uint64_t gic_cpu_base;
  80. rt_uint64_t gic_dist_base;
  81. #ifdef BSP_USING_GICV3
  82. rt_uint64_t gic_rdist_base;
  83. #endif
  84. rt_uint64_t gic_irq_start;
  85. /* initialize vector table */
  86. rt_hw_vector_init();
  87. /* initialize exceptions table */
  88. rt_memset(isr_table, 0x00, sizeof(isr_table));
  89. /* initialize ARM GIC */
  90. #ifdef RT_USING_USERSPACE
  91. gic_dist_base = (rt_uint64_t)rt_hw_mmu_map(&mmu_info, 0, (void*)platform_get_gic_dist_base(), 0x2000, MMU_MAP_K_DEVICE);
  92. gic_cpu_base = (rt_uint64_t)rt_hw_mmu_map(&mmu_info, 0, (void*)platform_get_gic_cpu_base(), 0x1000, MMU_MAP_K_DEVICE);
  93. #ifdef BSP_USING_GICV3
  94. gic_rdist_base = (rt_uint64_t)rt_hw_mmu_map(&mmu_info, 0, (void*)platform_get_gic_redist_base(),
  95. RT_CPUS_NR * (2 << 16), MMU_MAP_K_DEVICE);
  96. #endif
  97. #else
  98. gic_dist_base = platform_get_gic_dist_base();
  99. gic_cpu_base = platform_get_gic_cpu_base();
  100. gic_rdist_base = platform_get_gic_redist_base();
  101. #endif
  102. gic_irq_start = GIC_IRQ_START;
  103. arm_gic_dist_init(0, gic_dist_base, gic_irq_start);
  104. arm_gic_cpu_init(0, gic_cpu_base);
  105. #ifdef BSP_USING_GICV3
  106. arm_gic_redist_init(0, gic_rdist_base);
  107. #endif
  108. #endif
  109. }
  110. /**
  111. * This function will mask a interrupt.
  112. * @param vector the interrupt number
  113. */
  114. void rt_hw_interrupt_mask(int vector)
  115. {
  116. #ifdef SOC_BCM283x
  117. if (vector < 32)
  118. {
  119. IRQ_DISABLE1 = (1 << vector);
  120. }
  121. else if (vector < 64)
  122. {
  123. vector = vector % 32;
  124. IRQ_DISABLE2 = (1 << vector);
  125. }
  126. else
  127. {
  128. vector = vector - 64;
  129. IRQ_DISABLE_BASIC = (1 << vector);
  130. }
  131. #else
  132. arm_gic_mask(0, vector);
  133. #endif
  134. }
  135. /**
  136. * This function will un-mask a interrupt.
  137. * @param vector the interrupt number
  138. */
  139. void rt_hw_interrupt_umask(int vector)
  140. {
  141. #ifdef SOC_BCM283x
  142. if (vector < 32)
  143. {
  144. IRQ_ENABLE1 = (1 << vector);
  145. }
  146. else if (vector < 64)
  147. {
  148. vector = vector % 32;
  149. IRQ_ENABLE2 = (1 << vector);
  150. }
  151. else
  152. {
  153. vector = vector - 64;
  154. IRQ_ENABLE_BASIC = (1 << vector);
  155. }
  156. #else
  157. arm_gic_umask(0, vector);
  158. #endif
  159. }
  160. /**
  161. * This function returns the active interrupt number.
  162. * @param none
  163. */
  164. int rt_hw_interrupt_get_irq(void)
  165. {
  166. #ifndef SOC_BCM283x
  167. return arm_gic_get_active_irq(0);
  168. #else
  169. return 0;
  170. #endif
  171. }
  172. /**
  173. * This function acknowledges the interrupt.
  174. * @param vector the interrupt number
  175. */
  176. void rt_hw_interrupt_ack(int vector)
  177. {
  178. #ifndef SOC_BCM283x
  179. arm_gic_ack(0, vector);
  180. #endif
  181. }
  182. /**
  183. * This function set interrupt CPU targets.
  184. * @param vector: the interrupt number
  185. * cpu_mask: target cpus mask, one bit for one core
  186. */
  187. void rt_hw_interrupt_set_target_cpus(int vector, unsigned int cpu_mask)
  188. {
  189. arm_gic_set_cpu(0, vector, cpu_mask);
  190. }
  191. /**
  192. * This function get interrupt CPU targets.
  193. * @param vector: the interrupt number
  194. * @return target cpus mask, one bit for one core
  195. */
  196. unsigned int rt_hw_interrupt_get_target_cpus(int vector)
  197. {
  198. return arm_gic_get_target_cpu(0, vector);
  199. }
  200. /**
  201. * This function set interrupt triger mode.
  202. * @param vector: the interrupt number
  203. * mode: interrupt triger mode; 0: level triger, 1: edge triger
  204. */
  205. void rt_hw_interrupt_set_triger_mode(int vector, unsigned int mode)
  206. {
  207. arm_gic_set_configuration(0, vector, mode);
  208. }
  209. /**
  210. * This function get interrupt triger mode.
  211. * @param vector: the interrupt number
  212. * @return interrupt triger mode; 0: level triger, 1: edge triger
  213. */
  214. unsigned int rt_hw_interrupt_get_triger_mode(int vector)
  215. {
  216. return arm_gic_get_configuration(0, vector);
  217. }
  218. /**
  219. * This function set interrupt pending flag.
  220. * @param vector: the interrupt number
  221. */
  222. void rt_hw_interrupt_set_pending(int vector)
  223. {
  224. arm_gic_set_pending_irq(0, vector);
  225. }
  226. /**
  227. * This function get interrupt pending flag.
  228. * @param vector: the interrupt number
  229. * @return interrupt pending flag, 0: not pending; 1: pending
  230. */
  231. unsigned int rt_hw_interrupt_get_pending(int vector)
  232. {
  233. return arm_gic_get_pending_irq(0, vector);
  234. }
  235. /**
  236. * This function clear interrupt pending flag.
  237. * @param vector: the interrupt number
  238. */
  239. void rt_hw_interrupt_clear_pending(int vector)
  240. {
  241. arm_gic_clear_pending_irq(0, vector);
  242. }
  243. /**
  244. * This function set interrupt priority value.
  245. * @param vector: the interrupt number
  246. * priority: the priority of interrupt to set
  247. */
  248. void rt_hw_interrupt_set_priority(int vector, unsigned int priority)
  249. {
  250. arm_gic_set_priority(0, vector, priority);
  251. }
  252. /**
  253. * This function get interrupt priority.
  254. * @param vector: the interrupt number
  255. * @return interrupt priority value
  256. */
  257. unsigned int rt_hw_interrupt_get_priority(int vector)
  258. {
  259. return arm_gic_get_priority(0, vector);
  260. }
  261. /**
  262. * This function set priority masking threshold.
  263. * @param priority: priority masking threshold
  264. */
  265. void rt_hw_interrupt_set_priority_mask(unsigned int priority)
  266. {
  267. arm_gic_set_interface_prior_mask(0, priority);
  268. }
  269. /**
  270. * This function get priority masking threshold.
  271. * @param none
  272. * @return priority masking threshold
  273. */
  274. unsigned int rt_hw_interrupt_get_priority_mask(void)
  275. {
  276. return arm_gic_get_interface_prior_mask(0);
  277. }
  278. /**
  279. * This function set priority grouping field split point.
  280. * @param bits: priority grouping field split point
  281. * @return 0: success; -1: failed
  282. */
  283. int rt_hw_interrupt_set_prior_group_bits(unsigned int bits)
  284. {
  285. int status;
  286. if (bits < 8)
  287. {
  288. arm_gic_set_binary_point(0, (7 - bits));
  289. status = 0;
  290. }
  291. else
  292. {
  293. status = -1;
  294. }
  295. return (status);
  296. }
  297. /**
  298. * This function get priority grouping field split point.
  299. * @param none
  300. * @return priority grouping field split point
  301. */
  302. unsigned int rt_hw_interrupt_get_prior_group_bits(void)
  303. {
  304. unsigned int bp;
  305. bp = arm_gic_get_binary_point(0) & 0x07;
  306. return (7 - bp);
  307. }
  308. /**
  309. * This function will install a interrupt service routine to a interrupt.
  310. * @param vector the interrupt number
  311. * @param new_handler the interrupt service routine to be installed
  312. * @param old_handler the old interrupt service routine
  313. */
  314. rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
  315. void *param, const char *name)
  316. {
  317. rt_isr_handler_t old_handler = RT_NULL;
  318. if (vector < MAX_HANDLERS)
  319. {
  320. old_handler = isr_table[vector].handler;
  321. if (handler != RT_NULL)
  322. {
  323. #ifdef RT_USING_INTERRUPT_INFO
  324. rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX);
  325. #endif /* RT_USING_INTERRUPT_INFO */
  326. isr_table[vector].handler = handler;
  327. isr_table[vector].param = param;
  328. }
  329. }
  330. return old_handler;
  331. }
  332. #ifdef RT_USING_SMP
  333. void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask)
  334. {
  335. #ifdef BSP_USING_GICV2
  336. arm_gic_send_sgi(0, ipi_vector, cpu_mask, 0);
  337. #elif defined(BSP_USING_GICV3)
  338. arm_gic_send_affinity_sgi(0, ipi_vector, (unsigned int *)&cpu_mask, GICV3_ROUTED_TO_SPEC);
  339. #endif
  340. }
  341. void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler)
  342. {
  343. /* note: ipi_vector maybe different with irq_vector */
  344. rt_hw_interrupt_install(ipi_vector, ipi_isr_handler, 0, "IPI_HANDLER");
  345. }
  346. #endif