HPM SDK
HPMicro Software Development Kit
hpm_interrupt.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2021-2023 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #ifndef HPM_INTERRUPT_H
9 #define HPM_INTERRUPT_H
10 #include "hpm_common.h"
11 #include "hpm_csr_drv.h"
12 #include "hpm_plic_drv.h"
13 
20 #define M_MODE 0
21 #define S_MODE 1
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26 
27 /* Machine mode API: these APIs are supposed to be called at machine mode */
28 
34 ATTR_ALWAYS_INLINE static inline void enable_global_irq(uint32_t mask)
35 {
36  set_csr(CSR_MSTATUS, mask);
37 }
38 
45 ATTR_ALWAYS_INLINE static inline uint32_t disable_global_irq(uint32_t mask)
46 {
47  return read_clear_csr(CSR_MSTATUS, mask);
48 }
49 
55 ATTR_ALWAYS_INLINE static inline void restore_global_irq(uint32_t mask)
56 {
57  set_csr(CSR_MSTATUS, mask);
58 }
59 
64 ATTR_ALWAYS_INLINE static inline void enable_irq_from_intc(void)
65 {
67 }
68 
73 ATTR_ALWAYS_INLINE static inline void disable_irq_from_intc(void)
74 {
76 }
77 
81 ATTR_ALWAYS_INLINE static inline void enable_mchtmr_irq(void)
82 {
84 }
85 
90 ATTR_ALWAYS_INLINE static inline void disable_mchtmr_irq(void)
91 {
93 }
94 
100 ATTR_ALWAYS_INLINE static inline void delegate_irq(uint32_t mask)
101 {
102  set_csr(CSR_MIDELEG, mask);
103 }
104 
110 ATTR_ALWAYS_INLINE static inline void undelegate_irq(uint32_t mask)
111 {
112  clear_csr(CSR_MIDELEG, mask);
113 }
114 
115 
116 /* Supervisor mode API: these APIs are supposed to be called at supervisor mode */
117 
123 ATTR_ALWAYS_INLINE static inline void enable_s_global_irq(uint32_t mask)
124 {
125  set_csr(CSR_SSTATUS, mask);
126 }
127 
134 ATTR_ALWAYS_INLINE static inline uint32_t disable_s_global_irq(uint32_t mask)
135 {
136  return read_clear_csr(CSR_SSTATUS, mask);
137 }
138 
144 ATTR_ALWAYS_INLINE static inline void restore_s_global_irq(uint32_t mask)
145 {
146  set_csr(CSR_SSTATUS, mask);
147 }
148 
153 ATTR_ALWAYS_INLINE static inline void disable_s_irq_from_intc(void)
154 {
156 }
157 
162 ATTR_ALWAYS_INLINE static inline void enable_s_irq_from_intc(void)
163 {
165 }
166 
170 ATTR_ALWAYS_INLINE static inline void enable_s_mchtmr_irq(void)
171 {
173 }
174 
179 ATTR_ALWAYS_INLINE static inline void disable_s_mchtmr_irq(void)
180 {
182 }
183 
184 
185 /*
186  * CPU Machine SWI control
187  *
188  * Machine SWI (MSIP) is connected to PLICSW irq 1.
189  */
190 #define PLICSWI 1
191 
196 ATTR_ALWAYS_INLINE static inline void intc_m_init_swi(void)
197 {
198  __plic_enable_irq(HPM_PLICSW_BASE, HPM_PLIC_TARGET_M_MODE, PLICSWI);
199 }
200 
201 
206 ATTR_ALWAYS_INLINE static inline void intc_m_enable_swi(void)
207 {
209 }
210 
211 
216 ATTR_ALWAYS_INLINE static inline void intc_m_disable_swi(void)
217 {
219 }
220 
221 
226 ATTR_ALWAYS_INLINE static inline void intc_m_trigger_swi(void)
227 {
228  __plic_set_irq_pending(HPM_PLICSW_BASE, PLICSWI);
229 }
230 
235 ATTR_ALWAYS_INLINE static inline void intc_m_claim_swi(void)
236 {
237  __plic_claim_irq(HPM_PLICSW_BASE, 0);
238 }
239 
244 ATTR_ALWAYS_INLINE static inline void intc_m_complete_swi(void)
245 {
246  __plic_complete_irq(HPM_PLICSW_BASE, HPM_PLIC_TARGET_M_MODE, PLICSWI);
247 }
248 
249 /*
250  * @brief Enable IRQ for machine mode
251  *
252  * @param[in] irq Interrupt number
253  */
254 #define intc_m_enable_irq(irq) \
255  intc_enable_irq(HPM_PLIC_TARGET_M_MODE, irq)
256 
257 /*
258  * @brief Disable IRQ for machine mode
259  *
260  * @param[in] irq Interrupt number
261  */
262 #define intc_m_disable_irq(irq) \
263  intc_disable_irq(HPM_PLIC_TARGET_M_MODE, irq)
264 
265 #define intc_m_set_threshold(threshold) \
266  intc_set_threshold(HPM_PLIC_TARGET_M_MODE, threshold)
267 
268 /*
269  * @brief Complete IRQ for machine mode
270  *
271  * @param[in] irq Interrupt number
272  */
273 #define intc_m_complete_irq(irq) \
274  intc_complete_irq(HPM_PLIC_TARGET_M_MODE, irq)
275 
276 /*
277  * @brief Claim IRQ for machine mode
278  *
279  */
280 #define intc_m_claim_irq() intc_claim_irq(HPM_PLIC_TARGET_M_MODE)
281 
282 /*
283  * @brief Enable IRQ for machine mode with priority
284  *
285  * @param[in] irq Interrupt number
286  * @param[in] priority Priority of interrupt
287  */
288 #define intc_m_enable_irq_with_priority(irq, priority) \
289  do { \
290  intc_set_irq_priority(irq, priority); \
291  intc_m_enable_irq(irq); \
292  } while (0)
293 
294 
295 
296 /* Supervisor mode */
297 
302 ATTR_ALWAYS_INLINE static inline void intc_s_enable_swi(void)
303 {
305 }
306 
307 
312 ATTR_ALWAYS_INLINE static inline void intc_s_disable_swi(void)
313 {
315 }
316 
317 
322 ATTR_ALWAYS_INLINE static inline void intc_s_trigger_swi(void)
323 {
325 }
326 
327 
332 ATTR_ALWAYS_INLINE static inline void intc_s_complete_swi(void)
333 {
335 }
336 
337 /*
338  * @brief Enable IRQ for supervisor mode
339  *
340  * @param[in] irq Interrupt number
341  */
342 #define intc_s_enable_irq(irq) \
343  intc_enable_irq(HPM_PLIC_TARGET_S_MODE, irq)
344 
345 /*
346  * @brief Disable IRQ for supervisor mode
347  *
348  * @param[in] irq Interrupt number
349  */
350 #define intc_s_disable_irq(irq) \
351  intc_disable_irq(HPM_PLIC_TARGET_S_MODE, irq)
352 
353 #define intc_set_s_threshold(threshold) \
354  intc_set_threshold(HPM_PLIC_TARGET_S_MODE, threshold)
355 
356 /*
357  * @brief Complete IRQ for supervisor mode
358  *
359  * @param[in] irq Interrupt number
360  */
361 #define intc_s_complete_irq(irq) \
362  intc_complete_irq(HPM_PLIC_TARGET_S_MODE, irq)
363 
364 /*
365  * @brief Claim IRQ for supervisor mode
366  *
367  */
368 #define intc_s_claim_irq() intc_claim_irq(HPM_PLIC_TARGET_S_MODE)
369 
370 /*
371  * @brief Enable IRQ for supervisor mode with priority
372  *
373  * @param[in] irq Interrupt number
374  * @param[in] priority Priority of interrupt
375  */
376 #define intc_s_enable_irq_with_priority(irq, priority) \
377  do { \
378  intc_set_irq_priority(irq, priority); \
379  intc_s_enable_irq(irq); \
380  } while (0)
381 
382 
383 /*
384  * @brief Enable specific interrupt
385  *
386  * @param[in] target Target to handle specific interrupt
387  * @param[in] irq Interrupt number
388  */
389 ATTR_ALWAYS_INLINE static inline void intc_enable_irq(uint32_t target, uint32_t irq)
390 {
391  __plic_enable_irq(HPM_PLIC_BASE, target, irq);
392 }
393 
400 ATTR_ALWAYS_INLINE static inline void intc_set_irq_priority(uint32_t irq, uint32_t priority)
401 {
402  __plic_set_irq_priority(HPM_PLIC_BASE, irq, priority);
403 }
404 
411 ATTR_ALWAYS_INLINE static inline void intc_disable_irq(uint32_t target, uint32_t irq)
412 {
413  __plic_disable_irq(HPM_PLIC_BASE, target, irq);
414 }
415 
422 ATTR_ALWAYS_INLINE static inline void intc_set_threshold(uint32_t target, uint32_t threshold)
423 {
424  __plic_set_threshold(HPM_PLIC_BASE, target, threshold);
425 }
426 
433 ATTR_ALWAYS_INLINE static inline uint32_t intc_claim_irq(uint32_t target)
434 {
435  return __plic_claim_irq(HPM_PLIC_BASE, target);
436 }
437 
445 ATTR_ALWAYS_INLINE static inline void intc_complete_irq(uint32_t target, uint32_t irq)
446 {
447  __plic_complete_irq(HPM_PLIC_BASE, target, irq);
448 }
449 
450 /*
451  * Vectored based irq install and uninstall
452  */
453 /* Machine mode */
454 extern int __vector_table[];
455 extern void default_irq_entry(void);
456 
464 ATTR_ALWAYS_INLINE static inline void install_isr(uint32_t irq, uint32_t isr)
465 {
466  __vector_table[irq] = isr;
467 }
468 
475 ATTR_ALWAYS_INLINE static inline void uninstall_isr(uint32_t irq)
476 {
477  __vector_table[irq] = (int) default_irq_entry;
478 }
479 
480 /* Supervisor mode */
481 extern int __vector_s_table[];
482 extern void default_s_irq_entry(void);
490 ATTR_ALWAYS_INLINE static inline void install_s_isr(uint32_t irq, uint32_t isr)
491 {
492  __vector_s_table[irq] = isr;
493 }
494 
501 ATTR_ALWAYS_INLINE static inline void uninstall_s_isr(uint32_t irq)
502 {
503  __vector_s_table[irq] = (int) default_s_irq_entry;
504 }
505 
506 
507 /*
508  * Inline nested irq entry/exit macros
509  */
510 /*
511  * @brief Save CSR
512  * @param[in] r Target CSR to be saved
513  */
514 #define SAVE_CSR(r) register long __##r = read_csr(r);
515 
516 /*
517  * @brief Restore macro
518  *
519  * @param[in] r Target CSR to be restored
520  */
521 #define RESTORE_CSR(r) write_csr(r, __##r);
522 
523 #if defined(SUPPORT_PFT_ARCH) && SUPPORT_PFT_ARCH
524 #define SAVE_MXSTATUS() SAVE_CSR(CSR_MXSTATUS)
525 #define RESTORE_MXSTATUS() RESTORE_CSR(CSR_MXSTATUS)
526 #else
527 #define SAVE_MXSTATUS()
528 #define RESTORE_MXSTATUS()
529 #endif
530 
531 #ifdef __riscv_flen
532 #define SAVE_FCSR() register int __fcsr = read_fcsr();
533 #define RESTORE_FCSR() write_fcsr(__fcsr);
534 #else
535 #define SAVE_FCSR()
536 #define RESTORE_FCSR()
537 #endif
538 
539 #ifdef __riscv_dsp
540 #define SAVE_UCODE() SAVE_CSR(CSR_UCODE)
541 #define RESTORE_UCODE() RESTORE_CSR(CSR_UCODE)
542 #else
543 #define SAVE_UCODE()
544 #define RESTORE_UCODE()
545 #endif
546 
547 #ifdef __riscv_flen
548 #if __riscv_flen == 32
549 /* RV32I caller registers + MCAUSE + MEPC + MSTATUS +MXSTATUS + 20 FPU caller registers +FCSR + UCODE (DSP) */
550 #define CONTEXT_REG_NUM (4 * (16 + 4 + 20))
551 #else /* __riscv_flen = 64 */
552 /* RV32I caller registers + MCAUSE + MEPC + MSTATUS +MXSTATUS + 20 DFPU caller + FCSR registers + UCODE (DSP) */
553 #define CONTEXT_REG_NUM (4 * (16 + 4 + 20 * 2))
554 #endif
555 
556 #else
557 /* RV32I caller registers + MCAUSE + MEPC + MSTATUS +MXSTATUS + UCODE (DSP)*/
558 #define CONTEXT_REG_NUM (4 * (16 + 4))
559 #endif
560 
561 #ifdef __riscv_flen
562 /*
563  * Save FPU caller registers:
564  * NOTE: To simplify the logic, the FPU caller registers are always stored at word offset 20 in the stack
565  */
566 #if __riscv_flen == 32
567 #ifdef __ICCRISCV__
568 #define SAVE_FPU_CONTEXT() { \
569  __asm volatile("\n\
570  c.fswsp ft0, 20*4\n\
571  c.fswsp ft1, 21*4 \n\
572  c.fswsp ft2, 22*4 \n\
573  c.fswsp ft3, 23*4 \n\
574  c.fswsp ft4, 24*4 \n\
575  c.fswsp ft5, 25*4 \n\
576  c.fswsp ft6, 26*4 \n\
577  c.fswsp ft7, 27*4 \n\
578  c.fswsp fa0, 28*4 \n\
579  c.fswsp fa1, 29*4 \n\
580  c.fswsp fa2, 30*4 \n\
581  c.fswsp fa3, 31*4 \n\
582  c.fswsp fa4, 32*4 \n\
583  c.fswsp fa5, 33*4 \n\
584  c.fswsp fa6, 34*4 \n\
585  c.fswsp fa7, 35*4 \n\
586  c.fswsp ft8, 36*4 \n\
587  c.fswsp ft9, 37*4 \n\
588  c.fswsp ft10, 38*4 \n\
589  c.fswsp ft11, 39*4 \n");\
590 }
591 
592 /*
593  * Restore FPU caller registers:
594  * NOTE: To simplify the logic, the FPU caller registers are always stored at word offset 20 in the stack
595  */
596 #define RESTORE_FPU_CONTEXT() { \
597  __asm volatile("\n\
598  c.flwsp ft0, 20*4\n\
599  c.flwsp ft1, 21*4 \n\
600  c.flwsp ft2, 22*4 \n\
601  c.flwsp ft3, 23*4 \n\
602  c.flwsp ft4, 24*4 \n\
603  c.flwsp ft5, 25*4 \n\
604  c.flwsp ft6, 26*4 \n\
605  c.flwsp ft7, 27*4 \n\
606  c.flwsp fa0, 28*4 \n\
607  c.flwsp fa1, 29*4 \n\
608  c.flwsp fa2, 30*4 \n\
609  c.flwsp fa3, 31*4 \n\
610  c.flwsp fa4, 32*4 \n\
611  c.flwsp fa5, 33*4 \n\
612  c.flwsp fa6, 34*4 \n\
613  c.flwsp fa7, 35*4 \n\
614  c.flwsp ft8, 36*4 \n\
615  c.flwsp ft9, 37*4 \n\
616  c.flwsp ft10, 38*4 \n\
617  c.flwsp ft11, 39*4 \n");\
618 }
619 #else /* __ICCRISCV__ not defined */
620 #define SAVE_FPU_CONTEXT() { \
621  __asm volatile("\n\
622  c.fswsp ft0, 20*4(sp)\n\
623  c.fswsp ft1, 21*4(sp) \n\
624  c.fswsp ft2, 22*4(sp) \n\
625  c.fswsp ft3, 23*4(sp) \n\
626  c.fswsp ft4, 24*4(sp) \n\
627  c.fswsp ft5, 25*4(sp) \n\
628  c.fswsp ft6, 26*4(sp) \n\
629  c.fswsp ft7, 27*4(sp) \n\
630  c.fswsp fa0, 28*4(sp) \n\
631  c.fswsp fa1, 29*4(sp) \n\
632  c.fswsp fa2, 30*4(sp) \n\
633  c.fswsp fa3, 31*4(sp) \n\
634  c.fswsp fa4, 32*4(sp) \n\
635  c.fswsp fa5, 33*4(sp) \n\
636  c.fswsp fa6, 34*4(sp) \n\
637  c.fswsp fa7, 35*4(sp) \n\
638  c.fswsp ft8, 36*4(sp) \n\
639  c.fswsp ft9, 37*4(sp) \n\
640  c.fswsp ft10, 38*4(sp) \n\
641  c.fswsp ft11, 39*4(sp) \n");\
642 }
643 
644 /*
645  * Restore FPU caller registers:
646  * NOTE: To simplify the logic, the FPU caller registers are always stored at word offset 20 in the stack
647  */
648 #define RESTORE_FPU_CONTEXT() { \
649  __asm volatile("\n\
650  c.flwsp ft0, 20*4(sp)\n\
651  c.flwsp ft1, 21*4(sp) \n\
652  c.flwsp ft2, 22*4(sp) \n\
653  c.flwsp ft3, 23*4(sp) \n\
654  c.flwsp ft4, 24*4(sp) \n\
655  c.flwsp ft5, 25*4(sp) \n\
656  c.flwsp ft6, 26*4(sp) \n\
657  c.flwsp ft7, 27*4(sp) \n\
658  c.flwsp fa0, 28*4(sp) \n\
659  c.flwsp fa1, 29*4(sp) \n\
660  c.flwsp fa2, 30*4(sp) \n\
661  c.flwsp fa3, 31*4(sp) \n\
662  c.flwsp fa4, 32*4(sp) \n\
663  c.flwsp fa5, 33*4(sp) \n\
664  c.flwsp fa6, 34*4(sp) \n\
665  c.flwsp fa7, 35*4(sp) \n\
666  c.flwsp ft8, 36*4(sp) \n\
667  c.flwsp ft9, 37*4(sp) \n\
668  c.flwsp ft10, 38*4(sp) \n\
669  c.flwsp ft11, 39*4(sp) \n");\
670 }
671 #endif
672 #else /*__riscv_flen == 64*/
673 #ifdef __ICCRISCV__
674 #define SAVE_FPU_CONTEXT() { \
675  __asm volatile("\n\
676  c.fsdsp ft0, 20*4\n\
677  c.fsdsp ft1, 22*4 \n\
678  c.fsdsp ft2, 24*4 \n\
679  c.fsdsp ft3, 26*4 \n\
680  c.fsdsp ft4, 28*4 \n\
681  c.fsdsp ft5, 30*4 \n\
682  c.fsdsp ft6, 32*4 \n\
683  c.fsdsp ft7, 34*4 \n\
684  c.fsdsp fa0, 36*4 \n\
685  c.fsdsp fa1, 38*4 \n\
686  c.fsdsp fa2, 40*4 \n\
687  c.fsdsp fa3, 42*4 \n\
688  c.fsdsp fa4, 44*4 \n\
689  c.fsdsp fa5, 46*4 \n\
690  c.fsdsp fa6, 48*4 \n\
691  c.fsdsp fa7, 50*4 \n\
692  c.fsdsp ft8, 52*4 \n\
693  c.fsdsp ft9, 54*4 \n\
694  c.fsdsp ft10, 56*4 \n\
695  c.fsdsp ft11, 58*4 \n");\
696 }
697 
698 /*
699  * Restore FPU caller registers:
700  * NOTE: To simplify the logic, the FPU caller registers are always stored at word offset 20 in the stack
701  */
702 #define RESTORE_FPU_CONTEXT() { \
703  __asm volatile("\n\
704  c.fldsp ft0, 20*4\n\
705  c.fldsp ft1, 22*4 \n\
706  c.fldsp ft2, 24*4 \n\
707  c.fldsp ft3, 26*4 \n\
708  c.fldsp ft4, 28*4 \n\
709  c.fldsp ft5, 30*4 \n\
710  c.fldsp ft6, 32*4 \n\
711  c.fldsp ft7, 34*4 \n\
712  c.fldsp fa0, 36*4 \n\
713  c.fldsp fa1, 38*4 \n\
714  c.fldsp fa2, 40*4 \n\
715  c.fldsp fa3, 42*4 \n\
716  c.fldsp fa4, 44*4 \n\
717  c.fldsp fa5, 46*4 \n\
718  c.fldsp fa6, 48*4 \n\
719  c.fldsp fa7, 50*4 \n\
720  c.fldsp ft8, 52*4 \n\
721  c.fldsp ft9, 54*4 \n\
722  c.fldsp ft10, 56*4 \n\
723  c.fldsp ft11, 58*4 \n");\
724 }
725 #else /*__riscv_flen == 64*/
726 #define SAVE_FPU_CONTEXT() { \
727  __asm volatile("\n\
728  c.fsdsp ft0, 20*4(sp)\n\
729  c.fsdsp ft1, 22*4(sp) \n\
730  c.fsdsp ft2, 24*4(sp) \n\
731  c.fsdsp ft3, 26*4(sp) \n\
732  c.fsdsp ft4, 28*4(sp) \n\
733  c.fsdsp ft5, 30*4(sp) \n\
734  c.fsdsp ft6, 32*4(sp) \n\
735  c.fsdsp ft7, 34*4(sp) \n\
736  c.fsdsp fa0, 36*4(sp) \n\
737  c.fsdsp fa1, 38*4(sp) \n\
738  c.fsdsp fa2, 40*4(sp) \n\
739  c.fsdsp fa3, 42*4(sp) \n\
740  c.fsdsp fa4, 44*4(sp) \n\
741  c.fsdsp fa5, 46*4(sp) \n\
742  c.fsdsp fa6, 48*4(sp) \n\
743  c.fsdsp fa7, 50*4(sp) \n\
744  c.fsdsp ft8, 52*4(sp) \n\
745  c.fsdsp ft9, 54*4(sp) \n\
746  c.fsdsp ft10, 56*4(sp) \n\
747  c.fsdsp ft11, 58*4(sp) \n");\
748 }
749 
750 /*
751  * Restore FPU caller registers:
752  * NOTE: To simplify the logic, the FPU caller registers are always stored at word offset 20 in the stack
753  */
754 #define RESTORE_FPU_CONTEXT() { \
755  __asm volatile("\n\
756  c.fldsp ft0, 20*4(sp)\n\
757  c.fldsp ft1, 22*4(sp) \n\
758  c.fldsp ft2, 24*4(sp) \n\
759  c.fldsp ft3, 26*4(sp) \n\
760  c.fldsp ft4, 28*4(sp) \n\
761  c.fldsp ft5, 30*4(sp) \n\
762  c.fldsp ft6, 32*4(sp) \n\
763  c.fldsp ft7, 34*4(sp) \n\
764  c.fldsp fa0, 36*4(sp) \n\
765  c.fldsp fa1, 38*4(sp) \n\
766  c.fldsp fa2, 40*4(sp) \n\
767  c.fldsp fa3, 42*4(sp) \n\
768  c.fldsp fa4, 44*4(sp) \n\
769  c.fldsp fa5, 46*4(sp) \n\
770  c.fldsp fa6, 48*4(sp) \n\
771  c.fldsp fa7, 50*4(sp) \n\
772  c.fldsp ft8, 52*4(sp) \n\
773  c.fldsp ft9, 54*4(sp) \n\
774  c.fldsp ft10, 56*4(sp) \n\
775  c.fldsp ft11, 58*4(sp) \n");\
776 }
777 #endif
778 #endif
779 #else
780 #define SAVE_FPU_CONTEXT()
781 #define RESTORE_FPU_CONTEXT()
782 #endif
783 
784 #ifdef __ICCRISCV__
788 #define SAVE_CALLER_CONTEXT() { \
789  __asm volatile("addi sp, sp, %0" : : "i"(-CONTEXT_REG_NUM) :);\
790  __asm volatile("\n\
791  c.swsp ra, 0*4 \n\
792  c.swsp t0, 1*4 \n\
793  c.swsp t1, 2*4 \n\
794  c.swsp t2, 3*4 \n\
795  c.swsp s0, 4*4 \n\
796  c.swsp s1, 5*4 \n\
797  c.swsp a0, 6*4 \n\
798  c.swsp a1, 7*4 \n\
799  c.swsp a2, 8*4 \n\
800  c.swsp a3, 9*4 \n\
801  c.swsp a4, 10*4 \n\
802  c.swsp a5, 11*4 \n\
803  c.swsp a6, 12*4 \n\
804  c.swsp a7, 13*4 \n\
805  c.swsp s2, 14*4 \n\
806  c.swsp s3, 15*4 \n\
807  c.swsp t3, 16*4 \n\
808  c.swsp t4, 17*4 \n\
809  c.swsp t5, 18*4 \n\
810  c.swsp t6, 19*4"); \
811  SAVE_FPU_CONTEXT(); \
812 }
813 
817 #define RESTORE_CALLER_CONTEXT() { \
818  __asm volatile("\n\
819  c.lwsp ra, 0*4 \n\
820  c.lwsp t0, 1*4 \n\
821  c.lwsp t1, 2*4 \n\
822  c.lwsp t2, 3*4 \n\
823  c.lwsp s0, 4*4 \n\
824  c.lwsp s1, 5*4 \n\
825  c.lwsp a0, 6*4 \n\
826  c.lwsp a1, 7*4 \n\
827  c.lwsp a2, 8*4 \n\
828  c.lwsp a3, 9*4 \n\
829  c.lwsp a4, 10*4 \n\
830  c.lwsp a5, 11*4 \n\
831  c.lwsp a6, 12*4 \n\
832  c.lwsp a7, 13*4 \n\
833  c.lwsp s2, 14*4 \n\
834  c.lwsp s3, 15*4 \n\
835  c.lwsp t3, 16*4 \n\
836  c.lwsp t4, 17*4 \n\
837  c.lwsp t5, 18*4 \n\
838  c.lwsp t6, 19*4 \n");\
839  RESTORE_FPU_CONTEXT(); \
840  __asm volatile("addi sp, sp, %0" : : "i"(CONTEXT_REG_NUM) :);\
841 }
842 #else
846 #define SAVE_CALLER_CONTEXT() { \
847  __asm volatile("addi sp, sp, %0" : : "i"(-CONTEXT_REG_NUM) :);\
848  __asm volatile("\n\
849  c.swsp ra, 0*4(sp) \n\
850  c.swsp t0, 1*4(sp) \n\
851  c.swsp t1, 2*4(sp) \n\
852  c.swsp t2, 3*4(sp) \n\
853  c.swsp s0, 4*4(sp) \n\
854  c.swsp s1, 5*4(sp) \n\
855  c.swsp a0, 6*4(sp) \n\
856  c.swsp a1, 7*4(sp) \n\
857  c.swsp a2, 8*4(sp) \n\
858  c.swsp a3, 9*4(sp) \n\
859  c.swsp a4, 10*4(sp) \n\
860  c.swsp a5, 11*4(sp) \n\
861  c.swsp a6, 12*4(sp) \n\
862  c.swsp a7, 13*4(sp) \n\
863  c.swsp s2, 14*4(sp) \n\
864  c.swsp s3, 15*4(sp) \n\
865  c.swsp t3, 16*4(sp) \n\
866  c.swsp t4, 17*4(sp) \n\
867  c.swsp t5, 18*4(sp) \n\
868  c.swsp t6, 19*4(sp)"); \
869  SAVE_FPU_CONTEXT(); \
870 }
871 
875 #define RESTORE_CALLER_CONTEXT() { \
876  __asm volatile("\n\
877  c.lwsp ra, 0*4(sp) \n\
878  c.lwsp t0, 1*4(sp) \n\
879  c.lwsp t1, 2*4(sp) \n\
880  c.lwsp t2, 3*4(sp) \n\
881  c.lwsp s0, 4*4(sp) \n\
882  c.lwsp s1, 5*4(sp) \n\
883  c.lwsp a0, 6*4(sp) \n\
884  c.lwsp a1, 7*4(sp) \n\
885  c.lwsp a2, 8*4(sp) \n\
886  c.lwsp a3, 9*4(sp) \n\
887  c.lwsp a4, 10*4(sp) \n\
888  c.lwsp a5, 11*4(sp) \n\
889  c.lwsp a6, 12*4(sp) \n\
890  c.lwsp a7, 13*4(sp) \n\
891  c.lwsp s2, 14*4(sp) \n\
892  c.lwsp s3, 15*4(sp) \n\
893  c.lwsp t3, 16*4(sp) \n\
894  c.lwsp t4, 17*4(sp) \n\
895  c.lwsp t5, 18*4(sp) \n\
896  c.lwsp t6, 19*4(sp) \n");\
897  RESTORE_FPU_CONTEXT(); \
898  __asm volatile("addi sp, sp, %0" : : "i"(CONTEXT_REG_NUM) :);\
899 }
900 #endif
901 
902 #ifdef __riscv_flen
903 #define SAVE_FPU_STATE() { \
904  __asm volatile("frcsr s1\n"); \
905 }
906 
907 #define RESTORE_FPU_STATE() { \
908  __asm volatile("fscsr s1\n"); \
909 }
910 #else
911 #define SAVE_FPU_STATE()
912 #define RESTORE_FPU_STATE()
913 #endif
914 
915 #ifdef __riscv_dsp
916 /*
917  * Save DSP context
918  * NOTE: DSP context registers are stored at word offset 41 in the stack
919  */
920 #define SAVE_DSP_CONTEXT() { \
921  __asm volatile("csrrs s0, %0, x0\n" ::"i"(CSR_UCODE):); \
922 }
923 /*
924  * @brief Restore DSP context
925  * @note DSP context registers are stored at word offset 41 in the stack
926  */
927 #define RESTORE_DSP_CONTEXT() {\
928  __asm volatile("csrw %0, s0\n" ::"i"(CSR_UCODE):); \
929 }
930 
931 #else
932 #define SAVE_DSP_CONTEXT()
933 #define RESTORE_DSP_CONTEXT()
934 #endif
935 
936 /*
937  * @brief Enter Nested IRQ Handling
938  * @note To simplify the logic, Nested IRQ related registers are stored in the stack as below:
939  * MCAUSE - word offset 16 (not used in the vectored mode)
940  * EPC - word offset 17
941  * MSTATUS = word offset 18
942  * MXSTATUS = word offset 19
943  */
944 #define ENTER_NESTED_IRQ_HANDLING_M() { \
945  __asm volatile("\n\
946  csrr s2, mepc \n\
947  csrr s3, mstatus \n");\
948  SAVE_FPU_STATE(); \
949  SAVE_DSP_CONTEXT(); \
950  __asm volatile("csrsi mstatus, 8"); \
951 }
952 
953 /*
954  * @brief Complete IRQ Handling
955  */
956 #define COMPLETE_IRQ_HANDLING_M(irq_num) { \
957  __asm volatile("csrci mstatus, 8"); \
958  __asm volatile("lui a4, 0xe4200"); \
959  __asm volatile("li a3, %0" : : "i" (irq_num) :); \
960  __asm volatile("sw a3, 4(a4)"); \
961 }
962 
963 /*
964  * @brief Exit Nested IRQ Handling
965  * @note To simplify the logic, Nested IRQ related registers are stored in the stack as below:
966  * MCAUSE - word offset 16 (not used in the vectored mode)
967  * EPC - word offset 17
968  * MSTATUS = word offset 18
969  * MXSTATUS = word offset 19
970  */
971 #define EXIT_NESTED_IRQ_HANDLING_M() { \
972  __asm volatile("\n\
973  csrw mstatus, s3 \n\
974  csrw mepc, s2 \n");\
975  RESTORE_FPU_STATE(); \
976  RESTORE_DSP_CONTEXT(); \
977 }
978 
979 
980 #define ENTER_NESTED_IRQ_HANDLING_S() {\
981  __asm volatile("\n\
982  csrr s2, sepc \n\
983  csrr s3, sstatus \n");\
984  SAVE_FPU_STATE(); \
985  SAVE_DSP_CONTEXT(); \
986  __asm volatile("csrsi sstatus, 2"); \
987 }
988 #define COMPLETE_IRQ_HANDLING_S(irq_num) {\
989  __asm volatile("csrci sstatus, 2"); \
990  __asm volatile("lui a4, 0xe4201"); \
991  __asm volatile("li a3, %0" : : "i" (irq_num) :); \
992  __asm volatile("sw a3, 4(a4)"); \
993 }
994 
995 /*
996  * @brief Exit Nested IRQ Handling at supervisor mode
997  * @note To simplify the logic, Nested IRQ related registers are stored in the stack as below:
998  * SCAUSE - word offset 16 (not used in the vectored mode)
999  * EPC - word offset 17
1000  * SSTATUS = word offset 18
1001  */
1002 #define EXIT_NESTED_IRQ_HANDLING_S() { \
1003  __asm volatile("\n\
1004  csrw sstatus, s3 \n\
1005  csrw sepc, s2 \n");\
1006  RESTORE_FPU_STATE(); \
1007  RESTORE_DSP_CONTEXT(); \
1008 }
1009 
1010 /* @brief Nested IRQ entry macro : Save CSRs and enable global irq. */
1011 #define NESTED_IRQ_ENTER() \
1012  SAVE_CSR(CSR_MEPC) \
1013  SAVE_CSR(CSR_MSTATUS) \
1014  SAVE_MXSTATUS() \
1015  SAVE_FCSR() \
1016  SAVE_UCODE() \
1017  set_csr(CSR_MSTATUS, CSR_MSTATUS_MIE_MASK);
1018 
1019 /* @brief Nested IRQ exit macro : Restore CSRs */
1020 #define NESTED_IRQ_EXIT() \
1021  RESTORE_CSR(CSR_MSTATUS) \
1022  RESTORE_CSR(CSR_MEPC) \
1023  RESTORE_MXSTATUS() \
1024  RESTORE_FCSR() \
1025  RESTORE_UCODE()
1026 
1027 #ifdef __cplusplus
1028 #define EXTERN_C extern "C"
1029 #else
1030 #define EXTERN_C
1031 #endif
1032 
1033 #define ISR_NAME_M(irq_num) default_isr_##irq_num
1034 #define ISR_NAME_S(irq_num) default_isr_s_##irq_num
1041 #if !defined(USE_NONVECTOR_MODE) || (USE_NONVECTOR_MODE == 0)
1042 #if defined(CONFIG_FREERTOS) && CONFIG_FREERTOS
1043 #define FREERTOS_VECTOR_ISR_WRAPPER_NAME(irq_num) irq_handler_wrapper_##irq_num
1044 #define SDK_DECLARE_EXT_ISR_M(irq_num, isr) \
1045 void isr(void) __attribute__((section(".isr_vector"))); \
1046 EXTERN_C void FREERTOS_VECTOR_ISR_WRAPPER_NAME(irq_num)(void) __attribute__((section(".isr_vector"))); \
1047 void FREERTOS_VECTOR_ISR_WRAPPER_NAME(irq_num)(void) \
1048 { \
1049  isr();\
1050 }
1051 
1058 #define SDK_DECLARE_EXT_ISR_S(irq_num, isr) \
1059 void isr(void) __attribute__((section(".isr_s_vector")));\
1060 EXTERN_C void FREERTOS_VECTOR_ISR_WRAPPER_NAME(irq_num)(void) __attribute__((section(".isr_s_vector")));\
1061 void FREERTOS_VECTOR_ISR_WRAPPER_NAME(irq_num)(void) \
1062 { \
1063  isr();\
1064 }
1065 #else
1066 #define SDK_DECLARE_EXT_ISR_M(irq_num, isr) \
1067 void isr(void) __attribute__((section(".isr_vector")));\
1068 EXTERN_C void ISR_NAME_M(irq_num)(void) __attribute__((section(".isr_vector")));\
1069 void ISR_NAME_M(irq_num)(void) \
1070 { \
1071  SAVE_CALLER_CONTEXT(); \
1072  ENTER_NESTED_IRQ_HANDLING_M();\
1073  __asm volatile("la t1, %0\n\t" : : "i" (isr) : );\
1074  __asm volatile("jalr t1\n");\
1075  COMPLETE_IRQ_HANDLING_M(irq_num);\
1076  EXIT_NESTED_IRQ_HANDLING_M();\
1077  RESTORE_CALLER_CONTEXT();\
1078  __asm volatile("fence io, io");\
1079  __asm volatile("mret\n");\
1080 }
1081 
1088 #define SDK_DECLARE_EXT_ISR_S(irq_num, isr) \
1089 void isr(void) __attribute__((section(".isr_s_vector")));\
1090 EXTERN_C void ISR_NAME_S(irq_num)(void) __attribute__((section(".isr_s_vector")));\
1091 void ISR_NAME_S(irq_num)(void) {\
1092  SAVE_CALLER_CONTEXT(); \
1093  ENTER_NESTED_IRQ_HANDLING_S();\
1094  __asm volatile("la t1, %0\n\t" : : "i" (isr) : );\
1095  __asm volatile("jalr t1\n");\
1096  COMPLETE_IRQ_HANDLING_S(irq_num);\
1097  EXIT_NESTED_IRQ_HANDLING_S();\
1098  RESTORE_CALLER_CONTEXT();\
1099  __asm volatile("fence io, io");\
1100  __asm volatile("sret\n");\
1101 }
1102 #endif
1103 #else
1104 
1105 #define SDK_DECLARE_EXT_ISR_M(irq_num, isr) \
1106 void isr(void) __attribute__((section(".isr_vector")));\
1107 EXTERN_C void ISR_NAME_M(irq_num)(void) __attribute__((section(".isr_vector")));\
1108 void ISR_NAME_M(irq_num)(void) { \
1109  isr(); \
1110 }
1111 
1112 #define SDK_DECLARE_EXT_ISR_S(irq_num, isr) \
1113 void isr(void) __attribute__((section(".isr_vector")));\
1114 EXTERN_C void ISR_NAME_S(irq_num)(void) __attribute__((section(".isr_vector")));\
1115 void ISR_NAME_S(irq_num)(void) { \
1116  isr(); \
1117 }
1118 
1119 #endif
1120 
1121 
1127 #define SDK_DECLARE_MCHTMR_ISR(isr) \
1128 void isr(void) __attribute__((section(".isr_vector")));\
1129 EXTERN_C void mchtmr_isr(void) __attribute__((section(".isr_vector"))); \
1130 void mchtmr_isr(void) {\
1131  isr();\
1132 }
1133 
1139 #define SDK_DECLARE_SWI_ISR(isr)\
1140 void isr(void) __attribute__((section(".isr_vector")));\
1141 EXTERN_C void swi_isr(void) __attribute__((section(".isr_vector"))); \
1142 void swi_isr(void) {\
1143  isr();\
1144 }
1145 
1146 /* Supervisor mode */
1147 
1153 #define SDK_DECLARE_MCHTMR_ISR_S(isr) \
1154 void isr(void) __attribute__((section(".isr_vector")));\
1155 EXTERN_C void mchtmr_s_isr(void) __attribute__((section(".isr_vector"))); \
1156 void mchtmr_s_isr(void) {\
1157  isr();\
1158 }
1159 
1165 #define SDK_DECLARE_SWI_ISR_S(isr)\
1166 void isr(void) __attribute__((section(".isr_vector")));\
1167 EXTERN_C void swi_s_isr(void) __attribute__((section(".isr_vector"))); \
1168 void swi_s_isr(void) {\
1169  isr();\
1170 }
1171 
1172 #define CSR_MSTATUS_MPP_S_MODE (0x1)
1173 #define MODE_SWITCH_FROM_M(mstatus, mepc, label, mode) \
1174 do { \
1175  if (label) { \
1176  write_csr(mepc, label); \
1177  } \
1178  clear_csr(mstatus, CSR_MSTATUS_MPP_MASK); \
1179  set_csr(mstatus, CSR_MSTATUS_MPP_SET(mode)); \
1180 } while(0)
1181 
1182 typedef void (*s_mode_entry)(void);
1183 
1189 static inline void switch_to_s_mode(s_mode_entry entry)
1190 {
1191  write_csr(CSR_SEPC, entry);
1193  if (entry) {
1194  __asm("mret");
1195  }
1196 }
1197 #ifdef __cplusplus
1198 }
1199 #endif
1200 
1204 #endif /* HPM_INTERRUPT_H */
#define CSR_MIE_MEIE_MASK
Definition: hpm_csr_regs.h:734
#define CSR_MEPC
Definition: hpm_csr_regs.h:31
#define CSR_MSTATUS
Definition: hpm_csr_regs.h:21
#define CSR_MIE_MTIE_MASK
Definition: hpm_csr_regs.h:758
#define CSR_MIE
Definition: hpm_csr_regs.h:23
#define CSR_MIE_MSIE_MASK
Definition: hpm_csr_regs.h:782
#define HPM_PLICSW_BASE
Definition: hpm_soc.h:94
#define HPM_PLIC_BASE
Definition: hpm_soc.h:80
#define CSR_SEPC
Definition: hpm_csr_regs.h:27
#define CSR_SSTATUS
Definition: hpm_csr_regs.h:21
#define CSR_SIE_SEIE_MASK
Definition: hpm_csr_regs.h:677
#define CSR_SIE_SSIE_MASK
Definition: hpm_csr_regs.h:725
#define CSR_SIP
Definition: hpm_csr_regs.h:30
#define CSR_SIE_STIE_MASK
Definition: hpm_csr_regs.h:701
#define CSR_MIDELEG
Definition: hpm_csr_regs.h:35
#define CSR_SIP_SSIP_MASK
Definition: hpm_csr_regs.h:889
#define CSR_SIE
Definition: hpm_csr_regs.h:24
static ATTR_ALWAYS_INLINE void intc_complete_irq(uint32_t target, uint32_t irq)
Complete IRQ.
Definition: hpm_interrupt.h:445
static ATTR_ALWAYS_INLINE void enable_global_irq(uint32_t mask)
Enable global IRQ with mask.
Definition: hpm_interrupt.h:34
static ATTR_ALWAYS_INLINE void intc_m_disable_swi(void)
Disable software interrupt.
Definition: hpm_interrupt.h:216
static ATTR_ALWAYS_INLINE void intc_s_complete_swi(void)
Complete software interrupt for supervisor mode.
Definition: hpm_interrupt.h:332
static ATTR_ALWAYS_INLINE void intc_s_trigger_swi(void)
Trigger software interrupt for supervisor mode.
Definition: hpm_interrupt.h:322
static ATTR_ALWAYS_INLINE void disable_irq_from_intc(void)
Disable IRQ from interrupt controller.
Definition: hpm_interrupt.h:73
static ATTR_ALWAYS_INLINE void intc_set_irq_priority(uint32_t irq, uint32_t priority)
Set interrupt priority.
Definition: hpm_interrupt.h:400
static ATTR_ALWAYS_INLINE void intc_disable_irq(uint32_t target, uint32_t irq)
Disable specific interrupt.
Definition: hpm_interrupt.h:411
static ATTR_ALWAYS_INLINE void intc_m_trigger_swi(void)
Trigger software interrupt.
Definition: hpm_interrupt.h:226
static ATTR_ALWAYS_INLINE void install_isr(uint32_t irq, uint32_t isr)
Install ISR for certain IRQ for ram based vector table.
Definition: hpm_interrupt.h:464
static ATTR_ALWAYS_INLINE void restore_s_global_irq(uint32_t mask)
Restore global IRQ with mask for supervisor mode.
Definition: hpm_interrupt.h:144
static ATTR_ALWAYS_INLINE void enable_irq_from_intc(void)
Enable IRQ from interrupt controller.
Definition: hpm_interrupt.h:64
static ATTR_ALWAYS_INLINE void restore_global_irq(uint32_t mask)
Restore global IRQ with mask.
Definition: hpm_interrupt.h:55
static ATTR_ALWAYS_INLINE void uninstall_s_isr(uint32_t irq)
Uninstall ISR for certain IRQ for ram based vector table for supervisor mode.
Definition: hpm_interrupt.h:501
static ATTR_ALWAYS_INLINE void enable_s_global_irq(uint32_t mask)
Enable global IRQ with mask for supervisor mode.
Definition: hpm_interrupt.h:123
static ATTR_ALWAYS_INLINE void intc_enable_irq(uint32_t target, uint32_t irq)
Definition: hpm_interrupt.h:389
static ATTR_ALWAYS_INLINE void install_s_isr(uint32_t irq, uint32_t isr)
Install ISR for certain IRQ for ram based vector table for supervisor mode.
Definition: hpm_interrupt.h:490
static ATTR_ALWAYS_INLINE void enable_s_irq_from_intc(void)
Enable IRQ from interrupt controller for supervisor mode.
Definition: hpm_interrupt.h:162
static ATTR_ALWAYS_INLINE void delegate_irq(uint32_t mask)
Delegate IRQ handling.
Definition: hpm_interrupt.h:100
static ATTR_ALWAYS_INLINE void undelegate_irq(uint32_t mask)
Undelegate IRQ handling.
Definition: hpm_interrupt.h:110
static ATTR_ALWAYS_INLINE void disable_mchtmr_irq(void)
Disable machine timer IRQ.
Definition: hpm_interrupt.h:90
static ATTR_ALWAYS_INLINE void intc_m_init_swi(void)
Initialize software interrupt.
Definition: hpm_interrupt.h:196
static ATTR_ALWAYS_INLINE void intc_m_enable_swi(void)
Enable software interrupt.
Definition: hpm_interrupt.h:206
static ATTR_ALWAYS_INLINE void intc_m_complete_swi(void)
Complete software interrupt.
Definition: hpm_interrupt.h:244
static ATTR_ALWAYS_INLINE void intc_s_disable_swi(void)
Disable software interrupt for supervisor mode.
Definition: hpm_interrupt.h:312
static void switch_to_s_mode(s_mode_entry entry)
Switch mode to supervisor from machine.
Definition: hpm_interrupt.h:1189
static ATTR_ALWAYS_INLINE void enable_s_mchtmr_irq(void)
Enable machine timer IRQ for supervisor mode.
Definition: hpm_interrupt.h:170
static ATTR_ALWAYS_INLINE void intc_set_threshold(uint32_t target, uint32_t threshold)
Set interrupt threshold.
Definition: hpm_interrupt.h:422
static ATTR_ALWAYS_INLINE void uninstall_isr(uint32_t irq)
Uninstall ISR for certain IRQ for ram based vector table.
Definition: hpm_interrupt.h:475
static ATTR_ALWAYS_INLINE uint32_t disable_s_global_irq(uint32_t mask)
Disable global IRQ with mask and return sstatus for supervisor mode.
Definition: hpm_interrupt.h:134
static ATTR_ALWAYS_INLINE uint32_t intc_claim_irq(uint32_t target)
Claim IRQ.
Definition: hpm_interrupt.h:433
static ATTR_ALWAYS_INLINE void intc_m_claim_swi(void)
Claim software interrupt.
Definition: hpm_interrupt.h:235
static ATTR_ALWAYS_INLINE uint32_t disable_global_irq(uint32_t mask)
Disable global IRQ with mask and return mstatus.
Definition: hpm_interrupt.h:45
static ATTR_ALWAYS_INLINE void disable_s_mchtmr_irq(void)
Disable machine timer IRQ.
Definition: hpm_interrupt.h:179
static ATTR_ALWAYS_INLINE void enable_mchtmr_irq(void)
Enable machine timer IRQ.
Definition: hpm_interrupt.h:81
static ATTR_ALWAYS_INLINE void disable_s_irq_from_intc(void)
Disable IRQ from interrupt controller for supervisor mode.
Definition: hpm_interrupt.h:153
static ATTR_ALWAYS_INLINE void intc_s_enable_swi(void)
Enable software interrupt for supervisor mode.
Definition: hpm_interrupt.h:302
#define CSR_MSTATUS_MPP_S_MODE
Definition: hpm_interrupt.h:1172
void default_s_irq_entry(void)
#define MODE_SWITCH_FROM_M(mstatus, mepc, label, mode)
Definition: hpm_interrupt.h:1173
void default_irq_entry(void)
#define PLICSWI
Definition: hpm_interrupt.h:190
void(* s_mode_entry)(void)
Definition: hpm_interrupt.h:1184
write_csr((0x7CC), cmd)
#define HPM_PLIC_TARGET_M_MODE
Definition: hpm_plic_drv.h:17
#define set_csr(csr_num, bit)
set bits in csr
Definition: riscv_core.h:58
#define clear_csr(csr_num, bit)
clear bits in csr
Definition: riscv_core.h:30
#define read_clear_csr(csr_num, bit)
read and clear bits in csr
Definition: riscv_core.h:40