NMSIS-Core  Version 1.4.0
NMSIS-Core support for Nuclei processor-based devices
core_feature_eclic.h
1 /*
2  * Copyright (c) 2019 Nuclei Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Licensed under the Apache License, Version 2.0 (the License); you may
7  * not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 #ifndef __CORE_FEATURE_ECLIC__
19 #define __CORE_FEATURE_ECLIC__
24 /*
25  * ECLIC Feature Configuration Macro:
26  * 1. __ECLIC_PRESENT: Define whether Enhanced Core Local Interrupt Controller (ECLIC) Unit is present or not
27  * * 0: Not present
28  * * 1: Present
29  * 2. __ECLIC_BASEADDR: Base address of the ECLIC unit.
30  * 3. __ECLIC_INTCTLBITS: Optional, if defined, it should set to the value of ECLIC_GetInfoCtlbits(), define the number of hardware bits are actually implemented in the clicintctl registers.
31  * Valid number is 1 - 8.
32  * 4. __ECLIC_INTNUM: Define the external interrupt number of ECLIC Unit
33  * 5. __TEE_PRESENT: Define whether TEE feature present, if present, ECLIC will present with S-Mode ECLIC feature
34  * * 0: Not present
35  * * 1: Present
36  *
37  */
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41 
42 #include "core_feature_base.h"
43 
44 #if defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1)
56 typedef union
57 {
58  struct {
59  __IM uint8_t _reserved0:1;
60  __IOM uint8_t nlbits:4;
61  __IM uint8_t nmbits:2;
62  __IM uint8_t _reserved1:1;
63  } b;
64  uint8_t w;
65 } CLICCFG_Type;
66 
70 typedef union {
71  struct {
72  __IM uint32_t numint:13;
73  __IM uint32_t version:8;
74  __IM uint32_t intctlbits:4;
75  __IM uint32_t _reserved0:7;
76  } b;
77  __IM uint32_t w;
79 
83 typedef struct {
84  __IOM uint8_t INTIP;
85  __IOM uint8_t INTIE;
86  __IOM uint8_t INTATTR;
87  __IOM uint8_t INTCTRL;
89 
93 typedef struct {
94  __IOM uint8_t CFG;
95  __IM uint8_t RESERVED0[3];
96  __IM uint32_t INFO;
97  __IM uint8_t RESERVED1;
98 #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
99  __IOM uint8_t STH;
100 #else
101  __IM uint8_t RESERVED2;
102 #endif
103  __IM uint8_t RESERVED3;
104  __IOM uint8_t MTH;
105  uint32_t RESERVED4[1021];
106 #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
107  CLIC_CTRL_Type CTRL[1024];
108  __IM uint32_t RESERVED5[2];
109  __IM uint8_t RESERVED6;
110  __IOM uint8_t SSTH;
111  __IM uint8_t RESERVED7;
112  __IM uint8_t RESERVED8;
113  __IM uint32_t RESERVED9[1021];
114  CLIC_CTRL_Type SCTRL[1024];
115 #else
116  CLIC_CTRL_Type CTRL[4096];
117 #endif
118 } CLIC_Type;
119 
120 #define CLIC_CLICCFG_NLBIT_Pos 1U
121 #define CLIC_CLICCFG_NLBIT_Msk (0xFUL << CLIC_CLICCFG_NLBIT_Pos)
123 #define CLIC_CLICINFO_CTLBIT_Pos 21U
124 #define CLIC_CLICINFO_CTLBIT_Msk (0xFUL << CLIC_CLICINFO_CTLBIT_Pos)
126 #define CLIC_CLICINFO_VER_Pos 13U
127 #define CLIC_CLICINFO_VER_Msk (0xFFUL << CLIC_CLICINFO_VER_Pos)
129 #define CLIC_CLICINFO_NUM_Pos 0U
130 #define CLIC_CLICINFO_NUM_Msk (0x1FFFUL << CLIC_CLICINFO_NUM_Pos)
132 #define CLIC_INTIP_IP_Pos 0U
133 #define CLIC_INTIP_IP_Msk (0x1UL << CLIC_INTIP_IP_Pos)
135 #define CLIC_INTIE_IE_Pos 0U
136 #define CLIC_INTIE_IE_Msk (0x1UL << CLIC_INTIE_IE_Pos)
138 #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
139 #define CLIC_INTATTR_MODE_Pos 6U
140 #define CLIC_INTATTR_MODE_Msk (0x3U << CLIC_INTATTR_MODE_Pos)
141 #endif
142 
143 #define CLIC_INTATTR_TRIG_Pos 1U
144 #define CLIC_INTATTR_TRIG_Msk (0x3UL << CLIC_INTATTR_TRIG_Pos)
146 #define CLIC_INTATTR_SHV_Pos 0U
147 #define CLIC_INTATTR_SHV_Msk (0x1UL << CLIC_INTATTR_SHV_Pos)
149 #define ECLIC_MAX_NLBITS 8U
150 #define ECLIC_MODE_MTVEC_Msk 3U
152 #define ECLIC_NON_VECTOR_INTERRUPT 0x0
153 #define ECLIC_VECTOR_INTERRUPT 0x1
156 typedef enum ECLIC_TRIGGER {
160  ECLIC_MAX_TRIGGER = 0x3
162 
163 #ifndef __ECLIC_BASEADDR
164 /* Base address of ECLIC(__ECLIC_BASEADDR) should be defined in <Device.h> */
165 #error "__ECLIC_BASEADDR is not defined, please check!"
166 #endif
167 
168 #ifndef __ECLIC_INTCTLBITS
169 /* Define __ECLIC_INTCTLBITS to get via ECLIC->INFO if not defined */
170 #define __ECLIC_INTCTLBITS (__ECLIC_GetInfoCtlbits())
171 #endif
172 
173 /* ECLIC Memory mapping of Device */
174 #define ECLIC_BASE __ECLIC_BASEADDR
175 #define ECLIC ((CLIC_Type *) ECLIC_BASE) /* end of group NMSIS_Core_ECLIC_Registers */
178 
179 /* ########################## ECLIC functions #################################### */
197 /* The following enum IRQn definition in this file
198  * is only used for doxygen documentation generation,
199  * The <Device>.h is the real file to define it by vendor
200  */
201 #if defined(__ONLY_FOR_DOXYGEN_DOCUMENT_GENERATION__)
202 typedef enum IRQn {
203  /* ========= Nuclei N/NX Core Specific Interrupt Numbers =========== */
204  /* Core Internal Interrupt IRQn definitions */
225  /* ========= Device Specific Interrupt Numbers =================== */
226  /* ToDo: add here your device specific external interrupt numbers.
227  * 19~max(NUM_INTERRUPT, 1023) is reserved number for user.
228  * Maxmum interrupt supported could get from clicinfo.NUM_INTERRUPT.
229  * According the interrupt handlers defined in startup_Device.S
230  * eg.: Interrupt for Timer#1 eclic_tim1_handler -> TIM1_IRQn */
233 } IRQn_Type;
234 #endif /* __ONLY_FOR_DOXYGEN_DOCUMENT_GENERATION__ */
235 
236 #ifdef NMSIS_ECLIC_VIRTUAL
237  #ifndef NMSIS_ECLIC_VIRTUAL_HEADER_FILE
238  #define NMSIS_ECLIC_VIRTUAL_HEADER_FILE "nmsis_eclic_virtual.h"
239  #endif
240  #include NMSIS_ECLIC_VIRTUAL_HEADER_FILE
241 #else
242  #define ECLIC_SetCfgNlbits __ECLIC_SetCfgNlbits
243  #define ECLIC_GetCfgNlbits __ECLIC_GetCfgNlbits
244  #define ECLIC_GetInfoVer __ECLIC_GetInfoVer
245  #define ECLIC_GetInfoCtlbits __ECLIC_GetInfoCtlbits
246  #define ECLIC_GetInfoNum __ECLIC_GetInfoNum
247  #define ECLIC_SetMth __ECLIC_SetMth
248  #define ECLIC_GetMth __ECLIC_GetMth
249  #define ECLIC_EnableIRQ __ECLIC_EnableIRQ
250  #define ECLIC_GetEnableIRQ __ECLIC_GetEnableIRQ
251  #define ECLIC_DisableIRQ __ECLIC_DisableIRQ
252  #define ECLIC_SetPendingIRQ __ECLIC_SetPendingIRQ
253  #define ECLIC_GetPendingIRQ __ECLIC_GetPendingIRQ
254  #define ECLIC_ClearPendingIRQ __ECLIC_ClearPendingIRQ
255  #define ECLIC_SetTrigIRQ __ECLIC_SetTrigIRQ
256  #define ECLIC_GetTrigIRQ __ECLIC_GetTrigIRQ
257  #define ECLIC_SetShvIRQ __ECLIC_SetShvIRQ
258  #define ECLIC_GetShvIRQ __ECLIC_GetShvIRQ
259  #define ECLIC_SetCtrlIRQ __ECLIC_SetCtrlIRQ
260  #define ECLIC_GetCtrlIRQ __ECLIC_GetCtrlIRQ
261  #define ECLIC_SetLevelIRQ __ECLIC_SetLevelIRQ
262  #define ECLIC_GetLevelIRQ __ECLIC_GetLevelIRQ
263  #define ECLIC_SetPriorityIRQ __ECLIC_SetPriorityIRQ
264  #define ECLIC_GetPriorityIRQ __ECLIC_GetPriorityIRQ
265 
266  /* For TEE */
267 #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
268  #define ECLIC_SetModeIRQ __ECLIC_SetModeIRQ
269  #define ECLIC_SetSth __ECLIC_SetSth
270  #define ECLIC_GetSth __ECLIC_GetSth
271  #define ECLIC_SetTrigIRQ_S __ECLIC_SetTrigIRQ_S
272  #define ECLIC_GetTrigIRQ_S __ECLIC_GetTrigIRQ_S
273  #define ECLIC_SetShvIRQ_S __ECLIC_SetShvIRQ_S
274  #define ECLIC_GetShvIRQ_S __ECLIC_GetShvIRQ_S
275  #define ECLIC_SetCtrlIRQ_S __ECLIC_SetCtrlIRQ_S
276  #define ECLIC_GetCtrlIRQ_S __ECLIC_GetCtrlIRQ_S
277  #define ECLIC_SetLevelIRQ_S __ECLIC_SetLevelIRQ_S
278  #define ECLIC_GetLevelIRQ_S __ECLIC_GetLevelIRQ_S
279  #define ECLIC_SetPriorityIRQ_S __ECLIC_SetPriorityIRQ_S
280  #define ECLIC_GetPriorityIRQ_S __ECLIC_GetPriorityIRQ_S
281  #define ECLIC_EnableIRQ_S __ECLIC_EnableIRQ_S
282  #define ECLIC_GetEnableIRQ_S __ECLIC_GetEnableIRQ_S
283  #define ECLIC_DisableIRQ_S __ECLIC_DisableIRQ_S
284 
285 #endif
286 #endif /* NMSIS_ECLIC_VIRTUAL */
287 
288 #ifdef NMSIS_VECTAB_VIRTUAL
289  #ifndef NMSIS_VECTAB_VIRTUAL_HEADER_FILE
290  #define NMSIS_VECTAB_VIRTUAL_HEADER_FILE "nmsis_vectab_virtual.h"
291  #endif
292  #include NMSIS_VECTAB_VIRTUAL_HEADER_FILE
293 #else
294  #define ECLIC_SetVector __ECLIC_SetVector
295  #define ECLIC_GetVector __ECLIC_GetVector
296 
297 #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
298  #define ECLIC_SetVector_S __ECLIC_SetVector_S
299  #define ECLIC_GetVector_S __ECLIC_GetVector_S
300 #endif
301 #endif /* (NMSIS_VECTAB_VIRTUAL) */
302 
314 {
315  uint8_t temp = ECLIC->CFG;
316 
317  ECLIC->CFG = (temp & ~CLIC_CLICCFG_NLBIT_Msk) | \
318  ((uint8_t)((nlbits << CLIC_CLICCFG_NLBIT_Pos) & CLIC_CLICCFG_NLBIT_Msk));
319 }
320 
332 {
333  return ((uint32_t)((ECLIC->CFG & CLIC_CLICCFG_NLBIT_Msk) >> CLIC_CLICCFG_NLBIT_Pos));
334 }
335 
348 {
349  return ((uint32_t)((ECLIC->INFO & CLIC_CLICINFO_VER_Msk) >> CLIC_CLICINFO_VER_Pos));
350 }
351 
365 {
366  return ((uint32_t)((ECLIC->INFO & CLIC_CLICINFO_CTLBIT_Msk) >> CLIC_CLICINFO_CTLBIT_Pos));
367 }
368 
381 {
382  return ((uint32_t)((ECLIC->INFO & CLIC_CLICINFO_NUM_Msk) >> CLIC_CLICINFO_NUM_Pos));
383 }
384 
394 {
395  ECLIC->MTH = mth;
396 }
397 
407 {
408  return (ECLIC->MTH);
409 }
410 
411 
423 {
424  ECLIC->CTRL[IRQn].INTIE |= CLIC_INTIE_IE_Msk;
425 }
426 
442 {
443  return ((uint32_t) (ECLIC->CTRL[IRQn].INTIE) & CLIC_INTIE_IE_Msk);
444 }
445 
457 {
458  ECLIC->CTRL[IRQn].INTIE &= ~CLIC_INTIE_IE_Msk;
459 }
460 
476 {
477  return ((uint32_t)(ECLIC->CTRL[IRQn].INTIP) & CLIC_INTIP_IP_Msk);
478 }
479 
492 {
493  ECLIC->CTRL[IRQn].INTIP |= CLIC_INTIP_IP_Msk;
494 }
495 
509 {
510  ECLIC->CTRL[IRQn].INTIP &= ~CLIC_INTIP_IP_Msk;
511 }
512 
530 {
531  uint8_t temp = ECLIC->CTRL[IRQn].INTATTR;
532 
533  ECLIC->CTRL[IRQn].INTATTR = (temp & ~CLIC_INTATTR_TRIG_Msk) | \
534  ((uint8_t)(trig << CLIC_INTATTR_TRIG_Pos));
535 }
536 
553 {
554  return ((uint32_t)(((ECLIC->CTRL[IRQn].INTATTR) & CLIC_INTATTR_TRIG_Msk) >> CLIC_INTATTR_TRIG_Pos));
555 }
556 
571 {
572  uint8_t temp = ECLIC->CTRL[IRQn].INTATTR;
573 
574  ECLIC->CTRL[IRQn].INTATTR = (temp & ~CLIC_INTATTR_SHV_Msk) | \
575  ((uint8_t)(shv << CLIC_INTATTR_SHV_Pos));
576 }
577 
592 {
593  return ((uint32_t)(((ECLIC->CTRL[IRQn].INTATTR) & CLIC_INTATTR_SHV_Msk) >> CLIC_INTATTR_SHV_Pos));
594 }
595 
608 {
609  ECLIC->CTRL[IRQn].INTCTRL = intctrl;
610 }
611 
624 {
625  return (ECLIC->CTRL[IRQn].INTCTRL);
626 }
627 
644 {
645  uint8_t nlbits = __ECLIC_GetCfgNlbits();
646  uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
647 
648  if (nlbits == 0) {
649  return;
650  }
651 
652  if (nlbits > intctlbits) {
653  nlbits = intctlbits;
654  }
655  uint8_t maxlvl = ((1UL << nlbits) - 1);
656  if (lvl_abs > maxlvl) {
657  lvl_abs = maxlvl;
658  }
659  uint8_t lvl = lvl_abs << (ECLIC_MAX_NLBITS - nlbits);
660  uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ(IRQn);
661  cur_ctrl = cur_ctrl << nlbits;
662  cur_ctrl = cur_ctrl >> nlbits;
663  __ECLIC_SetCtrlIRQ(IRQn, (cur_ctrl | lvl));
664 }
665 
678 {
679  uint8_t nlbits = __ECLIC_GetCfgNlbits();
680  uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
681 
682  if (nlbits == 0) {
683  return 0;
684  }
685 
686  if (nlbits > intctlbits) {
687  nlbits = intctlbits;
688  }
689  uint8_t intctrl = __ECLIC_GetCtrlIRQ(IRQn);
690  uint8_t lvl_abs = intctrl >> (ECLIC_MAX_NLBITS - nlbits);
691  return lvl_abs;
692 }
693 
709 {
710  uint8_t nlbits = __ECLIC_GetCfgNlbits();
711  uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
712  if (nlbits < intctlbits) {
713  uint8_t maxpri = ((1UL << (intctlbits - nlbits)) - 1);
714  if (pri > maxpri) {
715  pri = maxpri;
716  }
717  pri = pri << (ECLIC_MAX_NLBITS - intctlbits);
718  uint8_t mask = ((uint8_t)(-1)) >> intctlbits;
719  pri = pri | mask;
720  uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ(IRQn);
721  cur_ctrl = cur_ctrl >> (ECLIC_MAX_NLBITS - nlbits);
722  cur_ctrl = cur_ctrl << (ECLIC_MAX_NLBITS - nlbits);
723  __ECLIC_SetCtrlIRQ(IRQn, (cur_ctrl | pri));
724  }
725 }
726 
739 {
740  uint8_t nlbits = __ECLIC_GetCfgNlbits();
741  uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
742  if (nlbits < intctlbits) {
743  uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ(IRQn);
744  uint8_t pri = cur_ctrl << nlbits;
745  pri = pri >> nlbits;
746  pri = pri >> (ECLIC_MAX_NLBITS - intctlbits);
747  return pri;
748  } else {
749  return 0;
750  }
751 }
752 
770 {
771  volatile unsigned long vec_base;
772  vec_base = ((unsigned long)__RV_CSR_READ(CSR_MTVT));
773  vec_base += ((unsigned long)IRQn) * sizeof(unsigned long);
774  (* (unsigned long *) vec_base) = vector;
775 #if (defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1))
776 #if (defined(__CCM_PRESENT) && (__CCM_PRESENT == 1))
777  MFlushDCacheLine((unsigned long)vec_base);
778 #endif
779 #endif
780 #if (defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1))
781 #if (defined(__CCM_PRESENT) && (__CCM_PRESENT == 1))
782  MInvalICacheLine((unsigned long)vec_base);
783 #else
784  __FENCE_I();
785 #endif
786 #endif
787 }
788 
802 {
803 #if __RISCV_XLEN == 32
804  return (*(uint32_t *)(__RV_CSR_READ(CSR_MTVT) + IRQn * 4));
805 #elif __RISCV_XLEN == 64
806  return (*(uint64_t *)(__RV_CSR_READ(CSR_MTVT) + IRQn * 8));
807 #else // TODO Need cover for XLEN=128 case in future
808  return (*(uint64_t *)(__RV_CSR_READ(CSR_MTVT) + IRQn * 8));
809 #endif
810 }
811 
812 #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
828 {
829  /*
830  * only 1 or 3 can be assigned to mode in one step.the default value of mode is 3,
831  * which can't be clear to 0 firstly, then OR it to 1
832  */
833  ECLIC->CTRL[IRQn].INTATTR = (uint8_t)(mode << CLIC_INTATTR_MODE_Pos) + \
834  (ECLIC->SCTRL[IRQn].INTATTR & (~CLIC_INTATTR_MODE_Msk));
835 }
836 
849 {
850  ECLIC->STH = sth;
851 }
852 
865 {
866  return (ECLIC->STH);
867 }
868 
886 {
887  uint8_t temp = ECLIC->SCTRL[IRQn].INTATTR;
888 
889  ECLIC->SCTRL[IRQn].INTATTR = (temp & ~CLIC_INTATTR_TRIG_Msk) | \
890  ((uint8_t)(trig << CLIC_INTATTR_TRIG_Pos));
891 }
892 
909 {
910  return ((uint8_t)(((ECLIC->SCTRL[IRQn].INTATTR) & CLIC_INTATTR_TRIG_Msk) >> CLIC_INTATTR_TRIG_Pos));
911 }
912 
913 
928 {
929  uint8_t temp = ECLIC->SCTRL[IRQn].INTATTR;
930 
931  ECLIC->SCTRL[IRQn].INTATTR = (temp & ~CLIC_INTATTR_SHV_Msk) | \
932  ((uint8_t)(shv << CLIC_INTATTR_SHV_Pos));
933 }
934 
949 {
950  return ((uint8_t)(((ECLIC->SCTRL[IRQn].INTATTR) & CLIC_INTATTR_SHV_Msk) >> CLIC_INTATTR_SHV_Pos));
951 }
952 
965 {
966  ECLIC->SCTRL[IRQn].INTCTRL = intctrl;
967 }
968 
981 {
982  return (ECLIC->SCTRL[IRQn].INTCTRL);
983 }
984 
1001 {
1002  uint8_t nlbits = __ECLIC_GetCfgNlbits();
1003  uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
1004 
1005  if (nlbits == 0) {
1006  return;
1007  }
1008 
1009  if (nlbits > intctlbits) {
1010  nlbits = intctlbits;
1011  }
1012  uint8_t maxlvl = ((1UL << nlbits) - 1);
1013  if (lvl_abs > maxlvl) {
1014  lvl_abs = maxlvl;
1015  }
1016  uint8_t lvl = lvl_abs << (ECLIC_MAX_NLBITS - nlbits);
1017  uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ_S(IRQn);
1018  cur_ctrl = cur_ctrl << nlbits;
1019  cur_ctrl = cur_ctrl >> nlbits;
1020  __ECLIC_SetCtrlIRQ_S(IRQn, (cur_ctrl | lvl));
1021 }
1022 
1023 
1036 {
1037  uint8_t nlbits = __ECLIC_GetCfgNlbits();
1038  uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
1039 
1040  if (nlbits == 0) {
1041  return 0;
1042  }
1043 
1044  if (nlbits > intctlbits) {
1045  nlbits = intctlbits;
1046  }
1047  uint8_t intctrl = __ECLIC_GetCtrlIRQ_S(IRQn);
1048  uint8_t lvl_abs = intctrl >> (ECLIC_MAX_NLBITS - nlbits);
1049  return lvl_abs;
1050 }
1051 
1067 {
1068  uint8_t nlbits = __ECLIC_GetCfgNlbits();
1069  uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
1070  if (nlbits < intctlbits) {
1071  uint8_t maxpri = ((1UL << (intctlbits - nlbits)) - 1);
1072  if (pri > maxpri) {
1073  pri = maxpri;
1074  }
1075  pri = pri << (ECLIC_MAX_NLBITS - intctlbits);
1076  uint8_t mask = ((uint8_t)(-1)) >> intctlbits;
1077  pri = pri | mask;
1078  uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ_S(IRQn);
1079  cur_ctrl = cur_ctrl >> (ECLIC_MAX_NLBITS - nlbits);
1080  cur_ctrl = cur_ctrl << (ECLIC_MAX_NLBITS - nlbits);
1081  __ECLIC_SetCtrlIRQ_S(IRQn, (cur_ctrl | pri));
1082  }
1083 }
1084 
1097 {
1098  uint8_t nlbits = __ECLIC_GetCfgNlbits();
1099  uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
1100  if (nlbits < intctlbits) {
1101  uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ_S(IRQn);
1102  uint8_t pri = cur_ctrl << nlbits;
1103  pri = pri >> nlbits;
1104  pri = pri >> (ECLIC_MAX_NLBITS - intctlbits);
1105  return pri;
1106  } else {
1107  return 0;
1108  }
1109 }
1110 
1122 {
1123  ECLIC->SCTRL[IRQn].INTIE |= CLIC_INTIE_IE_Msk;
1124 }
1125 
1141 {
1142  return ((uint8_t) (ECLIC->SCTRL[IRQn].INTIE) & CLIC_INTIE_IE_Msk);
1143 }
1144 
1156 {
1157  ECLIC->SCTRL[IRQn].INTIE &= ~CLIC_INTIE_IE_Msk;
1158 }
1159 
1177 {
1178  volatile unsigned long vec_base;
1179  vec_base = ((unsigned long)__RV_CSR_READ(CSR_STVT));
1180  vec_base += ((unsigned long)IRQn) * sizeof(unsigned long);
1181  (* (unsigned long *) vec_base) = vector;
1182 #if (defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1))
1183 #if (defined(__CCM_PRESENT) && (__CCM_PRESENT == 1))
1184  SFlushDCacheLine((unsigned long)vec_base);
1185 #endif
1186 #endif
1187 #if (defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1))
1188 #if (defined(__CCM_PRESENT) && (__CCM_PRESENT == 1))
1189  SInvalICacheLine((unsigned long)vec_base);
1190 #else
1191  __FENCE_I();
1192 #endif
1193 #endif
1194 }
1195 
1209 {
1210 #if __RISCV_XLEN == 32
1211  return (*(uint32_t *)(__RV_CSR_READ(CSR_STVT) + IRQn * 4));
1212 #elif __RISCV_XLEN == 64
1213  return (*(uint64_t *)(__RV_CSR_READ(CSR_STVT) + IRQn * 8));
1214 #else // TODO Need cover for XLEN=128 case in future
1215  return (*(uint64_t *)(__RV_CSR_READ(CSR_STVT) + IRQn * 8));
1216 #endif
1217 }
1218 
1219 #endif /* defined(__TEE_PRESENT) && (__TEE_PRESENT == 1) */
1220 
1233 {
1234  addr &= (rv_csr_t)(~0x3F);
1235  addr |= ECLIC_MODE_MTVEC_Msk;
1236  __RV_CSR_WRITE(CSR_MTVEC, addr);
1237 }
1238 
1251 {
1252  unsigned long addr = __RV_CSR_READ(CSR_MTVEC);
1253  return (addr & ~ECLIC_MODE_MTVEC_Msk);
1254 }
1255 
1268 {
1269  if (__RV_CSR_READ(CSR_MTVT2) & 0x1) {
1270  __RV_CSR_WRITE(CSR_MTVT2, addr | 0x01);
1271  } else {
1272  addr &= (rv_csr_t)(~0x3F);
1273  addr |= ECLIC_MODE_MTVEC_Msk;
1274  __RV_CSR_WRITE(CSR_MTVEC, addr);
1275  }
1276 }
1277 
1290 {
1291  if (__RV_CSR_READ(CSR_MTVT2) & 0x1) {
1292  return __RV_CSR_READ(CSR_MTVT2) & (~(rv_csr_t)(0x1));
1293  } else {
1295  return (addr & ~ECLIC_MODE_MTVEC_Msk);
1296  }
1297 }
1298 
1310 {
1311  return __RV_CSR_READ(CSR_MNVEC);
1312 }
1313 
1344 #define SAVE_IRQ_CSR_CONTEXT() \
1345  rv_csr_t __mcause = __RV_CSR_READ(CSR_MCAUSE); \
1346  rv_csr_t __mepc = __RV_CSR_READ(CSR_MEPC); \
1347  rv_csr_t __msubm = __RV_CSR_READ(CSR_MSUBM); \
1348  __enable_irq();
1349 
1351 #define SAVE_IRQ_CSR_CONTEXT_S() \
1352  rv_csr_t __scause = __RV_CSR_READ(CSR_SCAUSE); \
1353  rv_csr_t __sepc = __RV_CSR_READ(CSR_SEPC); \
1354  __enable_irq_s();
1355 
1356 
1366 #define RESTORE_IRQ_CSR_CONTEXT() \
1367  __disable_irq(); \
1368  __RV_CSR_WRITE(CSR_MSUBM, __msubm); \
1369  __RV_CSR_WRITE(CSR_MEPC, __mepc); \
1370  __RV_CSR_WRITE(CSR_MCAUSE, __mcause);
1371 
1373 #define RESTORE_IRQ_CSR_CONTEXT_S() \
1374  __disable_irq_s(); \
1375  __RV_CSR_WRITE(CSR_SEPC, __sepc); \
1376  __RV_CSR_WRITE(CSR_SCAUSE, __scause); /* End of Doxygen Group NMSIS_Core_IntExc */
1378 
1379 #endif /* defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1) */
1380 
1381 #ifdef __cplusplus
1382 }
1383 #endif
1384 #endif /* __CORE_FEATURE_ECLIC__ */
__STATIC_FORCEINLINE void __FENCE_I(void)
Fence.i Instruction.
#define __RV_CSR_READ(csr)
CSR operation Macro for csrr instruction.
#define __RV_CSR_WRITE(csr, val)
CSR operation Macro for csrw instruction.
#define CSR_MNVEC
#define CSR_MTVEC
#define CSR_MTVT
#define CSR_MTVT2
#define CSR_STVT
#define __STATIC_FORCEINLINE
Define a static function that should be always inlined by the compiler.
Definition: nmsis_gcc.h:70
__STATIC_FORCEINLINE void SFlushDCacheLine(unsigned long addr)
Flush one D-Cache line specified by address in S-Mode.
__STATIC_FORCEINLINE void MFlushDCacheLine(unsigned long addr)
Flush one D-Cache line specified by address in M-Mode.
#define CLIC_CLICCFG_NLBIT_Pos
CLIC CLICCFG: NLBIT Position.
#define CLIC_CLICINFO_CTLBIT_Msk
CLIC INTINFO: CLICINTCTLBITS Mask.
#define CLIC_CLICINFO_VER_Msk
CLIC CLICINFO: VERSION Mask.
#define CLIC_INTATTR_SHV_Msk
CLIC INTATTR: SHV Mask.
#define ECLIC_MODE_MTVEC_Msk
ECLIC Mode mask for MTVT CSR Register.
#define CLIC_CLICINFO_VER_Pos
CLIC CLICINFO: VERSION Position.
#define ECLIC_MAX_NLBITS
Max nlbit of the CLICINTCTLBITS.
ECLIC_TRIGGER_Type
ECLIC Trigger Enum for different Trigger Type.
#define CLIC_CLICINFO_NUM_Pos
CLIC CLICINFO: NUM Position.
#define CLIC_INTATTR_TRIG_Msk
CLIC INTATTR: TRIG Mask.
#define CLIC_INTATTR_SHV_Pos
CLIC INTATTR: SHV Position.
#define CLIC_INTATTR_MODE_Msk
CLIC INTATTA: Mode Mask.
#define CLIC_CLICCFG_NLBIT_Msk
CLIC CLICCFG: NLBIT Mask.
#define CLIC_INTIE_IE_Msk
CLIC INTIE: IE Mask.
#define CLIC_CLICINFO_NUM_Msk
CLIC CLICINFO: NUM Mask.
#define CLIC_INTATTR_MODE_Pos
CLIC INTATTA: Mode Position.
#define ECLIC
CLIC configuration struct.
#define CLIC_INTATTR_TRIG_Pos
CLIC INTATTR: TRIG Position.
#define CLIC_CLICINFO_CTLBIT_Pos
CLIC INTINFO: CLICINTCTLBITS Position.
#define CLIC_INTIP_IP_Msk
CLIC INTIP: IP Mask.
@ ECLIC_POSTIVE_EDGE_TRIGGER
Postive/Rising Edge Triggered, trig[0] = 1, trig[1] = 0.
@ ECLIC_LEVEL_TRIGGER
Level Triggerred, trig[0] = 0.
@ ECLIC_MAX_TRIGGER
MAX Supported Trigger Mode.
@ ECLIC_NEGTIVE_EDGE_TRIGGER
Negtive/Falling Edge Triggered, trig[0] = 1, trig[1] = 1.
__STATIC_FORCEINLINE void SInvalICacheLine(unsigned long addr)
Invalidate one I-Cache line specified by address in S-Mode.
__STATIC_FORCEINLINE void MInvalICacheLine(unsigned long addr)
Invalidate one I-Cache line specified by address in M-Mode.
__STATIC_FORCEINLINE rv_csr_t __get_exc_entry(void)
Get Exception entry address.
__STATIC_FORCEINLINE uint32_t __ECLIC_GetInfoVer(void)
Get the ECLIC version number.
__STATIC_FORCEINLINE uint8_t __ECLIC_GetCtrlIRQ(IRQn_Type IRQn)
Get ECLIC Interrupt Input Control Register value for a specific interrupt.
__STATIC_FORCEINLINE void __ECLIC_SetTrigIRQ_S(IRQn_Type IRQn, uint32_t trig)
Set trigger mode and polarity for a specific interrupt in supervisor mode.
__STATIC_FORCEINLINE uint8_t __ECLIC_GetSth(void)
Get supervisor-mode Interrupt Level Threshold in supervisor mode.
__STATIC_FORCEINLINE uint8_t __ECLIC_GetLevelIRQ(IRQn_Type IRQn)
Get ECLIC Interrupt level of a specific interrupt.
__STATIC_FORCEINLINE uint32_t __ECLIC_GetCfgNlbits(void)
Get nlbits value.
__STATIC_FORCEINLINE void __ECLIC_SetShvIRQ(IRQn_Type IRQn, uint32_t shv)
Set interrupt working mode for a specific interrupt.
__STATIC_FORCEINLINE void __ECLIC_SetCtrlIRQ_S(IRQn_Type IRQn, uint8_t intctrl)
Modify ECLIC Interrupt Input Control Register for a specific interrupt in supervisor mode.
__STATIC_FORCEINLINE uint8_t __ECLIC_GetShvIRQ_S(IRQn_Type IRQn)
Get interrupt working mode for a specific interrupt in supervisor mode.
__STATIC_FORCEINLINE uint32_t __ECLIC_GetInfoNum(void)
Get number of maximum interrupt inputs supported.
__STATIC_FORCEINLINE void __ECLIC_SetCtrlIRQ(IRQn_Type IRQn, uint8_t intctrl)
Modify ECLIC Interrupt Input Control Register for a specific interrupt.
__STATIC_FORCEINLINE void __ECLIC_SetVector(IRQn_Type IRQn, rv_csr_t vector)
Set Interrupt Vector of a specific interrupt.
__STATIC_FORCEINLINE rv_csr_t __get_nonvec_entry(void)
Get Non-vector interrupt entry address.
__STATIC_FORCEINLINE uint8_t __ECLIC_GetMth(void)
Get Machine Mode Interrupt Level Threshold.
__STATIC_FORCEINLINE void __ECLIC_SetCfgNlbits(uint32_t nlbits)
Set nlbits value.
__STATIC_FORCEINLINE void __ECLIC_SetSth(uint8_t sth)
Set supervisor-mode Interrupt Level Threshold in supervisor mode.
__STATIC_FORCEINLINE uint8_t __ECLIC_GetPriorityIRQ(IRQn_Type IRQn)
Get ECLIC Interrupt priority of a specific interrupt.
__STATIC_FORCEINLINE uint32_t __ECLIC_GetInfoCtlbits(void)
Get CLICINTCTLBITS.
__STATIC_FORCEINLINE void __ECLIC_SetPriorityIRQ_S(IRQn_Type IRQn, uint8_t pri)
Set ECLIC Interrupt priority of a specific interrupt in supervisor mode.
__STATIC_FORCEINLINE void __ECLIC_ClearPendingIRQ(IRQn_Type IRQn)
Clear a specific interrupt from pending.
__STATIC_FORCEINLINE rv_csr_t __ECLIC_GetVector(IRQn_Type IRQn)
Get Interrupt Vector of a specific interrupt.
IRQn_Type
Definition of IRQn numbers.
__STATIC_FORCEINLINE void __ECLIC_SetLevelIRQ_S(IRQn_Type IRQn, uint8_t lvl_abs)
Set ECLIC Interrupt level of a specific interrupt in supervisor mode.
__STATIC_FORCEINLINE void __ECLIC_SetModeIRQ(IRQn_Type IRQn, uint32_t mode)
Set privilege mode of a specific interrupt.
__STATIC_FORCEINLINE void __ECLIC_EnableIRQ_S(IRQn_Type IRQn)
Enable a specific interrupt in supervisor mode.
__STATIC_FORCEINLINE int32_t __ECLIC_GetPendingIRQ(IRQn_Type IRQn)
Get the pending specific interrupt.
__STATIC_FORCEINLINE void __ECLIC_DisableIRQ(IRQn_Type IRQn)
Disable a specific interrupt.
__STATIC_FORCEINLINE void __ECLIC_SetPriorityIRQ(IRQn_Type IRQn, uint8_t pri)
Get ECLIC Interrupt priority of a specific interrupt.
__STATIC_FORCEINLINE uint8_t __ECLIC_GetEnableIRQ_S(IRQn_Type IRQn)
Get a specific interrupt enable status in supervisor mode.
__STATIC_FORCEINLINE uint8_t __ECLIC_GetTrigIRQ_S(IRQn_Type IRQn)
Get trigger mode and polarity for a specific interrupt in supervisor mode.
__STATIC_FORCEINLINE uint32_t __ECLIC_GetTrigIRQ(IRQn_Type IRQn)
Get trigger mode and polarity for a specific interrupt.
__STATIC_FORCEINLINE void __ECLIC_SetVector_S(IRQn_Type IRQn, rv_csr_t vector)
Set Interrupt Vector of a specific interrupt in supervisor mode.
__STATIC_FORCEINLINE rv_csr_t __get_nmi_entry(void)
Get NMI interrupt entry from 'CSR_MNVEC'.
__STATIC_FORCEINLINE void __ECLIC_DisableIRQ_S(IRQn_Type IRQn)
Disable a specific interrupt in supervisor mode.
__STATIC_FORCEINLINE uint8_t __ECLIC_GetCtrlIRQ_S(IRQn_Type IRQn)
Get ECLIC Interrupt Input Control Register value for a specific interrupt in supervisor mode.
__STATIC_FORCEINLINE uint32_t __ECLIC_GetShvIRQ(IRQn_Type IRQn)
Get interrupt working mode for a specific interrupt.
__STATIC_FORCEINLINE uint32_t __ECLIC_GetEnableIRQ(IRQn_Type IRQn)
Get a specific interrupt enable status.
__STATIC_FORCEINLINE void __ECLIC_SetPendingIRQ(IRQn_Type IRQn)
Set a specific interrupt to pending.
__STATIC_FORCEINLINE void __set_nonvec_entry(rv_csr_t addr)
Set Non-vector interrupt entry address.
__STATIC_FORCEINLINE uint8_t __ECLIC_GetLevelIRQ_S(IRQn_Type IRQn)
Get ECLIC Interrupt level of a specific interrupt.
__STATIC_FORCEINLINE void __ECLIC_EnableIRQ(IRQn_Type IRQn)
Enable a specific interrupt.
__STATIC_FORCEINLINE void __ECLIC_SetLevelIRQ(IRQn_Type IRQn, uint8_t lvl_abs)
Set ECLIC Interrupt level of a specific interrupt.
__STATIC_FORCEINLINE void __ECLIC_SetShvIRQ_S(IRQn_Type IRQn, uint32_t shv)
Set interrupt working mode for a specific interrupt in supervisor mode.
__STATIC_FORCEINLINE void __set_exc_entry(rv_csr_t addr)
Set Exception entry address.
__STATIC_FORCEINLINE void __ECLIC_SetTrigIRQ(IRQn_Type IRQn, uint32_t trig)
Set trigger mode and polarity for a specific interrupt.
__STATIC_FORCEINLINE void __ECLIC_SetMth(uint8_t mth)
Set Machine Mode Interrupt Level Threshold.
__STATIC_FORCEINLINE rv_csr_t __ECLIC_GetVector_S(IRQn_Type IRQn)
Get Interrupt Vector of a specific interrupt in supervisor mode.
__STATIC_FORCEINLINE uint8_t __ECLIC_GetPriorityIRQ_S(IRQn_Type IRQn)
Get ECLIC Interrupt priority of a specific interrupt in supervisor mode.
@ SysTimerSW_IRQn
System Timer SW interrupt.
@ Reserved10_IRQn
Internal reserved.
@ Reserved2_IRQn
Internal reserved.
@ Reserved15_IRQn
Internal reserved.
@ Reserved14_IRQn
Internal reserved.
@ SysTimer_IRQn
System Timer Interrupt.
@ Reserved0_IRQn
Internal reserved.
@ Reserved16_IRQn
Internal reserved.
@ Reserved9_IRQn
Internal reserved.
@ Reserved11_IRQn
Internal reserved.
@ Reserved6_IRQn
Internal reserved.
@ Reserved12_IRQn
Internal reserved.
@ Reserved13_IRQn
Internal reserved.
@ Reserved5_IRQn
Internal reserved.
@ Reserved4_IRQn
Internal reserved.
@ Reserved8_IRQn
Internal reserved.
@ FirstDeviceSpecificInterrupt_IRQn
First Device Specific Interrupt.
@ Reserved1_IRQn
Internal reserved.
@ SOC_INT_MAX
Number of total interrupts.
@ Reserved7_IRQn
Internal reserved.
@ Reserved3_IRQn
Internal reserved.
#define __IM
Defines 'read only' structure member permissions.
#define __IOM
Defines 'read/write' structure member permissions.
unsigned long rv_csr_t
Type of Control and Status Register(CSR), depends on the XLEN defined in RISC-V.
Access to the machine mode register structure of INTIP, INTIE, INTATTR, INTCTL.
__IOM uint8_t INTIP
Offset: 0x000 (R/W) Interrupt set pending register.
__IOM uint8_t INTIE
Offset: 0x001 (R/W) Interrupt set enable register.
__IOM uint8_t INTATTR
Offset: 0x002 (R/W) Interrupt set attributes register.
__IOM uint8_t INTCTRL
Offset: 0x003 (R/W) Interrupt configure register.
Access to the structure of ECLIC Memory Map, which is compatible with TEE.
__IM uint8_t RESERVED7
__IM uint8_t RESERVED3
__IOM uint8_t SSTH
Offset: 0x2009 (R) CLIC supervisor mode threshold register, which is a mirror to mintthresh....
__IM uint32_t INFO
Offset: 0x004 (R/ ) CLIC information register.
__IM uint8_t RESERVED1
__IM uint8_t RESERVED8
__IOM uint8_t CFG
Offset: 0x000 (R/W) CLIC configuration register.
__IOM uint8_t STH
Offset: 0x009 (R/W ) CLIC supervisor mode interrupt-level threshold.
__IM uint8_t RESERVED6
__IOM uint8_t MTH
Offset: 0x00B(R/W) CLIC machine mode interrupt-level threshold.
Union type to access CLICFG configure register.
__IM uint8_t nmbits
bit: 5..6 ties to 1 if supervisor-level interrupt supported, or else it's reserved
__IM uint8_t _reserved0
__IM uint8_t _reserved1
uint8_t w
Type used for byte access.
__IOM uint8_t nlbits
bit: 1..4 specified the bit-width of level and priority in the register clicintctl[i]
Union type to access CLICINFO information register.
__IM uint32_t _reserved0
bit: 25..31 Reserved
__IM uint32_t intctlbits
bit: 21..24 specifies how many hardware bits are actually implemented in the clicintctl registers
__IM uint32_t w
Type used for word access.
__IM uint32_t version
bit: 13..20 20:17 for architecture version,16:13 for implementation version
__IM uint32_t numint
bit: 0..12 number of maximum interrupt inputs supported