core_feature_eclic.h 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384
  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__
  20. /*!
  21. * @file core_feature_eclic.h
  22. * @brief ECLIC feature API header file for Nuclei N/NX Core
  23. */
  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. #include "core_feature_base.h"
  42. #if defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1)
  43. /**
  44. * \defgroup NMSIS_Core_ECLIC_Registers Register Define and Type Definitions Of ECLIC
  45. * \ingroup NMSIS_Core_Registers
  46. * \brief Type definitions and defines for eclic registers.
  47. *
  48. * @{
  49. */
  50. /**
  51. * \brief Union type to access CLICFG configure register.
  52. */
  53. typedef union
  54. {
  55. struct {
  56. __IM uint8_t _reserved0:1;
  57. __IOM uint8_t nlbits:4; /*!< bit: 1..4 specified the bit-width of level and priority in the register clicintctl[i] */
  58. __IM uint8_t nmbits:2; /*!< bit: 5..6 ties to 1 if supervisor-level interrupt supported, or else it's reserved */
  59. __IM uint8_t _reserved1:1;
  60. } b; /*!< Structure used for bit access */
  61. uint8_t w; /*!< Type used for byte access */
  62. } CLICCFG_Type;
  63. /**
  64. * \brief Union type to access CLICINFO information register.
  65. */
  66. typedef union {
  67. struct {
  68. __IM uint32_t numint:13; /*!< bit: 0..12 number of maximum interrupt inputs supported */
  69. __IM uint32_t version:8; /*!< bit: 13..20 20:17 for architecture version,16:13 for implementation version */
  70. __IM uint32_t intctlbits:4; /*!< bit: 21..24 specifies how many hardware bits are actually implemented in the clicintctl registers */
  71. __IM uint32_t _reserved0:7; /*!< bit: 25..31 Reserved */
  72. } b; /*!< Structure used for bit access */
  73. __IM uint32_t w; /*!< Type used for word access */
  74. } CLICINFO_Type;
  75. /**
  76. * \brief Access to the machine mode register structure of INTIP, INTIE, INTATTR, INTCTL.
  77. */
  78. typedef struct {
  79. __IOM uint8_t INTIP; /*!< Offset: 0x000 (R/W) Interrupt set pending register */
  80. __IOM uint8_t INTIE; /*!< Offset: 0x001 (R/W) Interrupt set enable register */
  81. __IOM uint8_t INTATTR; /*!< Offset: 0x002 (R/W) Interrupt set attributes register */
  82. __IOM uint8_t INTCTRL; /*!< Offset: 0x003 (R/W) Interrupt configure register */
  83. } CLIC_CTRL_Type;
  84. /**
  85. * \brief Access to the structure of ECLIC Memory Map, which is compatible with TEE.
  86. */
  87. typedef struct {
  88. __IOM uint8_t CFG; /*!< Offset: 0x000 (R/W) CLIC configuration register */
  89. __IM uint8_t RESERVED0[3];
  90. __IM uint32_t INFO; /*!< Offset: 0x004 (R/ ) CLIC information register */
  91. __IM uint8_t RESERVED1;
  92. #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
  93. __IOM uint8_t STH; /*!< Offset: 0x009 (R/W ) CLIC supervisor mode interrupt-level threshold */
  94. #else
  95. __IM uint8_t RESERVED2;
  96. #endif
  97. __IM uint8_t RESERVED3;
  98. __IOM uint8_t MTH; /*!< Offset: 0x00B(R/W) CLIC machine mode interrupt-level threshold */
  99. uint32_t RESERVED4[1021];
  100. #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
  101. CLIC_CTRL_Type CTRL[1024]; /*!< Offset: 0x1000 (R/W) CLIC machine mode register structure for INTIP, INTIE, INTATTR, INTCTL */
  102. __IM uint32_t RESERVED5[2];
  103. __IM uint8_t RESERVED6;
  104. __IOM uint8_t SSTH; /*!< Offset: 0x2009 (R) CLIC supervisor mode threshold register, which is a mirror to mintthresh.sth */
  105. __IM uint8_t RESERVED7;
  106. __IM uint8_t RESERVED8;
  107. __IM uint32_t RESERVED9[1021];
  108. CLIC_CTRL_Type SCTRL[1024]; /*!< Offset: 0x3000 (R/W) CLIC supervisor mode register structure for INTIP, INTIE, INTATTR, INTCTL */
  109. #else
  110. CLIC_CTRL_Type CTRL[4096]; /*!< Offset: 0x1000 (R/W) CLIC machine mode register structure for INTIP, INTIE, INTATTR, INTCTL */
  111. #endif
  112. } CLIC_Type;
  113. #define CLIC_CLICCFG_NLBIT_Pos 1U /*!< CLIC CLICCFG: NLBIT Position */
  114. #define CLIC_CLICCFG_NLBIT_Msk (0xFUL << CLIC_CLICCFG_NLBIT_Pos) /*!< CLIC CLICCFG: NLBIT Mask */
  115. #define CLIC_CLICINFO_CTLBIT_Pos 21U /*!< CLIC INTINFO: CLICINTCTLBITS Position */
  116. #define CLIC_CLICINFO_CTLBIT_Msk (0xFUL << CLIC_CLICINFO_CTLBIT_Pos) /*!< CLIC INTINFO: CLICINTCTLBITS Mask */
  117. #define CLIC_CLICINFO_VER_Pos 13U /*!< CLIC CLICINFO: VERSION Position */
  118. #define CLIC_CLICINFO_VER_Msk (0xFFUL << CLIC_CLICINFO_VER_Pos) /*!< CLIC CLICINFO: VERSION Mask */
  119. #define CLIC_CLICINFO_NUM_Pos 0U /*!< CLIC CLICINFO: NUM Position */
  120. #define CLIC_CLICINFO_NUM_Msk (0x1FFFUL << CLIC_CLICINFO_NUM_Pos) /*!< CLIC CLICINFO: NUM Mask */
  121. #define CLIC_INTIP_IP_Pos 0U /*!< CLIC INTIP: IP Position */
  122. #define CLIC_INTIP_IP_Msk (0x1UL << CLIC_INTIP_IP_Pos) /*!< CLIC INTIP: IP Mask */
  123. #define CLIC_INTIE_IE_Pos 0U /*!< CLIC INTIE: IE Position */
  124. #define CLIC_INTIE_IE_Msk (0x1UL << CLIC_INTIE_IE_Pos) /*!< CLIC INTIE: IE Mask */
  125. #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
  126. #define CLIC_INTATTR_MODE_Pos 6U /*!< CLIC INTATTA: Mode Position */
  127. #define CLIC_INTATTR_MODE_Msk (0x3U << CLIC_INTATTR_MODE_Pos) /*!< CLIC INTATTA: Mode Mask */
  128. #endif
  129. #define CLIC_INTATTR_TRIG_Pos 1U /*!< CLIC INTATTR: TRIG Position */
  130. #define CLIC_INTATTR_TRIG_Msk (0x3UL << CLIC_INTATTR_TRIG_Pos) /*!< CLIC INTATTR: TRIG Mask */
  131. #define CLIC_INTATTR_SHV_Pos 0U /*!< CLIC INTATTR: SHV Position */
  132. #define CLIC_INTATTR_SHV_Msk (0x1UL << CLIC_INTATTR_SHV_Pos) /*!< CLIC INTATTR: SHV Mask */
  133. #define ECLIC_MAX_NLBITS 8U /*!< Max nlbit of the CLICINTCTLBITS */
  134. #define ECLIC_MODE_MTVEC_Msk 3U /*!< ECLIC Mode mask for MTVT CSR Register */
  135. #define ECLIC_NON_VECTOR_INTERRUPT 0x0 /*!< Non-Vector Interrupt Mode of ECLIC */
  136. #define ECLIC_VECTOR_INTERRUPT 0x1 /*!< Vector Interrupt Mode of ECLIC */
  137. /**\brief ECLIC Trigger Enum for different Trigger Type */
  138. typedef enum ECLIC_TRIGGER {
  139. ECLIC_LEVEL_TRIGGER = 0x0, /*!< Level Triggerred, trig[0] = 0 */
  140. ECLIC_POSTIVE_EDGE_TRIGGER = 0x1, /*!< Postive/Rising Edge Triggered, trig[0] = 1, trig[1] = 0 */
  141. ECLIC_NEGTIVE_EDGE_TRIGGER = 0x3, /*!< Negtive/Falling Edge Triggered, trig[0] = 1, trig[1] = 1 */
  142. ECLIC_MAX_TRIGGER = 0x3 /*!< MAX Supported Trigger Mode */
  143. } ECLIC_TRIGGER_Type;
  144. #ifndef __ECLIC_BASEADDR
  145. /* Base address of ECLIC(__ECLIC_BASEADDR) should be defined in <Device.h> */
  146. #error "__ECLIC_BASEADDR is not defined, please check!"
  147. #endif
  148. #ifndef __ECLIC_INTCTLBITS
  149. /* Define __ECLIC_INTCTLBITS to get via ECLIC->INFO if not defined */
  150. #define __ECLIC_INTCTLBITS (__ECLIC_GetInfoCtlbits())
  151. #endif
  152. /* ECLIC Memory mapping of Device */
  153. #define ECLIC_BASE __ECLIC_BASEADDR /*!< ECLIC Base Address */
  154. #define ECLIC ((CLIC_Type *) ECLIC_BASE) /*!< CLIC configuration struct */
  155. /** @} */ /* end of group NMSIS_Core_ECLIC_Registers */
  156. /* ########################## ECLIC functions #################################### */
  157. /**
  158. * \defgroup NMSIS_Core_IntExc Interrupts and Exceptions
  159. * \brief Functions that manage interrupts and exceptions via the ECLIC.
  160. *
  161. * @{
  162. */
  163. /**
  164. * \brief Definition of IRQn numbers
  165. * \details
  166. * The core interrupt enumeration names for IRQn values are defined in the file <b><Device>.h</b>.
  167. * - Interrupt ID(IRQn) from 0 to 18 are reserved for core internal interrupts.
  168. * - Interrupt ID(IRQn) start from 19 represent device-specific external interrupts.
  169. * - The first device-specific interrupt has the IRQn value 19.
  170. *
  171. * The table below describes the core interrupt names and their availability in various Nuclei Cores.
  172. */
  173. /* The following enum IRQn definition in this file
  174. * is only used for doxygen documentation generation,
  175. * The <Device>.h is the real file to define it by vendor
  176. */
  177. #if defined(__ONLY_FOR_DOXYGEN_DOCUMENT_GENERATION__)
  178. typedef enum IRQn {
  179. /* ========= Nuclei N/NX Core Specific Interrupt Numbers =========== */
  180. /* Core Internal Interrupt IRQn definitions */
  181. Reserved0_IRQn = 0, /*!< Internal reserved */
  182. Reserved1_IRQn = 1, /*!< Internal reserved */
  183. Reserved2_IRQn = 2, /*!< Internal reserved */
  184. SysTimerSW_IRQn = 3, /*!< System Timer SW interrupt */
  185. Reserved3_IRQn = 4, /*!< Internal reserved */
  186. Reserved4_IRQn = 5, /*!< Internal reserved */
  187. Reserved5_IRQn = 6, /*!< Internal reserved */
  188. SysTimer_IRQn = 7, /*!< System Timer Interrupt */
  189. Reserved6_IRQn = 8, /*!< Internal reserved */
  190. Reserved7_IRQn = 9, /*!< Internal reserved */
  191. Reserved8_IRQn = 10, /*!< Internal reserved */
  192. Reserved9_IRQn = 11, /*!< Internal reserved */
  193. Reserved10_IRQn = 12, /*!< Internal reserved */
  194. Reserved11_IRQn = 13, /*!< Internal reserved */
  195. Reserved12_IRQn = 14, /*!< Internal reserved */
  196. Reserved13_IRQn = 15, /*!< Internal reserved */
  197. Reserved14_IRQn = 16, /*!< Internal reserved */
  198. Reserved15_IRQn = 17, /*!< Internal reserved */
  199. Reserved16_IRQn = 18, /*!< Internal reserved */
  200. /* ========= Device Specific Interrupt Numbers =================== */
  201. /* ToDo: add here your device specific external interrupt numbers.
  202. * 19~max(NUM_INTERRUPT, 1023) is reserved number for user.
  203. * Maxmum interrupt supported could get from clicinfo.NUM_INTERRUPT.
  204. * According the interrupt handlers defined in startup_Device.S
  205. * eg.: Interrupt for Timer#1 eclic_tim1_handler -> TIM1_IRQn */
  206. FirstDeviceSpecificInterrupt_IRQn = 19, /*!< First Device Specific Interrupt */
  207. SOC_INT_MAX, /*!< Number of total interrupts */
  208. } IRQn_Type;
  209. #endif /* __ONLY_FOR_DOXYGEN_DOCUMENT_GENERATION__ */
  210. #ifdef NMSIS_ECLIC_VIRTUAL
  211. #ifndef NMSIS_ECLIC_VIRTUAL_HEADER_FILE
  212. #define NMSIS_ECLIC_VIRTUAL_HEADER_FILE "nmsis_eclic_virtual.h"
  213. #endif
  214. #include NMSIS_ECLIC_VIRTUAL_HEADER_FILE
  215. #else
  216. #define ECLIC_SetCfgNlbits __ECLIC_SetCfgNlbits
  217. #define ECLIC_GetCfgNlbits __ECLIC_GetCfgNlbits
  218. #define ECLIC_GetInfoVer __ECLIC_GetInfoVer
  219. #define ECLIC_GetInfoCtlbits __ECLIC_GetInfoCtlbits
  220. #define ECLIC_GetInfoNum __ECLIC_GetInfoNum
  221. #define ECLIC_SetMth __ECLIC_SetMth
  222. #define ECLIC_GetMth __ECLIC_GetMth
  223. #define ECLIC_EnableIRQ __ECLIC_EnableIRQ
  224. #define ECLIC_GetEnableIRQ __ECLIC_GetEnableIRQ
  225. #define ECLIC_DisableIRQ __ECLIC_DisableIRQ
  226. #define ECLIC_SetPendingIRQ __ECLIC_SetPendingIRQ
  227. #define ECLIC_GetPendingIRQ __ECLIC_GetPendingIRQ
  228. #define ECLIC_ClearPendingIRQ __ECLIC_ClearPendingIRQ
  229. #define ECLIC_SetTrigIRQ __ECLIC_SetTrigIRQ
  230. #define ECLIC_GetTrigIRQ __ECLIC_GetTrigIRQ
  231. #define ECLIC_SetShvIRQ __ECLIC_SetShvIRQ
  232. #define ECLIC_GetShvIRQ __ECLIC_GetShvIRQ
  233. #define ECLIC_SetCtrlIRQ __ECLIC_SetCtrlIRQ
  234. #define ECLIC_GetCtrlIRQ __ECLIC_GetCtrlIRQ
  235. #define ECLIC_SetLevelIRQ __ECLIC_SetLevelIRQ
  236. #define ECLIC_GetLevelIRQ __ECLIC_GetLevelIRQ
  237. #define ECLIC_SetPriorityIRQ __ECLIC_SetPriorityIRQ
  238. #define ECLIC_GetPriorityIRQ __ECLIC_GetPriorityIRQ
  239. /* For TEE */
  240. #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
  241. #define ECLIC_SetModeIRQ __ECLIC_SetModeIRQ
  242. #define ECLIC_SetSth __ECLIC_SetSth
  243. #define ECLIC_GetSth __ECLIC_GetSth
  244. #define ECLIC_SetTrigIRQ_S __ECLIC_SetTrigIRQ_S
  245. #define ECLIC_GetTrigIRQ_S __ECLIC_GetTrigIRQ_S
  246. #define ECLIC_SetShvIRQ_S __ECLIC_SetShvIRQ_S
  247. #define ECLIC_GetShvIRQ_S __ECLIC_GetShvIRQ_S
  248. #define ECLIC_SetCtrlIRQ_S __ECLIC_SetCtrlIRQ_S
  249. #define ECLIC_GetCtrlIRQ_S __ECLIC_GetCtrlIRQ_S
  250. #define ECLIC_SetLevelIRQ_S __ECLIC_SetLevelIRQ_S
  251. #define ECLIC_GetLevelIRQ_S __ECLIC_GetLevelIRQ_S
  252. #define ECLIC_SetPriorityIRQ_S __ECLIC_SetPriorityIRQ_S
  253. #define ECLIC_GetPriorityIRQ_S __ECLIC_GetPriorityIRQ_S
  254. #define ECLIC_EnableIRQ_S __ECLIC_EnableIRQ_S
  255. #define ECLIC_GetEnableIRQ_S __ECLIC_GetEnableIRQ_S
  256. #define ECLIC_DisableIRQ_S __ECLIC_DisableIRQ_S
  257. #endif
  258. #endif /* NMSIS_ECLIC_VIRTUAL */
  259. #ifdef NMSIS_VECTAB_VIRTUAL
  260. #ifndef NMSIS_VECTAB_VIRTUAL_HEADER_FILE
  261. #define NMSIS_VECTAB_VIRTUAL_HEADER_FILE "nmsis_vectab_virtual.h"
  262. #endif
  263. #include NMSIS_VECTAB_VIRTUAL_HEADER_FILE
  264. #else
  265. #define ECLIC_SetVector __ECLIC_SetVector
  266. #define ECLIC_GetVector __ECLIC_GetVector
  267. #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
  268. #define ECLIC_SetVector_S __ECLIC_SetVector_S
  269. #define ECLIC_GetVector_S __ECLIC_GetVector_S
  270. #endif
  271. #endif /* (NMSIS_VECTAB_VIRTUAL) */
  272. /**
  273. * \brief Set nlbits value
  274. * \details
  275. * This function set the nlbits value of CLICCFG register.
  276. * \param [in] nlbits nlbits value
  277. * \remarks
  278. * - nlbits is used to set the width of level in the CLICINTCTL[i].
  279. * \sa
  280. * - \ref ECLIC_GetCfgNlbits
  281. */
  282. __STATIC_FORCEINLINE void __ECLIC_SetCfgNlbits(uint32_t nlbits)
  283. {
  284. uint8_t temp = ECLIC->CFG;
  285. ECLIC->CFG = (temp & ~CLIC_CLICCFG_NLBIT_Msk) | \
  286. ((uint8_t)((nlbits << CLIC_CLICCFG_NLBIT_Pos) & CLIC_CLICCFG_NLBIT_Msk));
  287. }
  288. /**
  289. * \brief Get nlbits value
  290. * \details
  291. * This function get the nlbits value of CLICCFG register.
  292. * \return nlbits value of CLICCFG register
  293. * \remarks
  294. * - nlbits is used to set the width of level in the CLICINTCTL[i].
  295. * \sa
  296. * - \ref ECLIC_SetCfgNlbits
  297. */
  298. __STATIC_FORCEINLINE uint32_t __ECLIC_GetCfgNlbits(void)
  299. {
  300. return ((uint32_t)((ECLIC->CFG & CLIC_CLICCFG_NLBIT_Msk) >> CLIC_CLICCFG_NLBIT_Pos));
  301. }
  302. /**
  303. * \brief Get the ECLIC version number
  304. * \details
  305. * This function gets the hardware version information from CLICINFO register.
  306. * \return hardware version number in CLICINFO register.
  307. * \remarks
  308. * - This function gets harware version information from CLICINFO register.
  309. * - Bit 20:17 for architecture version, bit 16:13 for implementation version.
  310. * \sa
  311. * - \ref ECLIC_GetInfoNum
  312. */
  313. __STATIC_FORCEINLINE uint32_t __ECLIC_GetInfoVer(void)
  314. {
  315. return ((uint32_t)((ECLIC->INFO & CLIC_CLICINFO_VER_Msk) >> CLIC_CLICINFO_VER_Pos));
  316. }
  317. /**
  318. * \brief Get CLICINTCTLBITS
  319. * \details
  320. * This function gets CLICINTCTLBITS from CLICINFO register.
  321. * \return CLICINTCTLBITS from CLICINFO register.
  322. * \remarks
  323. * - In the CLICINTCTL[i] registers, with 2 <= CLICINTCTLBITS <= 8.
  324. * - The implemented bits are kept left-justified in the most-significant bits of each 8-bit
  325. * CLICINTCTL[I] register, with the lower unimplemented bits treated as hardwired to 1.
  326. * \sa
  327. * - \ref ECLIC_GetInfoNum
  328. */
  329. __STATIC_FORCEINLINE uint32_t __ECLIC_GetInfoCtlbits(void)
  330. {
  331. return ((uint32_t)((ECLIC->INFO & CLIC_CLICINFO_CTLBIT_Msk) >> CLIC_CLICINFO_CTLBIT_Pos));
  332. }
  333. /**
  334. * \brief Get number of maximum interrupt inputs supported
  335. * \details
  336. * This function gets number of maximum interrupt inputs supported from CLICINFO register.
  337. * \return number of maximum interrupt inputs supported from CLICINFO register.
  338. * \remarks
  339. * - This function gets number of maximum interrupt inputs supported from CLICINFO register.
  340. * - The num_interrupt field specifies the actual number of maximum interrupt inputs supported in this implementation.
  341. * \sa
  342. * - \ref ECLIC_GetInfoCtlbits
  343. */
  344. __STATIC_FORCEINLINE uint32_t __ECLIC_GetInfoNum(void)
  345. {
  346. return ((uint32_t)((ECLIC->INFO & CLIC_CLICINFO_NUM_Msk) >> CLIC_CLICINFO_NUM_Pos));
  347. }
  348. /**
  349. * \brief Set Machine Mode Interrupt Level Threshold
  350. * \details
  351. * This function sets machine mode interrupt level threshold.
  352. * \param [in] mth Interrupt Level Threshold.
  353. * \sa
  354. * - \ref ECLIC_GetMth
  355. */
  356. __STATIC_FORCEINLINE void __ECLIC_SetMth(uint8_t mth)
  357. {
  358. ECLIC->MTH = mth;
  359. }
  360. /**
  361. * \brief Get Machine Mode Interrupt Level Threshold
  362. * \details
  363. * This function gets machine mode interrupt level threshold.
  364. * \return Interrupt Level Threshold.
  365. * \sa
  366. * - \ref ECLIC_SetMth
  367. */
  368. __STATIC_FORCEINLINE uint8_t __ECLIC_GetMth(void)
  369. {
  370. return (ECLIC->MTH);
  371. }
  372. /**
  373. * \brief Enable a specific interrupt
  374. * \details
  375. * This function enables the specific interrupt \em IRQn.
  376. * \param [in] IRQn Interrupt number
  377. * \remarks
  378. * - IRQn must not be negative.
  379. * \sa
  380. * - \ref ECLIC_DisableIRQ
  381. */
  382. __STATIC_FORCEINLINE void __ECLIC_EnableIRQ(IRQn_Type IRQn)
  383. {
  384. ECLIC->CTRL[IRQn].INTIE |= CLIC_INTIE_IE_Msk;
  385. }
  386. /**
  387. * \brief Get a specific interrupt enable status
  388. * \details
  389. * This function returns the interrupt enable status for the specific interrupt \em IRQn.
  390. * \param [in] IRQn Interrupt number
  391. * \returns
  392. * - 0 Interrupt is not enabled
  393. * - 1 Interrupt is pending
  394. * \remarks
  395. * - IRQn must not be negative.
  396. * \sa
  397. * - \ref ECLIC_EnableIRQ
  398. * - \ref ECLIC_DisableIRQ
  399. */
  400. __STATIC_FORCEINLINE uint32_t __ECLIC_GetEnableIRQ(IRQn_Type IRQn)
  401. {
  402. return ((uint32_t) (ECLIC->CTRL[IRQn].INTIE) & CLIC_INTIE_IE_Msk);
  403. }
  404. /**
  405. * \brief Disable a specific interrupt
  406. * \details
  407. * This function disables the specific interrupt \em IRQn.
  408. * \param [in] IRQn Number of the external interrupt to disable
  409. * \remarks
  410. * - IRQn must not be negative.
  411. * \sa
  412. * - \ref ECLIC_EnableIRQ
  413. */
  414. __STATIC_FORCEINLINE void __ECLIC_DisableIRQ(IRQn_Type IRQn)
  415. {
  416. ECLIC->CTRL[IRQn].INTIE &= ~CLIC_INTIE_IE_Msk;
  417. }
  418. /**
  419. * \brief Get the pending specific interrupt
  420. * \details
  421. * This function returns the pending status of the specific interrupt \em IRQn.
  422. * \param [in] IRQn Interrupt number
  423. * \returns
  424. * - 0 Interrupt is not pending
  425. * - 1 Interrupt is pending
  426. * \remarks
  427. * - IRQn must not be negative.
  428. * \sa
  429. * - \ref ECLIC_SetPendingIRQ
  430. * - \ref ECLIC_ClearPendingIRQ
  431. */
  432. __STATIC_FORCEINLINE int32_t __ECLIC_GetPendingIRQ(IRQn_Type IRQn)
  433. {
  434. return ((uint32_t)(ECLIC->CTRL[IRQn].INTIP) & CLIC_INTIP_IP_Msk);
  435. }
  436. /**
  437. * \brief Set a specific interrupt to pending
  438. * \details
  439. * This function sets the pending bit for the specific interrupt \em IRQn.
  440. * \param [in] IRQn Interrupt number
  441. * \remarks
  442. * - IRQn must not be negative.
  443. * \sa
  444. * - \ref ECLIC_GetPendingIRQ
  445. * - \ref ECLIC_ClearPendingIRQ
  446. */
  447. __STATIC_FORCEINLINE void __ECLIC_SetPendingIRQ(IRQn_Type IRQn)
  448. {
  449. ECLIC->CTRL[IRQn].INTIP |= CLIC_INTIP_IP_Msk;
  450. }
  451. /**
  452. * \brief Clear a specific interrupt from pending
  453. * \details
  454. * This function removes the pending state of the specific interrupt \em IRQn.
  455. * \em IRQn cannot be a negative number.
  456. * \param [in] IRQn Interrupt number
  457. * \remarks
  458. * - IRQn must not be negative.
  459. * \sa
  460. * - \ref ECLIC_SetPendingIRQ
  461. * - \ref ECLIC_GetPendingIRQ
  462. */
  463. __STATIC_FORCEINLINE void __ECLIC_ClearPendingIRQ(IRQn_Type IRQn)
  464. {
  465. ECLIC->CTRL[IRQn].INTIP &= ~CLIC_INTIP_IP_Msk;
  466. }
  467. /**
  468. * \brief Set trigger mode and polarity for a specific interrupt
  469. * \details
  470. * This function set trigger mode and polarity of the specific interrupt \em IRQn.
  471. * \param [in] IRQn Interrupt number
  472. * \param [in] trig
  473. * - 00 level trigger, \ref ECLIC_LEVEL_TRIGGER
  474. * - 01 positive edge trigger, \ref ECLIC_POSTIVE_EDGE_TRIGGER
  475. * - 02 level trigger, \ref ECLIC_LEVEL_TRIGGER
  476. * - 03 negative edge trigger, \ref ECLIC_NEGTIVE_EDGE_TRIGGER
  477. * \remarks
  478. * - IRQn must not be negative.
  479. *
  480. * \sa
  481. * - \ref ECLIC_GetTrigIRQ
  482. */
  483. __STATIC_FORCEINLINE void __ECLIC_SetTrigIRQ(IRQn_Type IRQn, uint32_t trig)
  484. {
  485. uint8_t temp = ECLIC->CTRL[IRQn].INTATTR;
  486. ECLIC->CTRL[IRQn].INTATTR = (temp & ~CLIC_INTATTR_TRIG_Msk) | \
  487. ((uint8_t)(trig << CLIC_INTATTR_TRIG_Pos));
  488. }
  489. /**
  490. * \brief Get trigger mode and polarity for a specific interrupt
  491. * \details
  492. * This function get trigger mode and polarity of the specific interrupt \em IRQn.
  493. * \param [in] IRQn Interrupt number
  494. * \return
  495. * - 00 level trigger, \ref ECLIC_LEVEL_TRIGGER
  496. * - 01 positive edge trigger, \ref ECLIC_POSTIVE_EDGE_TRIGGER
  497. * - 02 level trigger, \ref ECLIC_LEVEL_TRIGGER
  498. * - 03 negative edge trigger, \ref ECLIC_NEGTIVE_EDGE_TRIGGER
  499. * \remarks
  500. * - IRQn must not be negative.
  501. * \sa
  502. * - \ref ECLIC_SetTrigIRQ
  503. */
  504. __STATIC_FORCEINLINE uint32_t __ECLIC_GetTrigIRQ(IRQn_Type IRQn)
  505. {
  506. return ((uint32_t)(((ECLIC->CTRL[IRQn].INTATTR) & CLIC_INTATTR_TRIG_Msk) >> CLIC_INTATTR_TRIG_Pos));
  507. }
  508. /**
  509. * \brief Set interrupt working mode for a specific interrupt
  510. * \details
  511. * This function set selective hardware vector or non-vector working mode of the specific interrupt \em IRQn.
  512. * \param [in] IRQn Interrupt number
  513. * \param [in] shv
  514. * - 0 non-vector mode, \ref ECLIC_NON_VECTOR_INTERRUPT
  515. * - 1 vector mode, \ref ECLIC_VECTOR_INTERRUPT
  516. * \remarks
  517. * - IRQn must not be negative.
  518. * \sa
  519. * - \ref ECLIC_GetShvIRQ
  520. */
  521. __STATIC_FORCEINLINE void __ECLIC_SetShvIRQ(IRQn_Type IRQn, uint32_t shv)
  522. {
  523. uint8_t temp = ECLIC->CTRL[IRQn].INTATTR;
  524. ECLIC->CTRL[IRQn].INTATTR = (temp & ~CLIC_INTATTR_SHV_Msk) | \
  525. ((uint8_t)(shv << CLIC_INTATTR_SHV_Pos));
  526. }
  527. /**
  528. * \brief Get interrupt working mode for a specific interrupt
  529. * \details
  530. * This function get selective hardware vector or non-vector working mode of the specific interrupt \em IRQn.
  531. * \param [in] IRQn Interrupt number
  532. * \return shv
  533. * - 0 non-vector mode, \ref ECLIC_NON_VECTOR_INTERRUPT
  534. * - 1 vector mode, \ref ECLIC_VECTOR_INTERRUPT
  535. * \remarks
  536. * - IRQn must not be negative.
  537. * \sa
  538. * - \ref ECLIC_SetShvIRQ
  539. */
  540. __STATIC_FORCEINLINE uint32_t __ECLIC_GetShvIRQ(IRQn_Type IRQn)
  541. {
  542. return ((uint32_t)(((ECLIC->CTRL[IRQn].INTATTR) & CLIC_INTATTR_SHV_Msk) >> CLIC_INTATTR_SHV_Pos));
  543. }
  544. /**
  545. * \brief Modify ECLIC Interrupt Input Control Register for a specific interrupt
  546. * \details
  547. * This function modify ECLIC Interrupt Input Control(CLICINTCTL[i]) register of the specific interrupt \em IRQn.
  548. * \param [in] IRQn Interrupt number
  549. * \param [in] intctrl Set value for CLICINTCTL[i] register
  550. * \remarks
  551. * - IRQn must not be negative.
  552. * \sa
  553. * - \ref ECLIC_GetCtrlIRQ
  554. */
  555. __STATIC_FORCEINLINE void __ECLIC_SetCtrlIRQ(IRQn_Type IRQn, uint8_t intctrl)
  556. {
  557. ECLIC->CTRL[IRQn].INTCTRL = intctrl;
  558. }
  559. /**
  560. * \brief Get ECLIC Interrupt Input Control Register value for a specific interrupt
  561. * \details
  562. * This function modify ECLIC Interrupt Input Control register of the specific interrupt \em IRQn.
  563. * \param [in] IRQn Interrupt number
  564. * \return value of ECLIC Interrupt Input Control register
  565. * \remarks
  566. * - IRQn must not be negative.
  567. * \sa
  568. * - \ref ECLIC_SetCtrlIRQ
  569. */
  570. __STATIC_FORCEINLINE uint8_t __ECLIC_GetCtrlIRQ(IRQn_Type IRQn)
  571. {
  572. return (ECLIC->CTRL[IRQn].INTCTRL);
  573. }
  574. /**
  575. * \brief Set ECLIC Interrupt level of a specific interrupt
  576. * \details
  577. * This function set interrupt level of the specific interrupt \em IRQn.
  578. * \param [in] IRQn Interrupt number
  579. * \param [in] lvl_abs Interrupt level
  580. * \remarks
  581. * - IRQn must not be negative.
  582. * - If lvl_abs to be set is larger than the max level allowed, it will be force to be max level.
  583. * - When you set level value you need use clciinfo.nlbits to get the width of level.
  584. * Then we could know the maximum of level. CLICINTCTLBITS is how many total bits are
  585. * present in the CLICINTCTL register.
  586. * \sa
  587. * - \ref ECLIC_GetLevelIRQ
  588. */
  589. __STATIC_INLINE void __ECLIC_SetLevelIRQ(IRQn_Type IRQn, uint8_t lvl_abs)
  590. {
  591. uint8_t nlbits = __ECLIC_GetCfgNlbits();
  592. uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
  593. if (nlbits == 0) {
  594. return;
  595. }
  596. if (nlbits > intctlbits) {
  597. nlbits = intctlbits;
  598. }
  599. uint8_t maxlvl = ((1UL << nlbits) - 1);
  600. if (lvl_abs > maxlvl) {
  601. lvl_abs = maxlvl;
  602. }
  603. uint8_t lvl = lvl_abs << (ECLIC_MAX_NLBITS - nlbits);
  604. uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ(IRQn);
  605. cur_ctrl = cur_ctrl << nlbits;
  606. cur_ctrl = cur_ctrl >> nlbits;
  607. __ECLIC_SetCtrlIRQ(IRQn, (cur_ctrl | lvl));
  608. }
  609. /**
  610. * \brief Get ECLIC Interrupt level of a specific interrupt
  611. * \details
  612. * This function get interrupt level of the specific interrupt \em IRQn.
  613. * \param [in] IRQn Interrupt number
  614. * \return Interrupt level
  615. * \remarks
  616. * - IRQn must not be negative.
  617. * \sa
  618. * - \ref ECLIC_SetLevelIRQ
  619. */
  620. __STATIC_INLINE uint8_t __ECLIC_GetLevelIRQ(IRQn_Type IRQn)
  621. {
  622. uint8_t nlbits = __ECLIC_GetCfgNlbits();
  623. uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
  624. if (nlbits == 0) {
  625. return 0;
  626. }
  627. if (nlbits > intctlbits) {
  628. nlbits = intctlbits;
  629. }
  630. uint8_t intctrl = __ECLIC_GetCtrlIRQ(IRQn);
  631. uint8_t lvl_abs = intctrl >> (ECLIC_MAX_NLBITS - nlbits);
  632. return lvl_abs;
  633. }
  634. /**
  635. * \brief Get ECLIC Interrupt priority of a specific interrupt
  636. * \details
  637. * This function get interrupt priority of the specific interrupt \em IRQn.
  638. * \param [in] IRQn Interrupt number
  639. * \param [in] pri Interrupt priority
  640. * \remarks
  641. * - IRQn must not be negative.
  642. * - If pri to be set is larger than the max priority allowed, it will be force to be max priority.
  643. * - Priority width is CLICINTCTLBITS minus clciinfo.nlbits if clciinfo.nlbits
  644. * is less than CLICINTCTLBITS. Otherwise priority width is 0.
  645. * \sa
  646. * - \ref ECLIC_GetPriorityIRQ
  647. */
  648. __STATIC_INLINE void __ECLIC_SetPriorityIRQ(IRQn_Type IRQn, uint8_t pri)
  649. {
  650. uint8_t nlbits = __ECLIC_GetCfgNlbits();
  651. uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
  652. if (nlbits < intctlbits) {
  653. uint8_t maxpri = ((1UL << (intctlbits - nlbits)) - 1);
  654. if (pri > maxpri) {
  655. pri = maxpri;
  656. }
  657. pri = pri << (ECLIC_MAX_NLBITS - intctlbits);
  658. uint8_t mask = ((uint8_t)(-1)) >> intctlbits;
  659. pri = pri | mask;
  660. uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ(IRQn);
  661. cur_ctrl = cur_ctrl >> (ECLIC_MAX_NLBITS - nlbits);
  662. cur_ctrl = cur_ctrl << (ECLIC_MAX_NLBITS - nlbits);
  663. __ECLIC_SetCtrlIRQ(IRQn, (cur_ctrl | pri));
  664. }
  665. }
  666. /**
  667. * \brief Get ECLIC Interrupt priority of a specific interrupt
  668. * \details
  669. * This function get interrupt priority of the specific interrupt \em IRQn.
  670. * \param [in] IRQn Interrupt number
  671. * \return Interrupt priority
  672. * \remarks
  673. * - IRQn must not be negative.
  674. * \sa
  675. * - \ref ECLIC_SetPriorityIRQ
  676. */
  677. __STATIC_INLINE uint8_t __ECLIC_GetPriorityIRQ(IRQn_Type IRQn)
  678. {
  679. uint8_t nlbits = __ECLIC_GetCfgNlbits();
  680. uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
  681. if (nlbits < intctlbits) {
  682. uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ(IRQn);
  683. uint8_t pri = cur_ctrl << nlbits;
  684. pri = pri >> nlbits;
  685. pri = pri >> (ECLIC_MAX_NLBITS - intctlbits);
  686. return pri;
  687. } else {
  688. return 0;
  689. }
  690. }
  691. /**
  692. * \brief Set Interrupt Vector of a specific interrupt
  693. * \details
  694. * This function set interrupt handler address of the specific interrupt \em IRQn.
  695. * \param [in] IRQn Interrupt number
  696. * \param [in] vector Interrupt handler address
  697. * \remarks
  698. * - IRQn must not be negative.
  699. * - You can set the \ref CSR_CSR_MTVT to set interrupt vector table entry address.
  700. * - If your vector table is placed in readonly section, the vector for IRQn will not be modified.
  701. * For this case, you need to use the correct irq handler name defined in your vector table as
  702. * your irq handler function name.
  703. * - This function will only work correctly when the vector table is placed in an read-write enabled section.
  704. * \sa
  705. * - \ref ECLIC_GetVector
  706. */
  707. __STATIC_INLINE void __ECLIC_SetVector(IRQn_Type IRQn, rv_csr_t vector)
  708. {
  709. volatile unsigned long vec_base;
  710. vec_base = ((unsigned long)__RV_CSR_READ(CSR_MTVT));
  711. vec_base += ((unsigned long)IRQn) * sizeof(unsigned long);
  712. (* (unsigned long *) vec_base) = vector;
  713. #if (defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1))
  714. #if (defined(__CCM_PRESENT) && (__CCM_PRESENT == 1))
  715. MFlushDCacheLine((unsigned long)vec_base);
  716. #endif
  717. #endif
  718. #if (defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1))
  719. #if (defined(__CCM_PRESENT) && (__CCM_PRESENT == 1))
  720. MInvalICacheLine((unsigned long)vec_base);
  721. #else
  722. __FENCE_I();
  723. #endif
  724. #endif
  725. }
  726. /**
  727. * \brief Get Interrupt Vector of a specific interrupt
  728. * \details
  729. * This function get interrupt handler address of the specific interrupt \em IRQn.
  730. * \param [in] IRQn Interrupt number
  731. * \return Interrupt handler address
  732. * \remarks
  733. * - IRQn must not be negative.
  734. * - You can read \ref CSR_CSR_MTVT to get interrupt vector table entry address.
  735. * \sa
  736. * - \ref ECLIC_SetVector
  737. */
  738. __STATIC_FORCEINLINE rv_csr_t __ECLIC_GetVector(IRQn_Type IRQn)
  739. {
  740. #if __RISCV_XLEN == 32
  741. return (*(uint32_t *)(__RV_CSR_READ(CSR_MTVT) + IRQn * 4));
  742. #elif __RISCV_XLEN == 64
  743. return (*(uint64_t *)(__RV_CSR_READ(CSR_MTVT) + IRQn * 8));
  744. #else // TODO Need cover for XLEN=128 case in future
  745. return (*(uint64_t *)(__RV_CSR_READ(CSR_MTVT) + IRQn * 8));
  746. #endif
  747. }
  748. #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
  749. /**
  750. * \brief Set privilege mode of a specific interrupt
  751. * \details
  752. * This function set in which privilege mode the interrupts \em IRQn should be taken.
  753. * \param [in] IRQn Interrupt number
  754. * \param [in] mode Privilege mode
  755. * \remarks
  756. * - IRQn must not be negative.
  757. * - mode must be 1(Supervisor Mode) or 3(Machine Mode), other values are ignored.
  758. * - M-mode can R/W this field, but S-mode can only read.And ECLIC with TEE does not
  759. * reply on CSR mideleg to delegate interrupts.
  760. * - Mode of S-mode ECLIC region's clicintattr can be omitted to set, which is mirror to M-mode ECLIC region's.
  761. * Only the low 6 bits of clicintattr [i] can be written via the S-mode memory region.
  762. */
  763. __STATIC_FORCEINLINE void __ECLIC_SetModeIRQ(IRQn_Type IRQn, uint32_t mode)
  764. {
  765. /*
  766. * only 1 or 3 can be assigned to mode in one step.the default value of mode is 3,
  767. * which can't be clear to 0 firstly, then OR it to 1
  768. */
  769. ECLIC->CTRL[IRQn].INTATTR = (uint8_t)(mode << CLIC_INTATTR_MODE_Pos) + \
  770. (ECLIC->SCTRL[IRQn].INTATTR & (~CLIC_INTATTR_MODE_Msk));
  771. }
  772. /**
  773. * \brief Set supervisor-mode Interrupt Level Threshold in supervisor mode
  774. * \details
  775. * This function sets supervisor-mode interrupt level threshold.
  776. * \param [in] sth Interrupt Level Threshold.
  777. * \remarks
  778. * - S-mode ECLIC region sintthresh'sth is a mirror to M-mode ECLIC region's mintthresh.sth,
  779. * and will be updated synchronously, here operate on mintthresh.sth.
  780. * \sa
  781. * - \ref ECLIC_GetSth
  782. */
  783. __STATIC_FORCEINLINE void __ECLIC_SetSth(uint8_t sth)
  784. {
  785. ECLIC->STH = sth;
  786. }
  787. /**
  788. * \brief Get supervisor-mode Interrupt Level Threshold in supervisor mode
  789. * \details
  790. * This function gets supervisor mode interrupt level threshold.
  791. * \return Interrupt Level Threshold.
  792. * \remarks
  793. * - S-mode ECLIC region sintthresh'sth is a mirror to M-mode ECLIC region's mintthresh.sth,
  794. * and will be updated synchronously, here operate on mintthresh.sth.
  795. * \sa
  796. * - \ref ECLIC_SetSth
  797. */
  798. __STATIC_FORCEINLINE uint8_t __ECLIC_GetSth(void)
  799. {
  800. return (ECLIC->STH);
  801. }
  802. /**
  803. * \brief Set trigger mode and polarity for a specific interrupt in supervisor mode
  804. * \details
  805. * This function set trigger mode and polarity of the specific interrupt \em IRQn.
  806. * \param [in] IRQn Interrupt number
  807. * \param [in] trig
  808. * - 00 level trigger, \ref ECLIC_LEVEL_TRIGGER
  809. * - 01 positive edge trigger, \ref ECLIC_POSTIVE_EDGE_TRIGGER
  810. * - 02 level trigger, \ref ECLIC_LEVEL_TRIGGER
  811. * - 03 negative edge trigger, \ref ECLIC_NEGTIVE_EDGE_TRIGGER
  812. * \remarks
  813. * - IRQn must not be negative.
  814. *
  815. * \sa
  816. * - \ref ECLIC_GetTrigIRQ_S
  817. */
  818. __STATIC_FORCEINLINE void __ECLIC_SetTrigIRQ_S(IRQn_Type IRQn, uint32_t trig)
  819. {
  820. uint8_t temp = ECLIC->SCTRL[IRQn].INTATTR;
  821. ECLIC->SCTRL[IRQn].INTATTR = (temp & ~CLIC_INTATTR_TRIG_Msk) | \
  822. ((uint8_t)(trig << CLIC_INTATTR_TRIG_Pos));
  823. }
  824. /**
  825. * \brief Get trigger mode and polarity for a specific interrupt in supervisor mode
  826. * \details
  827. * This function get trigger mode and polarity of the specific interrupt \em IRQn.
  828. * \param [in] IRQn Interrupt number
  829. * \return
  830. * - 00 level trigger, \ref ECLIC_LEVEL_TRIGGER
  831. * - 01 positive edge trigger, \ref ECLIC_POSTIVE_EDGE_TRIGGER
  832. * - 02 level trigger, \ref ECLIC_LEVEL_TRIGGER
  833. * - 03 negative edge trigger, \ref ECLIC_NEGTIVE_EDGE_TRIGGER
  834. * \remarks
  835. * - IRQn must not be negative.
  836. * \sa
  837. * - \ref ECLIC_SetTrigIRQ_S
  838. */
  839. __STATIC_FORCEINLINE uint8_t __ECLIC_GetTrigIRQ_S(IRQn_Type IRQn)
  840. {
  841. return ((uint8_t)(((ECLIC->SCTRL[IRQn].INTATTR) & CLIC_INTATTR_TRIG_Msk) >> CLIC_INTATTR_TRIG_Pos));
  842. }
  843. /**
  844. * \brief Set interrupt working mode for a specific interrupt in supervisor mode
  845. * \details
  846. * This function set selective hardware vector or non-vector working mode of the specific interrupt \em IRQn.
  847. * \param [in] IRQn Interrupt number
  848. * \param [in] shv
  849. * - 0 non-vector mode, \ref ECLIC_NON_VECTOR_INTERRUPT
  850. * - 1 vector mode, \ref ECLIC_VECTOR_INTERRUPT
  851. * \remarks
  852. * - IRQn must not be negative.
  853. * \sa
  854. * - \ref ECLIC_GetShvIRQ_S
  855. */
  856. __STATIC_FORCEINLINE void __ECLIC_SetShvIRQ_S(IRQn_Type IRQn, uint32_t shv)
  857. {
  858. uint8_t temp = ECLIC->SCTRL[IRQn].INTATTR;
  859. ECLIC->SCTRL[IRQn].INTATTR = (temp & ~CLIC_INTATTR_SHV_Msk) | \
  860. ((uint8_t)(shv << CLIC_INTATTR_SHV_Pos));
  861. }
  862. /**
  863. * \brief Get interrupt working mode for a specific interrupt in supervisor mode
  864. * \details
  865. * This function get selective hardware vector or non-vector working mode of the specific interrupt \em IRQn.
  866. * \param [in] IRQn Interrupt number
  867. * \return shv
  868. * - 0 non-vector mode, \ref ECLIC_NON_VECTOR_INTERRUPT
  869. * - 1 vector mode, \ref ECLIC_VECTOR_INTERRUPT
  870. * \remarks
  871. * - IRQn must not be negative.
  872. * \sa
  873. * - \ref ECLIC_SMODE_SetShvIRQ
  874. */
  875. __STATIC_FORCEINLINE uint8_t __ECLIC_GetShvIRQ_S(IRQn_Type IRQn)
  876. {
  877. return ((uint8_t)(((ECLIC->SCTRL[IRQn].INTATTR) & CLIC_INTATTR_SHV_Msk) >> CLIC_INTATTR_SHV_Pos));
  878. }
  879. /**
  880. * \brief Modify ECLIC Interrupt Input Control Register for a specific interrupt in supervisor mode
  881. * \details
  882. * This function modify ECLIC Interrupt Input Control(CLICINTCTL[i]) register of the specific interrupt \em IRQn.
  883. * \param [in] IRQn Interrupt number
  884. * \param [in] intctrl Set value for CLICINTCTL[i] register
  885. * \remarks
  886. * - IRQn must not be negative.
  887. * \sa
  888. * - \ref ECLIC_GetCtrlIRQ_S
  889. */
  890. __STATIC_FORCEINLINE void __ECLIC_SetCtrlIRQ_S(IRQn_Type IRQn, uint8_t intctrl)
  891. {
  892. ECLIC->SCTRL[IRQn].INTCTRL = intctrl;
  893. }
  894. /**
  895. * \brief Get ECLIC Interrupt Input Control Register value for a specific interrupt in supervisor mode
  896. * \details
  897. * This function modify ECLIC Interrupt Input Control register of the specific interrupt \em IRQn.
  898. * \param [in] IRQn Interrupt number
  899. * \return value of ECLIC Interrupt Input Control register
  900. * \remarks
  901. * - IRQn must not be negative.
  902. * \sa
  903. * - \ref ECLIC_SetCtrlIRQ_S
  904. */
  905. __STATIC_FORCEINLINE uint8_t __ECLIC_GetCtrlIRQ_S(IRQn_Type IRQn)
  906. {
  907. return (ECLIC->SCTRL[IRQn].INTCTRL);
  908. }
  909. /**
  910. * \brief Set ECLIC Interrupt level of a specific interrupt in supervisor mode
  911. * \details
  912. * This function set interrupt level of the specific interrupt \em IRQn.
  913. * \param [in] IRQn Interrupt number
  914. * \param [in] lvl_abs Interrupt level
  915. * \remarks
  916. * - IRQn must not be negative.
  917. * - If lvl_abs to be set is larger than the max level allowed, it will be force to be max level.
  918. * - When you set level value you need use clciinfo.nlbits to get the width of level.
  919. * Then we could know the maximum of level. CLICINTCTLBITS is how many total bits are
  920. * present in the CLICINTCTL register.
  921. * \sa
  922. * - \ref ECLIC_GetLevelIRQ_S
  923. */
  924. __STATIC_INLINE void __ECLIC_SetLevelIRQ_S(IRQn_Type IRQn, uint8_t lvl_abs)
  925. {
  926. uint8_t nlbits = __ECLIC_GetCfgNlbits();
  927. uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
  928. if (nlbits == 0) {
  929. return;
  930. }
  931. if (nlbits > intctlbits) {
  932. nlbits = intctlbits;
  933. }
  934. uint8_t maxlvl = ((1UL << nlbits) - 1);
  935. if (lvl_abs > maxlvl) {
  936. lvl_abs = maxlvl;
  937. }
  938. uint8_t lvl = lvl_abs << (ECLIC_MAX_NLBITS - nlbits);
  939. uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ_S(IRQn);
  940. cur_ctrl = cur_ctrl << nlbits;
  941. cur_ctrl = cur_ctrl >> nlbits;
  942. __ECLIC_SetCtrlIRQ_S(IRQn, (cur_ctrl | lvl));
  943. }
  944. /**
  945. * \brief Get ECLIC Interrupt level of a specific interrupt
  946. * \details
  947. * This function get interrupt level of the specific interrupt \em IRQn.
  948. * \param [in] IRQn Interrupt number
  949. * \return Interrupt level
  950. * \remarks
  951. * - IRQn must not be negative.
  952. * \sa
  953. * - \ref ECLIC_SetLevelIRQ_S
  954. */
  955. __STATIC_INLINE uint8_t __ECLIC_GetLevelIRQ_S(IRQn_Type IRQn)
  956. {
  957. uint8_t nlbits = __ECLIC_GetCfgNlbits();
  958. uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
  959. if (nlbits == 0) {
  960. return 0;
  961. }
  962. if (nlbits > intctlbits) {
  963. nlbits = intctlbits;
  964. }
  965. uint8_t intctrl = __ECLIC_GetCtrlIRQ_S(IRQn);
  966. uint8_t lvl_abs = intctrl >> (ECLIC_MAX_NLBITS - nlbits);
  967. return lvl_abs;
  968. }
  969. /**
  970. * \brief Set ECLIC Interrupt priority of a specific interrupt in supervisor mode
  971. * \details
  972. * This function get interrupt priority of the specific interrupt \em IRQn.
  973. * \param [in] IRQn Interrupt number
  974. * \param [in] pri Interrupt priority
  975. * \remarks
  976. * - IRQn must not be negative.
  977. * - If pri to be set is larger than the max priority allowed, it will be force to be max priority.
  978. * - Priority width is CLICINTCTLBITS minus clciinfo.nlbits if clciinfo.nlbits
  979. * is less than CLICINTCTLBITS. Otherwise priority width is 0.
  980. * \sa
  981. * - \ref ECLIC_GetPriorityIRQ_S
  982. */
  983. __STATIC_INLINE void __ECLIC_SetPriorityIRQ_S(IRQn_Type IRQn, uint8_t pri)
  984. {
  985. uint8_t nlbits = __ECLIC_GetCfgNlbits();
  986. uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
  987. if (nlbits < intctlbits) {
  988. uint8_t maxpri = ((1UL << (intctlbits - nlbits)) - 1);
  989. if (pri > maxpri) {
  990. pri = maxpri;
  991. }
  992. pri = pri << (ECLIC_MAX_NLBITS - intctlbits);
  993. uint8_t mask = ((uint8_t)(-1)) >> intctlbits;
  994. pri = pri | mask;
  995. uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ_S(IRQn);
  996. cur_ctrl = cur_ctrl >> (ECLIC_MAX_NLBITS - nlbits);
  997. cur_ctrl = cur_ctrl << (ECLIC_MAX_NLBITS - nlbits);
  998. __ECLIC_SetCtrlIRQ_S(IRQn, (cur_ctrl | pri));
  999. }
  1000. }
  1001. /**
  1002. * \brief Get ECLIC Interrupt priority of a specific interrupt in supervisor mode
  1003. * \details
  1004. * This function get interrupt priority of the specific interrupt \em IRQn.
  1005. * \param [in] IRQn Interrupt number
  1006. * \return Interrupt priority
  1007. * \remarks
  1008. * - IRQn must not be negative.
  1009. * \sa
  1010. * - \ref ECLIC_SetPriorityIRQ_S
  1011. */
  1012. __STATIC_INLINE uint8_t __ECLIC_GetPriorityIRQ_S(IRQn_Type IRQn)
  1013. {
  1014. uint8_t nlbits = __ECLIC_GetCfgNlbits();
  1015. uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
  1016. if (nlbits < intctlbits) {
  1017. uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ_S(IRQn);
  1018. uint8_t pri = cur_ctrl << nlbits;
  1019. pri = pri >> nlbits;
  1020. pri = pri >> (ECLIC_MAX_NLBITS - intctlbits);
  1021. return pri;
  1022. } else {
  1023. return 0;
  1024. }
  1025. }
  1026. /**
  1027. * \brief Enable a specific interrupt in supervisor mode
  1028. * \details
  1029. * This function enables the specific interrupt \em IRQn.
  1030. * \param [in] IRQn Interrupt number
  1031. * \remarks
  1032. * - IRQn must not be negative.
  1033. * \sa
  1034. * - \ref ECLIC_DisableIRQ
  1035. */
  1036. __STATIC_FORCEINLINE void __ECLIC_EnableIRQ_S(IRQn_Type IRQn)
  1037. {
  1038. ECLIC->SCTRL[IRQn].INTIE |= CLIC_INTIE_IE_Msk;
  1039. }
  1040. /**
  1041. * \brief Get a specific interrupt enable status in supervisor mode
  1042. * \details
  1043. * This function returns the interrupt enable status for the specific interrupt \em IRQn in S MODE.
  1044. * \param [in] IRQn Interrupt number
  1045. * \returns
  1046. * - 0 Interrupt is not masked
  1047. * - 1 Interrupt is enabled
  1048. * \remarks
  1049. * - IRQn must not be negative.
  1050. * \sa
  1051. * - \ref ECLIC_EnableIRQ_S
  1052. * - \ref ECLIC_DisableIRQ_S
  1053. */
  1054. __STATIC_FORCEINLINE uint8_t __ECLIC_GetEnableIRQ_S(IRQn_Type IRQn)
  1055. {
  1056. return ((uint8_t) (ECLIC->SCTRL[IRQn].INTIE) & CLIC_INTIE_IE_Msk);
  1057. }
  1058. /**
  1059. * \brief Disable a specific interrupt in supervisor mode
  1060. * \details
  1061. * This function disables the specific interrupt \em IRQn.
  1062. * \param [in] IRQn Number of the external interrupt to disable
  1063. * \remarks
  1064. * - IRQn must not be negative.
  1065. * \sa
  1066. * - \ref ECLIC_EnableIRQ
  1067. */
  1068. __STATIC_FORCEINLINE void __ECLIC_DisableIRQ_S(IRQn_Type IRQn)
  1069. {
  1070. ECLIC->SCTRL[IRQn].INTIE &= ~CLIC_INTIE_IE_Msk;
  1071. }
  1072. /**
  1073. * \brief Set Interrupt Vector of a specific interrupt in supervisor mode
  1074. * \details
  1075. * This function set interrupt handler address of the specific interrupt \em IRQn.
  1076. * \param [in] IRQn Interrupt number
  1077. * \param [in] vector Interrupt handler address
  1078. * \remarks
  1079. * - IRQn must not be negative.
  1080. * - You can set the \ref CSR_CSR_MTVT to set interrupt vector table entry address.
  1081. * - If your vector table is placed in readonly section, the vector for IRQn will not be modified.
  1082. * For this case, you need to use the correct irq handler name defined in your vector table as
  1083. * your irq handler function name.
  1084. * - This function will only work correctly when the vector table is placed in an read-write enabled section.
  1085. * \sa
  1086. * - \ref ECLIC_GetVector_S
  1087. */
  1088. __STATIC_INLINE void __ECLIC_SetVector_S(IRQn_Type IRQn, rv_csr_t vector)
  1089. {
  1090. volatile unsigned long vec_base;
  1091. vec_base = ((unsigned long)__RV_CSR_READ(CSR_STVT));
  1092. vec_base += ((unsigned long)IRQn) * sizeof(unsigned long);
  1093. (* (unsigned long *) vec_base) = vector;
  1094. #if (defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1))
  1095. #if (defined(__CCM_PRESENT) && (__CCM_PRESENT == 1))
  1096. SFlushDCacheLine((unsigned long)vec_base);
  1097. #endif
  1098. #endif
  1099. #if (defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1))
  1100. #if (defined(__CCM_PRESENT) && (__CCM_PRESENT == 1))
  1101. SInvalICacheLine((unsigned long)vec_base);
  1102. #else
  1103. __FENCE_I();
  1104. #endif
  1105. #endif
  1106. }
  1107. /**
  1108. * \brief Get Interrupt Vector of a specific interrupt in supervisor mode
  1109. * \details
  1110. * This function get interrupt handler address of the specific interrupt \em IRQn.
  1111. * \param [in] IRQn Interrupt number
  1112. * \return Interrupt handler address
  1113. * \remarks
  1114. * - IRQn must not be negative.
  1115. * - You can read \ref CSR_CSR_MTVT to get interrupt vector table entry address.
  1116. * \sa
  1117. * - \ref ECLIC_SMODE_SetVector
  1118. */
  1119. __STATIC_FORCEINLINE rv_csr_t __ECLIC_GetVector_S(IRQn_Type IRQn)
  1120. {
  1121. #if __RISCV_XLEN == 32
  1122. return (*(uint32_t *)(__RV_CSR_READ(CSR_STVT) + IRQn * 4));
  1123. #elif __RISCV_XLEN == 64
  1124. return (*(uint64_t *)(__RV_CSR_READ(CSR_STVT) + IRQn * 8));
  1125. #else // TODO Need cover for XLEN=128 case in future
  1126. return (*(uint64_t *)(__RV_CSR_READ(CSR_STVT) + IRQn * 8));
  1127. #endif
  1128. }
  1129. #endif /* defined(__TEE_PRESENT) && (__TEE_PRESENT == 1) */
  1130. /**
  1131. * \brief Set Exception entry address
  1132. * \details
  1133. * This function set exception handler address to 'CSR_MTVEC'.
  1134. * \param [in] addr Exception handler address
  1135. * \remarks
  1136. * - This function use to set exception handler address to 'CSR_MTVEC'.
  1137. * Address need to be aligned to 64 bytes.
  1138. * \sa
  1139. * - \ref __get_exc_entry
  1140. */
  1141. __STATIC_FORCEINLINE void __set_exc_entry(rv_csr_t addr)
  1142. {
  1143. addr &= (rv_csr_t)(~0x3F);
  1144. addr |= ECLIC_MODE_MTVEC_Msk;
  1145. __RV_CSR_WRITE(CSR_MTVEC, addr);
  1146. }
  1147. /**
  1148. * \brief Get Exception entry address
  1149. * \details
  1150. * This function get exception handler address from 'CSR_MTVEC'.
  1151. * \return Exception handler address
  1152. * \remarks
  1153. * - This function use to get exception handler address from 'CSR_MTVEC'.
  1154. * Address need to be aligned to 64 bytes.
  1155. * \sa
  1156. * - \ref __set_exc_entry
  1157. */
  1158. __STATIC_FORCEINLINE rv_csr_t __get_exc_entry(void)
  1159. {
  1160. unsigned long addr = __RV_CSR_READ(CSR_MTVEC);
  1161. return (addr & ~ECLIC_MODE_MTVEC_Msk);
  1162. }
  1163. /**
  1164. * \brief Set Non-vector interrupt entry address
  1165. * \details
  1166. * This function set Non-vector interrupt address.
  1167. * \param [in] addr Non-vector interrupt entry address
  1168. * \remarks
  1169. * - This function use to set non-vector interrupt entry address to 'CSR_MTVT2' if
  1170. * - CSR_MTVT2 bit0 is 1. If 'CSR_MTVT2' bit0 is 0 then set address to 'CSR_MTVEC'
  1171. * \sa
  1172. * - \ref __get_nonvec_entry
  1173. */
  1174. __STATIC_INLINE void __set_nonvec_entry(rv_csr_t addr)
  1175. {
  1176. if (__RV_CSR_READ(CSR_MTVT2) & 0x1) {
  1177. __RV_CSR_WRITE(CSR_MTVT2, addr | 0x01);
  1178. } else {
  1179. addr &= (rv_csr_t)(~0x3F);
  1180. addr |= ECLIC_MODE_MTVEC_Msk;
  1181. __RV_CSR_WRITE(CSR_MTVEC, addr);
  1182. }
  1183. }
  1184. /**
  1185. * \brief Get Non-vector interrupt entry address
  1186. * \details
  1187. * This function get Non-vector interrupt address.
  1188. * \return Non-vector interrupt handler address
  1189. * \remarks
  1190. * - This function use to get non-vector interrupt entry address from 'CSR_MTVT2' if
  1191. * - CSR_MTVT2 bit0 is 1. If 'CSR_MTVT2' bit0 is 0 then get address from 'CSR_MTVEC'.
  1192. * \sa
  1193. * - \ref __set_nonvec_entry
  1194. */
  1195. __STATIC_INLINE rv_csr_t __get_nonvec_entry(void)
  1196. {
  1197. if (__RV_CSR_READ(CSR_MTVT2) & 0x1) {
  1198. return __RV_CSR_READ(CSR_MTVT2) & (~(rv_csr_t)(0x1));
  1199. } else {
  1200. rv_csr_t addr = __RV_CSR_READ(CSR_MTVEC);
  1201. return (addr & ~ECLIC_MODE_MTVEC_Msk);
  1202. }
  1203. }
  1204. /**
  1205. * \brief Get NMI interrupt entry from 'CSR_MNVEC'
  1206. * \details
  1207. * This function get NMI interrupt address from 'CSR_MNVEC'.
  1208. * \return NMI interrupt handler address
  1209. * \remarks
  1210. * - This function use to get NMI interrupt handler address from 'CSR_MNVEC'. If CSR_MMISC_CTL[9] = 1 'CSR_MNVEC'
  1211. * - will be equal as mtvec. If CSR_MMISC_CTL[9] = 0 'CSR_MNVEC' will be equal as reset vector.
  1212. * - NMI entry is defined via \ref CSR_MMISC_CTL, writing to \ref CSR_MNVEC will be ignored.
  1213. */
  1214. __STATIC_FORCEINLINE rv_csr_t __get_nmi_entry(void)
  1215. {
  1216. return __RV_CSR_READ(CSR_MNVEC);
  1217. }
  1218. /**
  1219. * \brief Save necessary CSRs into variables for vector interrupt nesting
  1220. * \details
  1221. * This macro is used to declare variables which are used for saving
  1222. * CSRs(MCAUSE, MEPC, MSUB), and it will read these CSR content into
  1223. * these variables, it need to be used in a vector-interrupt if nesting
  1224. * is required.
  1225. * \remarks
  1226. * - Interrupt will be enabled after this macro is called
  1227. * - It need to be used together with \ref RESTORE_IRQ_CSR_CONTEXT
  1228. * - Don't use variable names __mcause, __mpec, __msubm in your ISR code
  1229. * - If you want to enable interrupt nesting feature for vector interrupt,
  1230. * you can do it like this:
  1231. * \code
  1232. * // __INTERRUPT attribute will generates function entry and exit sequences suitable
  1233. * // for use in an interrupt handler when this attribute is present
  1234. * __INTERRUPT void eclic_mtip_handler(void)
  1235. * {
  1236. * // Must call this to save CSRs
  1237. * SAVE_IRQ_CSR_CONTEXT();
  1238. * // !!!Interrupt is enabled here!!!
  1239. * // !!!Higher priority interrupt could nest it!!!
  1240. *
  1241. * // put you own interrupt handling code here
  1242. *
  1243. * // Must call this to restore CSRs
  1244. * RESTORE_IRQ_CSR_CONTEXT();
  1245. * }
  1246. * \endcode
  1247. */
  1248. #define SAVE_IRQ_CSR_CONTEXT() \
  1249. rv_csr_t __mcause = __RV_CSR_READ(CSR_MCAUSE); \
  1250. rv_csr_t __mepc = __RV_CSR_READ(CSR_MEPC); \
  1251. rv_csr_t __msubm = __RV_CSR_READ(CSR_MSUBM); \
  1252. __enable_irq();
  1253. /*! Save necessary CSRs into variables for vector interrupt nesting in supervisor mode */
  1254. #define SAVE_IRQ_CSR_CONTEXT_S() \
  1255. rv_csr_t __scause = __RV_CSR_READ(CSR_SCAUSE); \
  1256. rv_csr_t __sepc = __RV_CSR_READ(CSR_SEPC); \
  1257. __enable_irq_s();
  1258. /**
  1259. * \brief Restore necessary CSRs from variables for vector interrupt nesting
  1260. * \details
  1261. * This macro is used restore CSRs(MCAUSE, MEPC, MSUB) from pre-defined variables
  1262. * in \ref SAVE_IRQ_CSR_CONTEXT macro.
  1263. * \remarks
  1264. * - Interrupt will be disabled after this macro is called
  1265. * - It need to be used together with \ref SAVE_IRQ_CSR_CONTEXT
  1266. */
  1267. #define RESTORE_IRQ_CSR_CONTEXT() \
  1268. __disable_irq(); \
  1269. __RV_CSR_WRITE(CSR_MSUBM, __msubm); \
  1270. __RV_CSR_WRITE(CSR_MEPC, __mepc); \
  1271. __RV_CSR_WRITE(CSR_MCAUSE, __mcause);
  1272. /*! Restore necessary CSRs from variables for vector interrupt nesting in supervisor mode */
  1273. #define RESTORE_IRQ_CSR_CONTEXT_S() \
  1274. __disable_irq_s(); \
  1275. __RV_CSR_WRITE(CSR_SEPC, __sepc); \
  1276. __RV_CSR_WRITE(CSR_SCAUSE, __scause);
  1277. /** @} */ /* End of Doxygen Group NMSIS_Core_IntExc */
  1278. #endif /* defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1) */
  1279. #ifdef __cplusplus
  1280. }
  1281. #endif
  1282. #endif /* __CORE_FEATURE_ECLIC__ */