core_feature_eclic.h 73 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922
  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 Hardware implementation version number. 1: version 1. 2: version 2, support hardware context saving and restoring. */
  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 shd_num:4; /*!< bit: 25..28 number of shadow register groups for single mode(M/S mode) */
  72. __IM uint32_t _reserved0:3; /*!< bit: 29..31 Reserved */
  73. } b; /*!< Structure used for bit access */
  74. __IM uint32_t w; /*!< Type used for word access */
  75. } CLICINFO_Type;
  76. /**
  77. * \brief Access to the machine mode register structure of INTIP, INTIE, INTATTR, INTCTL.
  78. */
  79. typedef struct {
  80. __IOM uint8_t INTIP; /*!< Offset: 0x000 (R/W) Interrupt set pending register */
  81. __IOM uint8_t INTIE; /*!< Offset: 0x001 (R/W) Interrupt set enable register */
  82. __IOM uint8_t INTATTR; /*!< Offset: 0x002 (R/W) Interrupt set attributes register */
  83. __IOM uint8_t INTCTRL; /*!< Offset: 0x003 (R/W) Interrupt configure register */
  84. } CLIC_CTRL_Type;
  85. /**
  86. * \brief Access to the structure of ECLIC Memory Map, which is compatible with TEE.
  87. */
  88. typedef struct {
  89. __IOM uint8_t CFG; /*!< Offset: 0x000 (R/W) CLIC configuration register */
  90. __IM uint8_t RESERVED0[3];
  91. __IM uint32_t INFO; /*!< Offset: 0x004 (R/ ) CLIC information register */
  92. __IM uint8_t RESERVED1;
  93. #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
  94. __IOM uint8_t STH; /*!< Offset: 0x009 (R/W ) CLIC supervisor mode interrupt-level threshold */
  95. #else
  96. __IM uint8_t RESERVED2;
  97. #endif
  98. __IM uint8_t RESERVED3;
  99. __IOM uint8_t MTH; /*!< Offset: 0x00B(R/W) CLIC machine mode interrupt-level threshold */
  100. uint32_t RESERVED4[1021];
  101. #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
  102. CLIC_CTRL_Type CTRL[1024]; /*!< Offset: 0x1000 (R/W) CLIC machine mode register structure for INTIP, INTIE, INTATTR, INTCTL */
  103. __IM uint32_t RESERVED5[2];
  104. __IM uint8_t RESERVED6;
  105. __IOM uint8_t SSTH; /*!< Offset: 0x2009 (R) CLIC supervisor mode threshold register, which is a mirror to mintthresh.sth */
  106. __IM uint8_t RESERVED7;
  107. __IM uint8_t RESERVED8;
  108. __IM uint32_t RESERVED9[1021];
  109. CLIC_CTRL_Type SCTRL[1024]; /*!< Offset: 0x3000 (R/W) CLIC supervisor mode register structure for INTIP, INTIE, INTATTR, INTCTL */
  110. #else
  111. CLIC_CTRL_Type CTRL[4096]; /*!< Offset: 0x1000 (R/W) CLIC machine mode register structure for INTIP, INTIE, INTATTR, INTCTL */
  112. #endif
  113. } CLIC_Type;
  114. #define CLIC_CLICCFG_NLBIT_Pos 1U /*!< CLIC CLICCFG: NLBIT Position */
  115. #define CLIC_CLICCFG_NLBIT_Msk (0xFUL << CLIC_CLICCFG_NLBIT_Pos) /*!< CLIC CLICCFG: NLBIT Mask */
  116. #define CLIC_CLICINFO_CTLBIT_Pos 21U /*!< CLIC INTINFO: CLICINTCTLBITS Position */
  117. #define CLIC_CLICINFO_CTLBIT_Msk (0xFUL << CLIC_CLICINFO_CTLBIT_Pos) /*!< CLIC INTINFO: CLICINTCTLBITS Mask */
  118. #define CLIC_CLICINFO_VER_Pos 13U /*!< CLIC CLICINFO: VERSION Position */
  119. #define CLIC_CLICINFO_VER_Msk (0xFFUL << CLIC_CLICINFO_VER_Pos) /*!< CLIC CLICINFO: VERSION Mask */
  120. #define CLIC_CLICINFO_NUM_Pos 0U /*!< CLIC CLICINFO: NUM_INTERRUPT Position */
  121. #define CLIC_CLICINFO_NUM_Msk (0x1FFFUL << CLIC_CLICINFO_NUM_Pos) /*!< CLIC CLICINFO: NUM_INTERRUPT Mask */
  122. #define CLIC_CLICINFO_SHD_NUM_Pos 25U /*!< CLIC CLICINFO: SHD_NUM Position */
  123. #define CLIC_CLICINFO_SHD_NUM_Msk (0xFUL << CLIC_CLICINFO_SHD_NUM_Pos) /*!< CLIC CLICINFO: SHD_NUM Mask */
  124. #define CLIC_INTIP_IP_Pos 0U /*!< CLIC INTIP: IP Position */
  125. #define CLIC_INTIP_IP_Msk (0x1UL << CLIC_INTIP_IP_Pos) /*!< CLIC INTIP: IP Mask */
  126. #define CLIC_INTIE_IE_Pos 0U /*!< CLIC INTIE: IE Position */
  127. #define CLIC_INTIE_IE_Msk (0x1UL << CLIC_INTIE_IE_Pos) /*!< CLIC INTIE: IE Mask */
  128. #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
  129. #define CLIC_INTATTR_MODE_Pos 6U /*!< CLIC INTATTA: Mode Position */
  130. #define CLIC_INTATTR_MODE_Msk (0x3U << CLIC_INTATTR_MODE_Pos) /*!< CLIC INTATTA: Mode Mask */
  131. #endif
  132. #define CLIC_INTATTR_TRIG_Pos 1U /*!< CLIC INTATTR: TRIG Position */
  133. #define CLIC_INTATTR_TRIG_Msk (0x3UL << CLIC_INTATTR_TRIG_Pos) /*!< CLIC INTATTR: TRIG Mask */
  134. #define CLIC_INTATTR_SHV_Pos 0U /*!< CLIC INTATTR: SHV Position */
  135. #define CLIC_INTATTR_SHV_Msk (0x1UL << CLIC_INTATTR_SHV_Pos) /*!< CLIC INTATTR: SHV Mask */
  136. #define ECLIC_MAX_NLBITS 8U /*!< Max nlbit of the CLICINTCTLBITS */
  137. #define ECLIC_MODE_MTVEC_Msk 3U /*!< ECLIC Mode mask for MTVT CSR Register */
  138. #define ECLIC_NON_VECTOR_INTERRUPT 0x0 /*!< Non-Vector Interrupt Mode of ECLIC */
  139. #define ECLIC_VECTOR_INTERRUPT 0x1 /*!< Vector Interrupt Mode of ECLIC */
  140. /**\brief ECLIC Trigger Enum for different Trigger Type */
  141. typedef enum ECLIC_TRIGGER {
  142. ECLIC_LEVEL_TRIGGER = 0x0, /*!< Level Triggerred, trig[0] = 0 */
  143. ECLIC_POSTIVE_EDGE_TRIGGER = 0x1, /*!< Postive/Rising Edge Triggered, trig[0] = 1, trig[1] = 0 */
  144. ECLIC_NEGTIVE_EDGE_TRIGGER = 0x3, /*!< Negtive/Falling Edge Triggered, trig[0] = 1, trig[1] = 1 */
  145. ECLIC_MAX_TRIGGER = 0x3 /*!< MAX Supported Trigger Mode */
  146. } ECLIC_TRIGGER_Type;
  147. #ifndef __ECLIC_BASEADDR
  148. /* Base address of ECLIC(__ECLIC_BASEADDR) should be defined in <Device.h> */
  149. #error "__ECLIC_BASEADDR is not defined, please check!"
  150. #endif
  151. #ifndef __ECLIC_INTCTLBITS
  152. /* Define __ECLIC_INTCTLBITS to get via ECLIC->INFO if not defined */
  153. #define __ECLIC_INTCTLBITS (__ECLIC_GetInfoCtlbits())
  154. #endif
  155. /* ECLIC Memory mapping of Device */
  156. #define ECLIC_BASE __ECLIC_BASEADDR /*!< ECLIC Base Address */
  157. #define ECLIC ((CLIC_Type *) ECLIC_BASE) /*!< CLIC configuration struct */
  158. /** @} */ /* end of group NMSIS_Core_ECLIC_Registers */
  159. /* ########################## ECLIC functions #################################### */
  160. /**
  161. * \defgroup NMSIS_Core_IntExc Interrupts and Exceptions
  162. * \brief Functions that manage interrupts and exceptions via the ECLIC.
  163. *
  164. * @{
  165. */
  166. /**
  167. * \brief Definition of IRQn numbers
  168. * \details
  169. * The core interrupt enumeration names for IRQn values are defined in the file <b><Device>.h</b>.
  170. * - Interrupt ID(IRQn) from 0 to 18 are reserved for core internal interrupts.
  171. * - Interrupt ID(IRQn) start from 19 represent device-specific external interrupts.
  172. * - The first device-specific interrupt has the IRQn value 19.
  173. *
  174. * The table below describes the core interrupt names and their availability in various Nuclei Cores.
  175. */
  176. /* The following enum IRQn definition in this file
  177. * is only used for doxygen documentation generation,
  178. * The <Device>.h is the real file to define it by vendor
  179. */
  180. #if defined(__ONLY_FOR_DOXYGEN_DOCUMENT_GENERATION__)
  181. typedef enum IRQn {
  182. /* ========= Nuclei N/NX Core Specific Interrupt Numbers =========== */
  183. /* Core Internal Interrupt IRQn definitions */
  184. Reserved0_IRQn = 0, /*!< Internal reserved */
  185. Reserved1_IRQn = 1, /*!< Internal reserved */
  186. Reserved2_IRQn = 2, /*!< Internal reserved */
  187. SysTimerSW_IRQn = 3, /*!< System Timer SW interrupt */
  188. Reserved3_IRQn = 4, /*!< Internal reserved */
  189. Reserved4_IRQn = 5, /*!< Internal reserved */
  190. Reserved5_IRQn = 6, /*!< Internal reserved */
  191. SysTimer_IRQn = 7, /*!< System Timer Interrupt */
  192. Reserved6_IRQn = 8, /*!< Internal reserved */
  193. Reserved7_IRQn = 9, /*!< Internal reserved */
  194. Reserved8_IRQn = 10, /*!< Internal reserved */
  195. Reserved9_IRQn = 11, /*!< Internal reserved */
  196. Reserved10_IRQn = 12, /*!< Internal reserved */
  197. Reserved11_IRQn = 13, /*!< Internal reserved */
  198. Reserved12_IRQn = 14, /*!< Internal reserved */
  199. Reserved13_IRQn = 15, /*!< Internal reserved */
  200. Reserved14_IRQn = 16, /*!< Internal reserved */
  201. Reserved15_IRQn = 17, /*!< Internal reserved */
  202. Reserved16_IRQn = 18, /*!< Internal reserved */
  203. /* ========= Device Specific Interrupt Numbers =================== */
  204. /* ToDo: add here your device specific external interrupt numbers.
  205. * 19~max(NUM_INTERRUPT, 1023) is reserved number for user.
  206. * Maxmum interrupt supported could get from clicinfo.NUM_INTERRUPT.
  207. * According the interrupt handlers defined in startup_Device.S
  208. * eg.: Interrupt for Timer#1 eclic_tim1_handler -> TIM1_IRQn */
  209. FirstDeviceSpecificInterrupt_IRQn = 19, /*!< First Device Specific Interrupt */
  210. SOC_INT_MAX, /*!< Number of total interrupts */
  211. } IRQn_Type;
  212. #endif /* __ONLY_FOR_DOXYGEN_DOCUMENT_GENERATION__ */
  213. #ifdef NMSIS_ECLIC_VIRTUAL
  214. #ifndef NMSIS_ECLIC_VIRTUAL_HEADER_FILE
  215. #define NMSIS_ECLIC_VIRTUAL_HEADER_FILE "nmsis_eclic_virtual.h"
  216. #endif
  217. #include NMSIS_ECLIC_VIRTUAL_HEADER_FILE
  218. #else
  219. #define ECLIC_SetCfgNlbits __ECLIC_SetCfgNlbits
  220. #define ECLIC_GetCfgNlbits __ECLIC_GetCfgNlbits
  221. #define ECLIC_GetInfoVer __ECLIC_GetInfoVer
  222. #define ECLIC_GetInfoCtlbits __ECLIC_GetInfoCtlbits
  223. #define ECLIC_GetInfoNum __ECLIC_GetInfoNum
  224. #define ECLIC_GetInfoShadowNum __ECLIC_GetInfoShadowNum
  225. #define ECLIC_SetMth __ECLIC_SetMth
  226. #define ECLIC_GetMth __ECLIC_GetMth
  227. #define ECLIC_EnableIRQ __ECLIC_EnableIRQ
  228. #define ECLIC_GetEnableIRQ __ECLIC_GetEnableIRQ
  229. #define ECLIC_DisableIRQ __ECLIC_DisableIRQ
  230. #define ECLIC_SetPendingIRQ __ECLIC_SetPendingIRQ
  231. #define ECLIC_GetPendingIRQ __ECLIC_GetPendingIRQ
  232. #define ECLIC_ClearPendingIRQ __ECLIC_ClearPendingIRQ
  233. #define ECLIC_SetTrigIRQ __ECLIC_SetTrigIRQ
  234. #define ECLIC_GetTrigIRQ __ECLIC_GetTrigIRQ
  235. #define ECLIC_SetShvIRQ __ECLIC_SetShvIRQ
  236. #define ECLIC_GetShvIRQ __ECLIC_GetShvIRQ
  237. #define ECLIC_SetCtrlIRQ __ECLIC_SetCtrlIRQ
  238. #define ECLIC_GetCtrlIRQ __ECLIC_GetCtrlIRQ
  239. #define ECLIC_SetLevelIRQ __ECLIC_SetLevelIRQ
  240. #define ECLIC_GetLevelIRQ __ECLIC_GetLevelIRQ
  241. #define ECLIC_SetPriorityIRQ __ECLIC_SetPriorityIRQ
  242. #define ECLIC_GetPriorityIRQ __ECLIC_GetPriorityIRQ
  243. #if __ECLIC_VER == 2
  244. #define ECLIC_EnableShadow __ECLIC_EnableShadow
  245. #define ECLIC_DisableShadow __ECLIC_DisableShadow
  246. #define ECLIC_SetShadowLevel __ECLIC_SetShadowLevel
  247. #define ECLIC_GetShadowLevel __ECLIC_GetShadowLevel
  248. #define ECLIC_SetShadowLevelReg __ECLIC_SetShadowLevelReg
  249. #define ECLIC_GetShadowLevelReg __ECLIC_GetShadowLevelReg
  250. #endif
  251. /* For TEE */
  252. #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
  253. #define ECLIC_SetModeIRQ __ECLIC_SetModeIRQ
  254. #define ECLIC_SetSth __ECLIC_SetSth
  255. #define ECLIC_GetSth __ECLIC_GetSth
  256. #define ECLIC_SetPendingIRQ_S __ECLIC_SetPendingIRQ_S
  257. #define ECLIC_GetPendingIRQ_S __ECLIC_GetPendingIRQ_S
  258. #define ECLIC_ClearPendingIRQ_S __ECLIC_ClearPendingIRQ_S
  259. #define ECLIC_SetTrigIRQ_S __ECLIC_SetTrigIRQ_S
  260. #define ECLIC_GetTrigIRQ_S __ECLIC_GetTrigIRQ_S
  261. #define ECLIC_SetShvIRQ_S __ECLIC_SetShvIRQ_S
  262. #define ECLIC_GetShvIRQ_S __ECLIC_GetShvIRQ_S
  263. #define ECLIC_SetCtrlIRQ_S __ECLIC_SetCtrlIRQ_S
  264. #define ECLIC_GetCtrlIRQ_S __ECLIC_GetCtrlIRQ_S
  265. #define ECLIC_SetLevelIRQ_S __ECLIC_SetLevelIRQ_S
  266. #define ECLIC_GetLevelIRQ_S __ECLIC_GetLevelIRQ_S
  267. #define ECLIC_SetPriorityIRQ_S __ECLIC_SetPriorityIRQ_S
  268. #define ECLIC_GetPriorityIRQ_S __ECLIC_GetPriorityIRQ_S
  269. #define ECLIC_EnableIRQ_S __ECLIC_EnableIRQ_S
  270. #define ECLIC_GetEnableIRQ_S __ECLIC_GetEnableIRQ_S
  271. #define ECLIC_DisableIRQ_S __ECLIC_DisableIRQ_S
  272. #if __ECLIC_VER == 2
  273. #define ECLIC_EnableShadow_S __ECLIC_EnableShadow_S
  274. #define ECLIC_DisableShadow_S __ECLIC_DisableShadow_S
  275. #define ECLIC_SetShadowLevel_S __ECLIC_SetShadowLevel_S
  276. #define ECLIC_GetShadowLevel_S __ECLIC_GetShadowLevel_S
  277. #define ECLIC_SetShadowLevelReg_S __ECLIC_SetShadowLevelReg_S
  278. #define ECLIC_GetShadowLevelReg_S __ECLIC_GetShadowLevelReg_S
  279. #endif
  280. #endif
  281. #endif /* NMSIS_ECLIC_VIRTUAL */
  282. #ifdef NMSIS_VECTAB_VIRTUAL
  283. #ifndef NMSIS_VECTAB_VIRTUAL_HEADER_FILE
  284. #define NMSIS_VECTAB_VIRTUAL_HEADER_FILE "nmsis_vectab_virtual.h"
  285. #endif
  286. #include NMSIS_VECTAB_VIRTUAL_HEADER_FILE
  287. #else
  288. #define ECLIC_SetVector __ECLIC_SetVector
  289. #define ECLIC_GetVector __ECLIC_GetVector
  290. #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
  291. #define ECLIC_SetVector_S __ECLIC_SetVector_S
  292. #define ECLIC_GetVector_S __ECLIC_GetVector_S
  293. #endif
  294. #endif /* (NMSIS_VECTAB_VIRTUAL) */
  295. /**
  296. * \brief Set nlbits value
  297. * \details
  298. * This function set the nlbits value of CLICCFG register.
  299. * \param [in] nlbits nlbits value
  300. * \remarks
  301. * - nlbits is used to set the width of level in the CLICINTCTL[i].
  302. * \sa
  303. * - \ref ECLIC_GetCfgNlbits
  304. */
  305. __STATIC_FORCEINLINE void __ECLIC_SetCfgNlbits(uint32_t nlbits)
  306. {
  307. uint8_t temp = ECLIC->CFG;
  308. ECLIC->CFG = (temp & ~CLIC_CLICCFG_NLBIT_Msk) | \
  309. ((uint8_t)((nlbits << CLIC_CLICCFG_NLBIT_Pos) & CLIC_CLICCFG_NLBIT_Msk));
  310. }
  311. /**
  312. * \brief Get nlbits value
  313. * \details
  314. * This function get the nlbits value of CLICCFG register.
  315. * \return nlbits value of CLICCFG register
  316. * \remarks
  317. * - nlbits is used to set the width of level in the CLICINTCTL[i].
  318. * \sa
  319. * - \ref ECLIC_SetCfgNlbits
  320. */
  321. __STATIC_FORCEINLINE uint32_t __ECLIC_GetCfgNlbits(void)
  322. {
  323. return ((uint32_t)((ECLIC->CFG & CLIC_CLICCFG_NLBIT_Msk) >> CLIC_CLICCFG_NLBIT_Pos));
  324. }
  325. /**
  326. * \brief Get the ECLIC version number
  327. * \details
  328. * This function gets the hardware version information from CLICINFO register.
  329. * \return hardware version number in CLICINFO register.
  330. * \remarks
  331. * - This function gets harware version information from CLICINFO register.
  332. * - Bit 20:17 for architecture version, bit 16:13 for implementation version.
  333. * \sa
  334. * - \ref ECLIC_GetInfoNum
  335. */
  336. __STATIC_FORCEINLINE uint32_t __ECLIC_GetInfoVer(void)
  337. {
  338. return ((uint32_t)((ECLIC->INFO & CLIC_CLICINFO_VER_Msk) >> CLIC_CLICINFO_VER_Pos));
  339. }
  340. /**
  341. * \brief Get CLICINTCTLBITS
  342. * \details
  343. * This function gets CLICINTCTLBITS from CLICINFO register.
  344. * \return CLICINTCTLBITS from CLICINFO register.
  345. * \remarks
  346. * - In the CLICINTCTL[i] registers, with 2 <= CLICINTCTLBITS <= 8.
  347. * - The implemented bits are kept left-justified in the most-significant bits of each 8-bit
  348. * CLICINTCTL[I] register, with the lower unimplemented bits hardwired to 1.
  349. * \sa
  350. * - \ref ECLIC_GetInfoNum
  351. */
  352. __STATIC_FORCEINLINE uint32_t __ECLIC_GetInfoCtlbits(void)
  353. {
  354. return ((uint32_t)((ECLIC->INFO & CLIC_CLICINFO_CTLBIT_Msk) >> CLIC_CLICINFO_CTLBIT_Pos));
  355. }
  356. /**
  357. * \brief Get number of maximum interrupt inputs supported
  358. * \details
  359. * This function gets number of maximum interrupt inputs supported from CLICINFO register.
  360. * \return number of maximum interrupt inputs supported from CLICINFO register.
  361. * \remarks
  362. * - This function gets number of maximum interrupt inputs supported from CLICINFO register.
  363. * - The num_interrupt field specifies the actual number of maximum interrupt inputs supported in this implementation.
  364. * \sa
  365. * - \ref ECLIC_GetInfoCtlbits
  366. */
  367. __STATIC_FORCEINLINE uint32_t __ECLIC_GetInfoNum(void)
  368. {
  369. return ((uint32_t)((ECLIC->INFO & CLIC_CLICINFO_NUM_Msk) >> CLIC_CLICINFO_NUM_Pos));
  370. }
  371. /**
  372. * \brief Get number of shadow register groups
  373. * \details
  374. * This function gets the number of shadow register groups from the CLICINFO register.
  375. * This includes both the first-come-first-served dedicated interrupt shadow registers
  376. * and the shadow registers designed for different interrupt levels.
  377. * This number represents the total count for M mode; if S Mode is present, the number is the same as M Mode.
  378. * Note that shadow register 0 is fixed for first-come-first-served m/s-mode interrupt and cannot be configured.
  379. * \return number of shadow register groups from the CLICINFO register.
  380. * \remarks
  381. * - This function is only valid for ECLICv2
  382. * - This function gets the number of shadow register groups from the CLICINFO register.
  383. * \sa
  384. * - \ref ECLIC_GetInfoNum
  385. */
  386. __STATIC_FORCEINLINE uint32_t __ECLIC_GetInfoShadowNum(void)
  387. {
  388. return ((uint32_t)((ECLIC->INFO & (CLIC_CLICINFO_SHD_NUM_Msk)) >> CLIC_CLICINFO_SHD_NUM_Pos));
  389. }
  390. /**
  391. * \brief Set Machine Mode Interrupt Level Threshold
  392. * \details
  393. * This function sets machine mode interrupt level threshold.
  394. * This threshold is not effective immediately, if you want to safely
  395. * change it, you need to disable all interrupts first, and then change it,
  396. * and do fence and then enable all interrupts.
  397. * \param [in] mth Interrupt Level Threshold.
  398. * \sa
  399. * - \ref ECLIC_GetMth
  400. */
  401. __STATIC_FORCEINLINE void __ECLIC_SetMth(uint8_t mth)
  402. {
  403. ECLIC->MTH = mth;
  404. }
  405. /**
  406. * \brief Get Machine Mode Interrupt Level Threshold
  407. * \details
  408. * This function gets machine mode interrupt level threshold.
  409. * \return Interrupt Level Threshold.
  410. * \sa
  411. * - \ref ECLIC_SetMth
  412. */
  413. __STATIC_FORCEINLINE uint8_t __ECLIC_GetMth(void)
  414. {
  415. return (ECLIC->MTH);
  416. }
  417. /**
  418. * \brief Enable a specific interrupt
  419. * \details
  420. * This function enables the specific interrupt \em IRQn.
  421. * \param [in] IRQn Interrupt number
  422. * \remarks
  423. * - IRQn must not be negative.
  424. * \sa
  425. * - \ref ECLIC_DisableIRQ
  426. */
  427. __STATIC_FORCEINLINE void __ECLIC_EnableIRQ(IRQn_Type IRQn)
  428. {
  429. ECLIC->CTRL[IRQn].INTIE |= CLIC_INTIE_IE_Msk;
  430. }
  431. /**
  432. * \brief Get a specific interrupt enable status
  433. * \details
  434. * This function returns the interrupt enable status for the specific interrupt \em IRQn.
  435. * \param [in] IRQn Interrupt number
  436. * \returns
  437. * - 0 Interrupt is not enabled
  438. * - 1 Interrupt is pending
  439. * \remarks
  440. * - IRQn must not be negative.
  441. * \sa
  442. * - \ref ECLIC_EnableIRQ
  443. * - \ref ECLIC_DisableIRQ
  444. */
  445. __STATIC_FORCEINLINE uint32_t __ECLIC_GetEnableIRQ(IRQn_Type IRQn)
  446. {
  447. return ((uint32_t) (ECLIC->CTRL[IRQn].INTIE) & CLIC_INTIE_IE_Msk);
  448. }
  449. /**
  450. * \brief Disable a specific interrupt
  451. * \details
  452. * This function disables the specific interrupt \em IRQn.
  453. * \param [in] IRQn Number of the external interrupt to disable
  454. * \remarks
  455. * - IRQn must not be negative.
  456. * \sa
  457. * - \ref ECLIC_EnableIRQ
  458. */
  459. __STATIC_FORCEINLINE void __ECLIC_DisableIRQ(IRQn_Type IRQn)
  460. {
  461. ECLIC->CTRL[IRQn].INTIE &= ~CLIC_INTIE_IE_Msk;
  462. }
  463. /**
  464. * \brief Get the pending specific interrupt
  465. * \details
  466. * This function returns the pending status of the specific interrupt \em IRQn.
  467. * \param [in] IRQn Interrupt number
  468. * \returns
  469. * - 0 Interrupt is not pending
  470. * - 1 Interrupt is pending
  471. * \remarks
  472. * - IRQn must not be negative.
  473. * \sa
  474. * - \ref ECLIC_SetPendingIRQ
  475. * - \ref ECLIC_ClearPendingIRQ
  476. */
  477. __STATIC_FORCEINLINE int32_t __ECLIC_GetPendingIRQ(IRQn_Type IRQn)
  478. {
  479. return ((uint32_t)(ECLIC->CTRL[IRQn].INTIP) & CLIC_INTIP_IP_Msk);
  480. }
  481. /**
  482. * \brief Set a specific interrupt to pending
  483. * \details
  484. * This function sets the pending bit for the specific interrupt \em IRQn.
  485. * \param [in] IRQn Interrupt number
  486. * \remarks
  487. * - IRQn must not be negative.
  488. * \sa
  489. * - \ref ECLIC_GetPendingIRQ
  490. * - \ref ECLIC_ClearPendingIRQ
  491. */
  492. __STATIC_FORCEINLINE void __ECLIC_SetPendingIRQ(IRQn_Type IRQn)
  493. {
  494. ECLIC->CTRL[IRQn].INTIP |= CLIC_INTIP_IP_Msk;
  495. }
  496. /**
  497. * \brief Clear a specific interrupt from pending
  498. * \details
  499. * This function removes the pending state of the specific interrupt \em IRQn.
  500. * \em IRQn cannot be a negative number.
  501. * \param [in] IRQn Interrupt number
  502. * \remarks
  503. * - IRQn must not be negative.
  504. * \sa
  505. * - \ref ECLIC_SetPendingIRQ
  506. * - \ref ECLIC_GetPendingIRQ
  507. */
  508. __STATIC_FORCEINLINE void __ECLIC_ClearPendingIRQ(IRQn_Type IRQn)
  509. {
  510. ECLIC->CTRL[IRQn].INTIP &= ~CLIC_INTIP_IP_Msk;
  511. }
  512. /**
  513. * \brief Set trigger mode and polarity for a specific interrupt
  514. * \details
  515. * This function set trigger mode and polarity of the specific interrupt \em IRQn.
  516. * \param [in] IRQn Interrupt number
  517. * \param [in] trig
  518. * - 00 level trigger, \ref ECLIC_LEVEL_TRIGGER
  519. * - 01 positive edge trigger, \ref ECLIC_POSTIVE_EDGE_TRIGGER
  520. * - 02 level trigger, \ref ECLIC_LEVEL_TRIGGER
  521. * - 03 negative edge trigger, \ref ECLIC_NEGTIVE_EDGE_TRIGGER
  522. * \remarks
  523. * - IRQn must not be negative.
  524. *
  525. * \sa
  526. * - \ref ECLIC_GetTrigIRQ
  527. */
  528. __STATIC_FORCEINLINE void __ECLIC_SetTrigIRQ(IRQn_Type IRQn, uint32_t trig)
  529. {
  530. uint8_t temp = ECLIC->CTRL[IRQn].INTATTR;
  531. ECLIC->CTRL[IRQn].INTATTR = (temp & ~CLIC_INTATTR_TRIG_Msk) | \
  532. ((uint8_t)(trig << CLIC_INTATTR_TRIG_Pos));
  533. }
  534. /**
  535. * \brief Get trigger mode and polarity for a specific interrupt
  536. * \details
  537. * This function get trigger mode and polarity of the specific interrupt \em IRQn.
  538. * \param [in] IRQn Interrupt number
  539. * \return
  540. * - 00 level trigger, \ref ECLIC_LEVEL_TRIGGER
  541. * - 01 positive edge trigger, \ref ECLIC_POSTIVE_EDGE_TRIGGER
  542. * - 02 level trigger, \ref ECLIC_LEVEL_TRIGGER
  543. * - 03 negative edge trigger, \ref ECLIC_NEGTIVE_EDGE_TRIGGER
  544. * \remarks
  545. * - IRQn must not be negative.
  546. * \sa
  547. * - \ref ECLIC_SetTrigIRQ
  548. */
  549. __STATIC_FORCEINLINE uint32_t __ECLIC_GetTrigIRQ(IRQn_Type IRQn)
  550. {
  551. return ((uint32_t)(((ECLIC->CTRL[IRQn].INTATTR) & CLIC_INTATTR_TRIG_Msk) >> CLIC_INTATTR_TRIG_Pos));
  552. }
  553. /**
  554. * \brief Set interrupt working mode for a specific interrupt
  555. * \details
  556. * This function set selective hardware vector or non-vector working mode of the specific interrupt \em IRQn.
  557. * \param [in] IRQn Interrupt number
  558. * \param [in] shv
  559. * - 0 non-vector mode, \ref ECLIC_NON_VECTOR_INTERRUPT
  560. * - 1 vector mode, \ref ECLIC_VECTOR_INTERRUPT
  561. * \remarks
  562. * - IRQn must not be negative.
  563. * \sa
  564. * - \ref ECLIC_GetShvIRQ
  565. */
  566. __STATIC_FORCEINLINE void __ECLIC_SetShvIRQ(IRQn_Type IRQn, uint32_t shv)
  567. {
  568. uint8_t temp = ECLIC->CTRL[IRQn].INTATTR;
  569. ECLIC->CTRL[IRQn].INTATTR = (temp & ~CLIC_INTATTR_SHV_Msk) | \
  570. ((uint8_t)(shv << CLIC_INTATTR_SHV_Pos));
  571. }
  572. /**
  573. * \brief Get interrupt working mode for a specific interrupt
  574. * \details
  575. * This function get selective hardware vector or non-vector working mode of the specific interrupt \em IRQn.
  576. * \param [in] IRQn Interrupt number
  577. * \return shv
  578. * - 0 non-vector mode, \ref ECLIC_NON_VECTOR_INTERRUPT
  579. * - 1 vector mode, \ref ECLIC_VECTOR_INTERRUPT
  580. * \remarks
  581. * - IRQn must not be negative.
  582. * \sa
  583. * - \ref ECLIC_SetShvIRQ
  584. */
  585. __STATIC_FORCEINLINE uint32_t __ECLIC_GetShvIRQ(IRQn_Type IRQn)
  586. {
  587. return ((uint32_t)(((ECLIC->CTRL[IRQn].INTATTR) & CLIC_INTATTR_SHV_Msk) >> CLIC_INTATTR_SHV_Pos));
  588. }
  589. /**
  590. * \brief Modify ECLIC Interrupt Input Control Register for a specific interrupt
  591. * \details
  592. * This function modify ECLIC Interrupt Input Control(CLICINTCTL[i]) register of the specific interrupt \em IRQn.
  593. * \param [in] IRQn Interrupt number
  594. * \param [in] intctrl Set value for CLICINTCTL[i] register
  595. * \remarks
  596. * - IRQn must not be negative.
  597. * \sa
  598. * - \ref ECLIC_GetCtrlIRQ
  599. */
  600. __STATIC_FORCEINLINE void __ECLIC_SetCtrlIRQ(IRQn_Type IRQn, uint8_t intctrl)
  601. {
  602. ECLIC->CTRL[IRQn].INTCTRL = intctrl;
  603. }
  604. /**
  605. * \brief Get ECLIC Interrupt Input Control Register value for a specific interrupt
  606. * \details
  607. * This function modify ECLIC Interrupt Input Control register of the specific interrupt \em IRQn.
  608. * \param [in] IRQn Interrupt number
  609. * \return value of ECLIC Interrupt Input Control register
  610. * \remarks
  611. * - IRQn must not be negative.
  612. * \sa
  613. * - \ref ECLIC_SetCtrlIRQ
  614. */
  615. __STATIC_FORCEINLINE uint8_t __ECLIC_GetCtrlIRQ(IRQn_Type IRQn)
  616. {
  617. return (ECLIC->CTRL[IRQn].INTCTRL);
  618. }
  619. /**
  620. * \brief Set ECLIC Interrupt level of a specific interrupt
  621. * \details
  622. * This function set interrupt level of the specific interrupt \em IRQn.
  623. * \param [in] IRQn Interrupt number
  624. * \param [in] lvl_abs Interrupt level
  625. * \remarks
  626. * - IRQn must not be negative.
  627. * - If lvl_abs to be set is larger than the max level allowed, it will be force to be max level.
  628. * - When you set level value you need use clciinfo.nlbits to get the width of level.
  629. * Then we could know the maximum of level. CLICINTCTLBITS is how many total bits are
  630. * present in the CLICINTCTL register.
  631. * \sa
  632. * - \ref ECLIC_GetLevelIRQ
  633. */
  634. __STATIC_INLINE void __ECLIC_SetLevelIRQ(IRQn_Type IRQn, uint8_t lvl_abs)
  635. {
  636. uint8_t nlbits = __ECLIC_GetCfgNlbits();
  637. uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
  638. if (nlbits == 0) {
  639. return;
  640. }
  641. if (nlbits > intctlbits) {
  642. nlbits = intctlbits;
  643. }
  644. uint8_t maxlvl = ((1UL << nlbits) - 1);
  645. if (lvl_abs > maxlvl) {
  646. lvl_abs = maxlvl;
  647. }
  648. uint8_t lvl = lvl_abs << (ECLIC_MAX_NLBITS - nlbits);
  649. uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ(IRQn);
  650. cur_ctrl = cur_ctrl << nlbits;
  651. cur_ctrl = cur_ctrl >> nlbits;
  652. __ECLIC_SetCtrlIRQ(IRQn, (cur_ctrl | lvl));
  653. }
  654. /**
  655. * \brief Get ECLIC Interrupt level of a specific interrupt
  656. * \details
  657. * This function get interrupt level of the specific interrupt \em IRQn.
  658. * \param [in] IRQn Interrupt number
  659. * \return Interrupt level
  660. * \remarks
  661. * - IRQn must not be negative.
  662. * \sa
  663. * - \ref ECLIC_SetLevelIRQ
  664. */
  665. __STATIC_INLINE uint8_t __ECLIC_GetLevelIRQ(IRQn_Type IRQn)
  666. {
  667. uint8_t nlbits = __ECLIC_GetCfgNlbits();
  668. uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
  669. if (nlbits == 0) {
  670. return 0;
  671. }
  672. if (nlbits > intctlbits) {
  673. nlbits = intctlbits;
  674. }
  675. uint8_t intctrl = __ECLIC_GetCtrlIRQ(IRQn);
  676. uint8_t lvl_abs = intctrl >> (ECLIC_MAX_NLBITS - nlbits);
  677. return lvl_abs;
  678. }
  679. /**
  680. * \brief Get ECLIC Interrupt priority of a specific interrupt
  681. * \details
  682. * This function get interrupt priority of the specific interrupt \em IRQn.
  683. * \param [in] IRQn Interrupt number
  684. * \param [in] pri Interrupt priority
  685. * \remarks
  686. * - IRQn must not be negative.
  687. * - If pri to be set is larger than the max priority allowed, it will be force to be max priority.
  688. * - Priority width is CLICINTCTLBITS minus clciinfo.nlbits if clciinfo.nlbits
  689. * is less than CLICINTCTLBITS. Otherwise priority width is 0.
  690. * \sa
  691. * - \ref ECLIC_GetPriorityIRQ
  692. */
  693. __STATIC_INLINE void __ECLIC_SetPriorityIRQ(IRQn_Type IRQn, uint8_t pri)
  694. {
  695. uint8_t nlbits = __ECLIC_GetCfgNlbits();
  696. uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
  697. if (nlbits < intctlbits) {
  698. uint8_t maxpri = ((1UL << (intctlbits - nlbits)) - 1);
  699. if (pri > maxpri) {
  700. pri = maxpri;
  701. }
  702. pri = pri << (ECLIC_MAX_NLBITS - intctlbits);
  703. uint8_t mask = ((uint8_t)(-1)) >> intctlbits;
  704. pri = pri | mask;
  705. uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ(IRQn);
  706. cur_ctrl = cur_ctrl >> (ECLIC_MAX_NLBITS - nlbits);
  707. cur_ctrl = cur_ctrl << (ECLIC_MAX_NLBITS - nlbits);
  708. __ECLIC_SetCtrlIRQ(IRQn, (cur_ctrl | pri));
  709. }
  710. }
  711. /**
  712. * \brief Get ECLIC Interrupt priority of a specific interrupt
  713. * \details
  714. * This function get interrupt priority of the specific interrupt \em IRQn.
  715. * \param [in] IRQn Interrupt number
  716. * \return Interrupt priority
  717. * \remarks
  718. * - IRQn must not be negative.
  719. * \sa
  720. * - \ref ECLIC_SetPriorityIRQ
  721. */
  722. __STATIC_INLINE uint8_t __ECLIC_GetPriorityIRQ(IRQn_Type IRQn)
  723. {
  724. uint8_t nlbits = __ECLIC_GetCfgNlbits();
  725. uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
  726. if (nlbits < intctlbits) {
  727. uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ(IRQn);
  728. uint8_t pri = cur_ctrl << nlbits;
  729. pri = pri >> nlbits;
  730. pri = pri >> (ECLIC_MAX_NLBITS - intctlbits);
  731. return pri;
  732. } else {
  733. return 0;
  734. }
  735. }
  736. #if __ECLIC_VER == 2
  737. /**
  738. * \brief Enable ECLIC Shadow Register Function (Machine Mode)
  739. * \details
  740. * This function enables the shadow register function for ECLIC in Machine Mode.
  741. * It sets the MECLIC_CTL_SHADOW_EN bit in the CSR_MECLIC_CTL CSR.
  742. * This function is only valid for ECLIC version 2 and above.
  743. * \remarks
  744. * - API only available for ECLIC v2
  745. * \sa
  746. * - \ref __ECLIC_DisableShadow
  747. */
  748. __STATIC_FORCEINLINE void __ECLIC_EnableShadow(void)
  749. {
  750. __RV_CSR_SET(CSR_MECLIC_CTL, MECLIC_CTL_SHADOW_EN);
  751. }
  752. /**
  753. * \brief Disable ECLIC Shadow Register Function (Machine Mode)
  754. * \details
  755. * This function disables the shadow register function for ECLIC in Machine Mode.
  756. * It clears the MECLIC_CTL_SHADOW_EN bit in the CSR_MECLIC_CTL CSR.
  757. * This function is only valid for ECLIC version 2 and above.
  758. * \remarks
  759. * - API only available for ECLIC v2
  760. * \sa
  761. * - \ref __ECLIC_EnableShadow
  762. */
  763. __STATIC_FORCEINLINE void __ECLIC_DisableShadow(void)
  764. {
  765. __RV_CSR_CLEAR(CSR_MECLIC_CTL, MECLIC_CTL_SHADOW_EN);
  766. }
  767. /**
  768. * \brief Set Shadow Register Interrupt Level for a specific m-mode shadow register
  769. * \details
  770. * This function sets the interrupt level for a specific m-mode shadow register \em idx + 1.
  771. * It configures CSR_MSHADGPRLVL0 and CSR_MSHADGPRLVL1 registers.
  772. * \param [in] idx Shadow register index (0-7), corresponding to shadow registers 1-8
  773. * (Note: shadow register 0 is fixed for first-come-first-served m-mode
  774. * interrupt and cannot be configured)
  775. * \param [in] level Interrupt level to set for the shadow register
  776. * \remarks
  777. * - API only available for ECLIC v2
  778. * - idx = 0 means set SHAD1_CFG, which configures the shadow register 1
  779. * - For RV64, all 8 shadow registers are configured in CSR_MSHADGPRLVL0
  780. * - For RV32, shadow registers 1-4 are in lower 32 bits of CSR_MSHADGPRLVL0,
  781. * and shadow registers 5-8 are in CSR_MSHADGPRLVL1
  782. * \sa
  783. * - \ref ECLIC_GetShadowLevel
  784. */
  785. __STATIC_INLINE void __ECLIC_SetShadowLevel(unsigned long idx, uint8_t level)
  786. {
  787. /* Check if idx is valid (0-7) */
  788. if (idx > 7) {
  789. return;
  790. }
  791. uint8_t nlbits = (uint8_t)__ECLIC_GetCfgNlbits();
  792. /* Limit the level value to the available number of bits */
  793. uint8_t max_level = (1U << nlbits) - 1;
  794. if (level > max_level) {
  795. level = max_level;
  796. }
  797. /* Position the level value in the upper nlbits of the 8-bit field and set the low (8-nlbits) bits to 1 */
  798. uint8_t level_shifted = (uint8_t)((level << (8 - nlbits)) | ((1U << (8 - nlbits)) - 1));
  799. #if __RISCV_XLEN == 64
  800. /* For RV64, all 8 shadow registers are in CSR_MSHADGPRLVL0 */
  801. /* Calculate the bit position for the 8-bit field of the specified index */
  802. uint32_t bit_pos = idx << 3; /* idx * 8 using bit shift */
  803. /* Create mask to clear the 8-bit field for the specified index */
  804. uint64_t mask = (uint64_t)0xFFUL << bit_pos;
  805. /* Read, modify, and write the CSR register */
  806. uint64_t current_val = __RV_CSR_READ(CSR_MSHADGPRLVL0);
  807. current_val = (current_val & ~mask) | (((uint64_t)level_shifted) << bit_pos);
  808. __RV_CSR_WRITE(CSR_MSHADGPRLVL0, current_val);
  809. #else
  810. /* For RV32, calculate bit position and select appropriate register */
  811. if (idx < 4) {
  812. /* Shadow registers 1-4 are in CSR_MSHADGPRLVL0 */
  813. uint32_t bit_pos = idx << 3; /* idx * 8 using bit shift */
  814. uint32_t mask = 0xFFUL << bit_pos;
  815. uint32_t current_val = __RV_CSR_READ(CSR_MSHADGPRLVL0);
  816. current_val = (current_val & ~mask) | (((uint32_t)level_shifted) << bit_pos);
  817. __RV_CSR_WRITE(CSR_MSHADGPRLVL0, current_val);
  818. } else {
  819. /* Shadow registers 5-8 are in CSR_MSHADGPRLVL1 */
  820. uint32_t bit_pos = (idx - 4) << 3; /* (idx - 4) * 8 using bit shift */
  821. uint32_t mask = 0xFFUL << bit_pos;
  822. uint32_t current_val = __RV_CSR_READ(CSR_MSHADGPRLVL1);
  823. current_val = (current_val & ~mask) | (((uint32_t)level_shifted) << bit_pos);
  824. __RV_CSR_WRITE(CSR_MSHADGPRLVL1, current_val);
  825. }
  826. #endif
  827. }
  828. /**
  829. * \brief Get Shadow Register Interrupt Level for a specific m-mode shadow register
  830. * \details
  831. * This function gets the interrupt level for a specific m-mode shadow register \em idx + 1.
  832. * It reads CSR_MSHADGPRLVL0 and CSR_MSHADGPRLVL1 registers.
  833. * \param [in] idx Shadow register index (0-7), corresponding to shadow registers 1-8
  834. * (Note: shadow register 0 is fixed for first-come-first-served m-mode
  835. * interrupt and cannot be configured)
  836. * \return Interrupt level of the shadow register
  837. * \remarks
  838. * - API only available for ECLIC v2
  839. * - idx = 0 means set SHAD1_CFG, which configures the shadow register 1
  840. * - For RV64, all 8 shadow registers are configured in CSR_MSHADGPRLVL0
  841. * - For RV32, shadow registers 1-4 are in lower 32 bits of CSR_MSHADGPRLVL0,
  842. * and shadow registers 5-8 are in CSR_MSHADGPRLVL1
  843. * \sa
  844. * - \ref ECLIC_SetShadowLevel
  845. */
  846. __STATIC_INLINE uint8_t __ECLIC_GetShadowLevel(unsigned long idx)
  847. {
  848. /* Check if idx is valid (0-7) */
  849. if (idx > 7) {
  850. return 0;
  851. }
  852. uint8_t nlbits = (uint8_t)__ECLIC_GetCfgNlbits();
  853. #if __RISCV_XLEN == 64
  854. /* For RV64, all 8 shadow registers are in CSR_MSHADGPRLVL0 */
  855. /* Calculate the bit position for the 8-bit field of the specified index */
  856. uint32_t bit_pos = idx << 3; /* idx * 8 using bit shift */
  857. /* Read the CSR register and extract the 8-bit field */
  858. uint64_t current_val = __RV_CSR_READ(CSR_MSHADGPRLVL0);
  859. uint8_t extracted_val = (uint8_t)((current_val >> bit_pos) & 0xFF);
  860. /* Extract the level from the upper nlbits of the 8-bit field */
  861. uint8_t level = (extracted_val >> (8 - nlbits));
  862. return level;
  863. #else
  864. /* For RV32, calculate bit position and select appropriate register */
  865. if (idx < 4) {
  866. /* Shadow registers 1-4 are in CSR_MSHADGPRLVL0 */
  867. uint32_t bit_pos = idx << 3; /* idx * 8 using bit shift */
  868. /* Read the CSR register and extract the 8-bit field */
  869. uint32_t current_val = __RV_CSR_READ(CSR_MSHADGPRLVL0);
  870. uint8_t extracted_val = (uint8_t)((current_val >> bit_pos) & 0xFF);
  871. /* Extract the level from the upper nlbits of the 8-bit field */
  872. uint8_t level = (extracted_val >> (8 - nlbits));
  873. return level;
  874. } else {
  875. /* Shadow registers 5-8 are in CSR_MSHADGPRLVL1 */
  876. uint32_t bit_pos = (idx - 4) << 3; /* (idx - 4) * 8 using bit shift */
  877. /* Read the CSR register and extract the 8-bit field */
  878. uint32_t current_val = __RV_CSR_READ(CSR_MSHADGPRLVL1);
  879. uint8_t extracted_val = (uint8_t)((current_val >> bit_pos) & 0xFF);
  880. /* Extract the level from the upper nlbits of the 8-bit field */
  881. uint8_t level = (extracted_val >> (8 - nlbits));
  882. return level;
  883. }
  884. #endif
  885. }
  886. /**
  887. * \brief Set Shadow Register Level Register for m-mode
  888. * \details
  889. * This function sets the entire shadow register level register for m-mode.
  890. * It writes directly to CSR_MSHADGPRLVL0 register (and CSR_MSHADGPRLVL1 for RV32).
  891. * \param [in] value 64-bit value to set for the shadow register level register
  892. * \remarks
  893. * - API only available for ECLIC v2
  894. * - For RV64, all 8 shadow registers are configured in CSR_MSHADGPRLVL0
  895. * - For RV32, shadow registers 1-4 are in lower 32 bits of CSR_MSHADGPRLVL0,
  896. * and shadow registers 5-8 are in CSR_MSHADGPRLVL1
  897. * - Note: shadow register 0 is fixed for first-come-first-served m-mode interrupt and cannot be configured
  898. * \sa
  899. * - \ref ECLIC_GetShadowLevelReg
  900. */
  901. __STATIC_INLINE void __ECLIC_SetShadowLevelReg(uint64_t value)
  902. {
  903. #if __RISCV_XLEN == 64
  904. __RV_CSR_WRITE(CSR_MSHADGPRLVL0, value);
  905. #else
  906. __RV_CSR_WRITE(CSR_MSHADGPRLVL0, (uint32_t)value);
  907. __RV_CSR_WRITE(CSR_MSHADGPRLVL1, (uint32_t)(value >> 32));
  908. #endif
  909. }
  910. /**
  911. * \brief Get Shadow Register Level Register for m-mode
  912. * \details
  913. * This function gets the entire shadow register level register for m-mode.
  914. * It reads from CSR_MSHADGPRLVL0 register (and CSR_MSHADGPRLVL1 for RV32) and combines them.
  915. * \return 64-bit value of the shadow register level register
  916. * \remarks
  917. * - API only available for ECLIC v2
  918. * - For RV64, all 8 shadow registers are configured in CSR_MSHADGPRLVL0
  919. * - For RV32, shadow registers 1-4 are in lower 32 bits of CSR_MSHADGPRLVL0,
  920. * and shadow registers 5-8 are in CSR_MSHADGPRLVL1
  921. * - Note: shadow register 0 is fixed for first-come-first-served m-mode interrupt and cannot be configured
  922. * \sa
  923. * - \ref ECLIC_SetShadowLevelReg
  924. */
  925. __STATIC_INLINE uint64_t __ECLIC_GetShadowLevelReg(void)
  926. {
  927. #if __RISCV_XLEN == 64
  928. return __RV_CSR_READ(CSR_MSHADGPRLVL0);
  929. #else
  930. uint64_t value = __RV_CSR_READ(CSR_MSHADGPRLVL1);
  931. value <<= 32;
  932. value |= __RV_CSR_READ(CSR_MSHADGPRLVL0);
  933. return value;
  934. #endif
  935. }
  936. #endif
  937. /**
  938. * \brief Set Interrupt Vector of a specific interrupt
  939. * \details
  940. * This function set interrupt handler address of the specific interrupt \em IRQn.
  941. * \param [in] IRQn Interrupt number
  942. * \param [in] vector Interrupt handler address
  943. * \remarks
  944. * - IRQn must not be negative.
  945. * - You can set the \ref CSR_CSR_MTVT to set interrupt vector table entry address.
  946. * - If your vector table is placed in readonly section, the vector for IRQn will not be modified.
  947. * For this case, you need to use the correct irq handler name defined in your vector table as
  948. * your irq handler function name.
  949. * - This function will only work correctly when the vector table is placed in an read-write enabled section.
  950. * \sa
  951. * - \ref ECLIC_GetVector
  952. */
  953. __STATIC_INLINE void __ECLIC_SetVector(IRQn_Type IRQn, rv_csr_t vector)
  954. {
  955. unsigned long vec_base;
  956. vec_base = ((unsigned long)__RV_CSR_READ(CSR_MTVT));
  957. vec_base += ((unsigned long)IRQn) * sizeof(unsigned long);
  958. (* (unsigned long *) vec_base) = vector;
  959. #if (defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1))
  960. #if (defined(__CCM_PRESENT) && (__CCM_PRESENT == 1))
  961. MFlushDCacheLine((unsigned long)vec_base);
  962. #endif
  963. #endif
  964. #if (defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1))
  965. #if (defined(__CCM_PRESENT) && (__CCM_PRESENT == 1))
  966. MInvalICacheLine((unsigned long)vec_base);
  967. #else
  968. __FENCE_I();
  969. #endif
  970. #endif
  971. }
  972. /**
  973. * \brief Get Interrupt Vector of a specific interrupt
  974. * \details
  975. * This function get interrupt handler address of the specific interrupt \em IRQn.
  976. * \param [in] IRQn Interrupt number
  977. * \return Interrupt handler address
  978. * \remarks
  979. * - IRQn must not be negative.
  980. * - You can read \ref CSR_CSR_MTVT to get interrupt vector table entry address.
  981. * \sa
  982. * - \ref ECLIC_SetVector
  983. */
  984. __STATIC_FORCEINLINE rv_csr_t __ECLIC_GetVector(IRQn_Type IRQn)
  985. {
  986. #if __RISCV_XLEN == 32
  987. return (*(uint32_t *)(__RV_CSR_READ(CSR_MTVT) + IRQn * 4));
  988. #elif __RISCV_XLEN == 64
  989. return (*(uint64_t *)(__RV_CSR_READ(CSR_MTVT) + IRQn * 8));
  990. #else // TODO Need cover for XLEN=128 case in future
  991. return (*(uint64_t *)(__RV_CSR_READ(CSR_MTVT) + IRQn * 8));
  992. #endif
  993. }
  994. #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
  995. /**
  996. * \brief Set privilege mode of a specific interrupt
  997. * \details
  998. * This function set in which privilege mode the interrupts \em IRQn should be taken.
  999. * \param [in] IRQn Interrupt number
  1000. * \param [in] mode Privilege mode
  1001. * \remarks
  1002. * - IRQn must not be negative.
  1003. * - mode must be 1(Supervisor Mode) or 3(Machine Mode), other values are ignored.
  1004. * - M-mode can R/W this field, but S-mode can only read.And ECLIC with TEE does not
  1005. * reply on CSR mideleg to delegate interrupts.
  1006. * - Mode of S-mode ECLIC region's clicintattr can be omitted to set, which is mirror to M-mode ECLIC region's.
  1007. * Only the low 6 bits of clicintattr [i] can be written via the S-mode memory region.
  1008. */
  1009. __STATIC_FORCEINLINE void __ECLIC_SetModeIRQ(IRQn_Type IRQn, uint32_t mode)
  1010. {
  1011. /*
  1012. * only 1 or 3 can be assigned to mode in one step.the default value of mode is 3,
  1013. * which can't be clear to 0 firstly, then OR it to 1
  1014. */
  1015. ECLIC->CTRL[IRQn].INTATTR = (uint8_t)(mode << CLIC_INTATTR_MODE_Pos) + \
  1016. (ECLIC->SCTRL[IRQn].INTATTR & (~CLIC_INTATTR_MODE_Msk));
  1017. }
  1018. /**
  1019. * \brief Set supervisor-mode Interrupt Level Threshold in supervisor mode
  1020. * \details
  1021. * This function sets supervisor-mode interrupt level threshold.
  1022. * \param [in] sth Interrupt Level Threshold.
  1023. * \remarks
  1024. * - S-mode ECLIC region sintthresh'sth is a mirror to M-mode ECLIC region's mintthresh.sth,
  1025. * and will be updated synchronously, here operate on mintthresh.sth.
  1026. * - Similiar to \ref ECLIC_SetMth, also recommended to disable interrupts before
  1027. * setting interrupt level threshold.
  1028. * \sa
  1029. * - \ref ECLIC_GetSth
  1030. */
  1031. __STATIC_FORCEINLINE void __ECLIC_SetSth(uint8_t sth)
  1032. {
  1033. ECLIC->STH = sth;
  1034. }
  1035. /**
  1036. * \brief Get supervisor-mode Interrupt Level Threshold in supervisor mode
  1037. * \details
  1038. * This function gets supervisor mode interrupt level threshold.
  1039. * \return Interrupt Level Threshold.
  1040. * \remarks
  1041. * - S-mode ECLIC region sintthresh'sth is a mirror to M-mode ECLIC region's mintthresh.sth,
  1042. * and will be updated synchronously, here operate on mintthresh.sth.
  1043. * \sa
  1044. * - \ref ECLIC_SetSth
  1045. */
  1046. __STATIC_FORCEINLINE uint8_t __ECLIC_GetSth(void)
  1047. {
  1048. return (ECLIC->STH);
  1049. }
  1050. /**
  1051. * \brief Set a specific interrupt to pending in supervisor mode
  1052. * \details
  1053. * This function sets the pending bit for the specific interrupt \em IRQn in supervisor mode.
  1054. * \param [in] IRQn Interrupt number
  1055. * \remarks
  1056. * - IRQn must not be negative.
  1057. * \sa
  1058. * - \ref ECLIC_GetPendingIRQ_S
  1059. * - \ref ECLIC_ClearPendingIRQ_S
  1060. */
  1061. __STATIC_FORCEINLINE void __ECLIC_SetPendingIRQ_S(IRQn_Type IRQn)
  1062. {
  1063. ECLIC->SCTRL[IRQn].INTIP |= CLIC_INTIP_IP_Msk;
  1064. }
  1065. /**
  1066. * \brief Get the pending specific interrupt in supervisor mode
  1067. * \details
  1068. * This function returns the pending status of the specific interrupt \em IRQn in supervisor mode.
  1069. * \param [in] IRQn Interrupt number
  1070. * \returns
  1071. * - 0 Interrupt is not pending
  1072. * - 1 Interrupt is pending
  1073. * \remarks
  1074. * - IRQn must not be negative.
  1075. * \sa
  1076. * - \ref ECLIC_SetPendingIRQ_S
  1077. * - \ref ECLIC_ClearPendingIRQ_S
  1078. */
  1079. __STATIC_FORCEINLINE int32_t __ECLIC_GetPendingIRQ_S(IRQn_Type IRQn)
  1080. {
  1081. return ((uint32_t)(ECLIC->SCTRL[IRQn].INTIP) & CLIC_INTIP_IP_Msk);
  1082. }
  1083. /**
  1084. * \brief Clear a specific interrupt from pending in supervisor mode
  1085. * \details
  1086. * This function removes the pending state of the specific interrupt \em IRQn in supervisor mode.
  1087. * \em IRQn cannot be a negative number.
  1088. * \param [in] IRQn Interrupt number
  1089. * \remarks
  1090. * - IRQn must not be negative.
  1091. * \sa
  1092. * - \ref ECLIC_SetPendingIRQ_S
  1093. * - \ref ECLIC_GetPendingIRQ_S
  1094. */
  1095. __STATIC_FORCEINLINE void __ECLIC_ClearPendingIRQ_S(IRQn_Type IRQn)
  1096. {
  1097. ECLIC->SCTRL[IRQn].INTIP &= ~CLIC_INTIP_IP_Msk;
  1098. }
  1099. /**
  1100. * \brief Set trigger mode and polarity for a specific interrupt in supervisor mode
  1101. * \details
  1102. * This function set trigger mode and polarity of the specific interrupt \em IRQn.
  1103. * \param [in] IRQn Interrupt number
  1104. * \param [in] trig
  1105. * - 00 level trigger, \ref ECLIC_LEVEL_TRIGGER
  1106. * - 01 positive edge trigger, \ref ECLIC_POSTIVE_EDGE_TRIGGER
  1107. * - 02 level trigger, \ref ECLIC_LEVEL_TRIGGER
  1108. * - 03 negative edge trigger, \ref ECLIC_NEGTIVE_EDGE_TRIGGER
  1109. * \remarks
  1110. * - IRQn must not be negative.
  1111. *
  1112. * \sa
  1113. * - \ref ECLIC_GetTrigIRQ_S
  1114. */
  1115. __STATIC_FORCEINLINE void __ECLIC_SetTrigIRQ_S(IRQn_Type IRQn, uint32_t trig)
  1116. {
  1117. uint8_t temp = ECLIC->SCTRL[IRQn].INTATTR;
  1118. ECLIC->SCTRL[IRQn].INTATTR = (temp & ~CLIC_INTATTR_TRIG_Msk) | \
  1119. ((uint8_t)(trig << CLIC_INTATTR_TRIG_Pos));
  1120. }
  1121. /**
  1122. * \brief Get trigger mode and polarity for a specific interrupt in supervisor mode
  1123. * \details
  1124. * This function get trigger mode and polarity of the specific interrupt \em IRQn.
  1125. * \param [in] IRQn Interrupt number
  1126. * \return
  1127. * - 00 level trigger, \ref ECLIC_LEVEL_TRIGGER
  1128. * - 01 positive edge trigger, \ref ECLIC_POSTIVE_EDGE_TRIGGER
  1129. * - 02 level trigger, \ref ECLIC_LEVEL_TRIGGER
  1130. * - 03 negative edge trigger, \ref ECLIC_NEGTIVE_EDGE_TRIGGER
  1131. * \remarks
  1132. * - IRQn must not be negative.
  1133. * \sa
  1134. * - \ref ECLIC_SetTrigIRQ_S
  1135. */
  1136. __STATIC_FORCEINLINE uint8_t __ECLIC_GetTrigIRQ_S(IRQn_Type IRQn)
  1137. {
  1138. return ((uint8_t)(((ECLIC->SCTRL[IRQn].INTATTR) & CLIC_INTATTR_TRIG_Msk) >> CLIC_INTATTR_TRIG_Pos));
  1139. }
  1140. /**
  1141. * \brief Set interrupt working mode for a specific interrupt in supervisor mode
  1142. * \details
  1143. * This function set selective hardware vector or non-vector working mode of the specific interrupt \em IRQn.
  1144. * \param [in] IRQn Interrupt number
  1145. * \param [in] shv
  1146. * - 0 non-vector mode, \ref ECLIC_NON_VECTOR_INTERRUPT
  1147. * - 1 vector mode, \ref ECLIC_VECTOR_INTERRUPT
  1148. * \remarks
  1149. * - IRQn must not be negative.
  1150. * \sa
  1151. * - \ref ECLIC_GetShvIRQ_S
  1152. */
  1153. __STATIC_FORCEINLINE void __ECLIC_SetShvIRQ_S(IRQn_Type IRQn, uint32_t shv)
  1154. {
  1155. uint8_t temp = ECLIC->SCTRL[IRQn].INTATTR;
  1156. ECLIC->SCTRL[IRQn].INTATTR = (temp & ~CLIC_INTATTR_SHV_Msk) | \
  1157. ((uint8_t)(shv << CLIC_INTATTR_SHV_Pos));
  1158. }
  1159. /**
  1160. * \brief Get interrupt working mode for a specific interrupt in supervisor mode
  1161. * \details
  1162. * This function get selective hardware vector or non-vector working mode of the specific interrupt \em IRQn.
  1163. * \param [in] IRQn Interrupt number
  1164. * \return shv
  1165. * - 0 non-vector mode, \ref ECLIC_NON_VECTOR_INTERRUPT
  1166. * - 1 vector mode, \ref ECLIC_VECTOR_INTERRUPT
  1167. * \remarks
  1168. * - IRQn must not be negative.
  1169. * \sa
  1170. * - \ref ECLIC_SMODE_SetShvIRQ
  1171. */
  1172. __STATIC_FORCEINLINE uint8_t __ECLIC_GetShvIRQ_S(IRQn_Type IRQn)
  1173. {
  1174. return ((uint8_t)(((ECLIC->SCTRL[IRQn].INTATTR) & CLIC_INTATTR_SHV_Msk) >> CLIC_INTATTR_SHV_Pos));
  1175. }
  1176. /**
  1177. * \brief Modify ECLIC Interrupt Input Control Register for a specific interrupt in supervisor mode
  1178. * \details
  1179. * This function modify ECLIC Interrupt Input Control(CLICINTCTL[i]) register of the specific interrupt \em IRQn.
  1180. * \param [in] IRQn Interrupt number
  1181. * \param [in] intctrl Set value for CLICINTCTL[i] register
  1182. * \remarks
  1183. * - IRQn must not be negative.
  1184. * \sa
  1185. * - \ref ECLIC_GetCtrlIRQ_S
  1186. */
  1187. __STATIC_FORCEINLINE void __ECLIC_SetCtrlIRQ_S(IRQn_Type IRQn, uint8_t intctrl)
  1188. {
  1189. ECLIC->SCTRL[IRQn].INTCTRL = intctrl;
  1190. }
  1191. /**
  1192. * \brief Get ECLIC Interrupt Input Control Register value for a specific interrupt in supervisor mode
  1193. * \details
  1194. * This function modify ECLIC Interrupt Input Control register of the specific interrupt \em IRQn.
  1195. * \param [in] IRQn Interrupt number
  1196. * \return value of ECLIC Interrupt Input Control register
  1197. * \remarks
  1198. * - IRQn must not be negative.
  1199. * \sa
  1200. * - \ref ECLIC_SetCtrlIRQ_S
  1201. */
  1202. __STATIC_FORCEINLINE uint8_t __ECLIC_GetCtrlIRQ_S(IRQn_Type IRQn)
  1203. {
  1204. return (ECLIC->SCTRL[IRQn].INTCTRL);
  1205. }
  1206. /**
  1207. * \brief Set ECLIC Interrupt level of a specific interrupt in supervisor mode
  1208. * \details
  1209. * This function set interrupt level of the specific interrupt \em IRQn.
  1210. * \param [in] IRQn Interrupt number
  1211. * \param [in] lvl_abs Interrupt level
  1212. * \remarks
  1213. * - IRQn must not be negative.
  1214. * - If lvl_abs to be set is larger than the max level allowed, it will be force to be max level.
  1215. * - When you set level value you need use clciinfo.nlbits to get the width of level.
  1216. * Then we could know the maximum of level. CLICINTCTLBITS is how many total bits are
  1217. * present in the CLICINTCTL register.
  1218. * \sa
  1219. * - \ref ECLIC_GetLevelIRQ_S
  1220. */
  1221. __STATIC_INLINE void __ECLIC_SetLevelIRQ_S(IRQn_Type IRQn, uint8_t lvl_abs)
  1222. {
  1223. uint8_t nlbits = __ECLIC_GetCfgNlbits();
  1224. uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
  1225. if (nlbits == 0) {
  1226. return;
  1227. }
  1228. if (nlbits > intctlbits) {
  1229. nlbits = intctlbits;
  1230. }
  1231. uint8_t maxlvl = ((1UL << nlbits) - 1);
  1232. if (lvl_abs > maxlvl) {
  1233. lvl_abs = maxlvl;
  1234. }
  1235. uint8_t lvl = lvl_abs << (ECLIC_MAX_NLBITS - nlbits);
  1236. uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ_S(IRQn);
  1237. cur_ctrl = cur_ctrl << nlbits;
  1238. cur_ctrl = cur_ctrl >> nlbits;
  1239. __ECLIC_SetCtrlIRQ_S(IRQn, (cur_ctrl | lvl));
  1240. }
  1241. /**
  1242. * \brief Get ECLIC Interrupt level of a specific interrupt
  1243. * \details
  1244. * This function get interrupt level of the specific interrupt \em IRQn.
  1245. * \param [in] IRQn Interrupt number
  1246. * \return Interrupt level
  1247. * \remarks
  1248. * - IRQn must not be negative.
  1249. * \sa
  1250. * - \ref ECLIC_SetLevelIRQ_S
  1251. */
  1252. __STATIC_INLINE uint8_t __ECLIC_GetLevelIRQ_S(IRQn_Type IRQn)
  1253. {
  1254. uint8_t nlbits = __ECLIC_GetCfgNlbits();
  1255. uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
  1256. if (nlbits == 0) {
  1257. return 0;
  1258. }
  1259. if (nlbits > intctlbits) {
  1260. nlbits = intctlbits;
  1261. }
  1262. uint8_t intctrl = __ECLIC_GetCtrlIRQ_S(IRQn);
  1263. uint8_t lvl_abs = intctrl >> (ECLIC_MAX_NLBITS - nlbits);
  1264. return lvl_abs;
  1265. }
  1266. /**
  1267. * \brief Set ECLIC Interrupt priority of a specific interrupt in supervisor mode
  1268. * \details
  1269. * This function get interrupt priority of the specific interrupt \em IRQn.
  1270. * \param [in] IRQn Interrupt number
  1271. * \param [in] pri Interrupt priority
  1272. * \remarks
  1273. * - IRQn must not be negative.
  1274. * - If pri to be set is larger than the max priority allowed, it will be force to be max priority.
  1275. * - Priority width is CLICINTCTLBITS minus clciinfo.nlbits if clciinfo.nlbits
  1276. * is less than CLICINTCTLBITS. Otherwise priority width is 0.
  1277. * \sa
  1278. * - \ref ECLIC_GetPriorityIRQ_S
  1279. */
  1280. __STATIC_INLINE void __ECLIC_SetPriorityIRQ_S(IRQn_Type IRQn, uint8_t pri)
  1281. {
  1282. uint8_t nlbits = __ECLIC_GetCfgNlbits();
  1283. uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
  1284. if (nlbits < intctlbits) {
  1285. uint8_t maxpri = ((1UL << (intctlbits - nlbits)) - 1);
  1286. if (pri > maxpri) {
  1287. pri = maxpri;
  1288. }
  1289. pri = pri << (ECLIC_MAX_NLBITS - intctlbits);
  1290. uint8_t mask = ((uint8_t)(-1)) >> intctlbits;
  1291. pri = pri | mask;
  1292. uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ_S(IRQn);
  1293. cur_ctrl = cur_ctrl >> (ECLIC_MAX_NLBITS - nlbits);
  1294. cur_ctrl = cur_ctrl << (ECLIC_MAX_NLBITS - nlbits);
  1295. __ECLIC_SetCtrlIRQ_S(IRQn, (cur_ctrl | pri));
  1296. }
  1297. }
  1298. /**
  1299. * \brief Get ECLIC Interrupt priority of a specific interrupt in supervisor mode
  1300. * \details
  1301. * This function get interrupt priority of the specific interrupt \em IRQn.
  1302. * \param [in] IRQn Interrupt number
  1303. * \return Interrupt priority
  1304. * \remarks
  1305. * - IRQn must not be negative.
  1306. * \sa
  1307. * - \ref ECLIC_SetPriorityIRQ_S
  1308. */
  1309. __STATIC_INLINE uint8_t __ECLIC_GetPriorityIRQ_S(IRQn_Type IRQn)
  1310. {
  1311. uint8_t nlbits = __ECLIC_GetCfgNlbits();
  1312. uint8_t intctlbits = (uint8_t)__ECLIC_INTCTLBITS;
  1313. if (nlbits < intctlbits) {
  1314. uint8_t cur_ctrl = __ECLIC_GetCtrlIRQ_S(IRQn);
  1315. uint8_t pri = cur_ctrl << nlbits;
  1316. pri = pri >> nlbits;
  1317. pri = pri >> (ECLIC_MAX_NLBITS - intctlbits);
  1318. return pri;
  1319. } else {
  1320. return 0;
  1321. }
  1322. }
  1323. /**
  1324. * \brief Enable a specific interrupt in supervisor mode
  1325. * \details
  1326. * This function enables the specific interrupt \em IRQn.
  1327. * \param [in] IRQn Interrupt number
  1328. * \remarks
  1329. * - IRQn must not be negative.
  1330. * \sa
  1331. * - \ref ECLIC_DisableIRQ
  1332. */
  1333. __STATIC_FORCEINLINE void __ECLIC_EnableIRQ_S(IRQn_Type IRQn)
  1334. {
  1335. ECLIC->SCTRL[IRQn].INTIE |= CLIC_INTIE_IE_Msk;
  1336. }
  1337. /**
  1338. * \brief Get a specific interrupt enable status in supervisor mode
  1339. * \details
  1340. * This function returns the interrupt enable status for the specific interrupt \em IRQn in S MODE.
  1341. * \param [in] IRQn Interrupt number
  1342. * \returns
  1343. * - 0 Interrupt is not masked
  1344. * - 1 Interrupt is enabled
  1345. * \remarks
  1346. * - IRQn must not be negative.
  1347. * \sa
  1348. * - \ref ECLIC_EnableIRQ_S
  1349. * - \ref ECLIC_DisableIRQ_S
  1350. */
  1351. __STATIC_FORCEINLINE uint8_t __ECLIC_GetEnableIRQ_S(IRQn_Type IRQn)
  1352. {
  1353. return ((uint8_t) (ECLIC->SCTRL[IRQn].INTIE) & CLIC_INTIE_IE_Msk);
  1354. }
  1355. /**
  1356. * \brief Disable a specific interrupt in supervisor mode
  1357. * \details
  1358. * This function disables the specific interrupt \em IRQn.
  1359. * \param [in] IRQn Number of the external interrupt to disable
  1360. * \remarks
  1361. * - IRQn must not be negative.
  1362. * \sa
  1363. * - \ref ECLIC_EnableIRQ
  1364. */
  1365. __STATIC_FORCEINLINE void __ECLIC_DisableIRQ_S(IRQn_Type IRQn)
  1366. {
  1367. ECLIC->SCTRL[IRQn].INTIE &= ~CLIC_INTIE_IE_Msk;
  1368. }
  1369. /**
  1370. * \brief Set Interrupt Vector of a specific interrupt in supervisor mode
  1371. * \details
  1372. * This function set interrupt handler address of the specific interrupt \em IRQn.
  1373. * \param [in] IRQn Interrupt number
  1374. * \param [in] vector Interrupt handler address
  1375. * \remarks
  1376. * - IRQn must not be negative.
  1377. * - You can set the \ref CSR_CSR_MTVT to set interrupt vector table entry address.
  1378. * - If your vector table is placed in readonly section, the vector for IRQn will not be modified.
  1379. * For this case, you need to use the correct irq handler name defined in your vector table as
  1380. * your irq handler function name.
  1381. * - This function will only work correctly when the vector table is placed in an read-write enabled section.
  1382. * \sa
  1383. * - \ref ECLIC_GetVector_S
  1384. */
  1385. __STATIC_INLINE void __ECLIC_SetVector_S(IRQn_Type IRQn, rv_csr_t vector)
  1386. {
  1387. volatile unsigned long vec_base;
  1388. vec_base = ((unsigned long)__RV_CSR_READ(CSR_STVT));
  1389. vec_base += ((unsigned long)IRQn) * sizeof(unsigned long);
  1390. (* (unsigned long *) vec_base) = vector;
  1391. #if (defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1))
  1392. #if (defined(__CCM_PRESENT) && (__CCM_PRESENT == 1))
  1393. SFlushDCacheLine((unsigned long)vec_base);
  1394. #endif
  1395. #endif
  1396. #if (defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1))
  1397. #if (defined(__CCM_PRESENT) && (__CCM_PRESENT == 1))
  1398. SInvalICacheLine((unsigned long)vec_base);
  1399. #else
  1400. __FENCE_I();
  1401. #endif
  1402. #endif
  1403. }
  1404. /**
  1405. * \brief Get Interrupt Vector of a specific interrupt in supervisor mode
  1406. * \details
  1407. * This function get interrupt handler address of the specific interrupt \em IRQn.
  1408. * \param [in] IRQn Interrupt number
  1409. * \return Interrupt handler address
  1410. * \remarks
  1411. * - IRQn must not be negative.
  1412. * - You can read \ref CSR_CSR_MTVT to get interrupt vector table entry address.
  1413. * \sa
  1414. * - \ref ECLIC_SMODE_SetVector
  1415. */
  1416. __STATIC_FORCEINLINE rv_csr_t __ECLIC_GetVector_S(IRQn_Type IRQn)
  1417. {
  1418. #if __RISCV_XLEN == 32
  1419. return (*(uint32_t *)(__RV_CSR_READ(CSR_STVT) + IRQn * 4));
  1420. #elif __RISCV_XLEN == 64
  1421. return (*(uint64_t *)(__RV_CSR_READ(CSR_STVT) + IRQn * 8));
  1422. #else // TODO Need cover for XLEN=128 case in future
  1423. return (*(uint64_t *)(__RV_CSR_READ(CSR_STVT) + IRQn * 8));
  1424. #endif
  1425. }
  1426. #if __ECLIC_VER == 2
  1427. /**
  1428. * \brief Enable ECLIC Shadow Register Function (Supervisor Mode)
  1429. * \details
  1430. * This function enables the shadow register function for ECLIC in Supervisor Mode.
  1431. * It sets the SECLIC_CTL_SHADOW_EN bit in the CSR_SECLIC_CTL CSR.
  1432. * This function is only valid for ECLIC version 2 and above in TEE environments.
  1433. * \remarks
  1434. * - API only available for ECLIC v2
  1435. * \sa
  1436. * - \ref __ECLIC_DisableShadow_S
  1437. */
  1438. __STATIC_FORCEINLINE void __ECLIC_EnableShadow_S(void)
  1439. {
  1440. __RV_CSR_SET(CSR_SECLIC_CTL, SECLIC_CTL_SHADOW_EN);
  1441. }
  1442. /**
  1443. * \brief Disable ECLIC Shadow Register Function (Supervisor Mode)
  1444. * \details
  1445. * This function disables the shadow register function for ECLIC in Supervisor Mode.
  1446. * It clears the SECLIC_CTL_SHADOW_EN bit in the CSR_SECLIC_CTL CSR.
  1447. * This function is only valid for ECLIC version 2 and above in TEE environments.
  1448. * \remarks
  1449. * - API only available for ECLIC v2
  1450. * \sa
  1451. * - \ref __ECLIC_EnableShadow_S
  1452. */
  1453. __STATIC_FORCEINLINE void __ECLIC_DisableShadow_S(void)
  1454. {
  1455. __RV_CSR_CLEAR(CSR_SECLIC_CTL, SECLIC_CTL_SHADOW_EN);
  1456. }
  1457. /**
  1458. * \brief Set Shadow Register Interrupt Level for a specific s-mode shadow register
  1459. * \details
  1460. * This function sets the interrupt level for a specific s-mode shadow register \em idx + 1.
  1461. * It configures CSR_SSHADGPRLVL0 and CSR_SSHADGPRLVL1 registers.
  1462. * \param [in] idx Shadow register index (0-7), corresponding to shadow registers 1-8
  1463. * (Note: shadow register 0 is fixed for first-come-first-served s-mode
  1464. * interrupt and cannot be configured)
  1465. * \param [in] level Interrupt level to set for the shadow register
  1466. * \remarks
  1467. * - API only available for ECLIC v2
  1468. * - idx = 0 means set SHAD1_CFG, which configures the shadow register 1
  1469. * - For RV64, all 8 shadow registers are configured in CSR_SSHADGPRLVL0
  1470. * - For RV32, shadow registers 1-4 are in lower 32 bits of CSR_SSHADGPRLVL0,
  1471. * and shadow registers 5-8 are in CSR_SSHADGPRLVL1
  1472. * \sa
  1473. * - \ref ECLIC_GetShadowLevel_S
  1474. */
  1475. __STATIC_INLINE void __ECLIC_SetShadowLevel_S(unsigned long idx, uint8_t level)
  1476. {
  1477. /* Check if idx is valid (0-7) */
  1478. if (idx > 7) {
  1479. return;
  1480. }
  1481. uint8_t nlbits = (uint8_t)__ECLIC_GetCfgNlbits();
  1482. /* Limit the level value to the available number of bits */
  1483. uint8_t max_level = (1U << nlbits) - 1;
  1484. if (level > max_level) {
  1485. level = max_level;
  1486. }
  1487. /* Position the level value in the upper nlbits of the 8-bit field and set the low (8-nlbits) bits to 1 */
  1488. uint8_t level_shifted = (uint8_t)((level << (8 - nlbits)) | ((1U << (8 - nlbits)) - 1));
  1489. #if __RISCV_XLEN == 64
  1490. /* For RV64, all 8 shadow registers are in CSR_SSHADGPRLVL0 */
  1491. /* Calculate the bit position for the 8-bit field of the specified index */
  1492. uint32_t bit_pos = idx << 3; /* idx * 8 using bit shift */
  1493. /* Create mask to clear the 8-bit field for the specified index */
  1494. uint64_t mask = (uint64_t)0xFFUL << bit_pos;
  1495. /* Read, modify, and write the CSR register */
  1496. uint64_t current_val = __RV_CSR_READ(CSR_SSHADGPRLVL0);
  1497. current_val = (current_val & ~mask) | (((uint64_t)level_shifted) << bit_pos);
  1498. __RV_CSR_WRITE(CSR_SSHADGPRLVL0, current_val);
  1499. #else
  1500. /* For RV32, calculate bit position and select appropriate register */
  1501. if (idx < 4) {
  1502. /* Shadow registers 1-4 are in CSR_SSHADGPRLVL0 */
  1503. uint32_t bit_pos = idx << 3; /* idx * 8 using bit shift */
  1504. uint32_t mask = 0xFFUL << bit_pos;
  1505. uint32_t current_val = __RV_CSR_READ(CSR_SSHADGPRLVL0);
  1506. current_val = (current_val & ~mask) | (((uint32_t)level_shifted) << bit_pos);
  1507. __RV_CSR_WRITE(CSR_SSHADGPRLVL0, current_val);
  1508. } else {
  1509. /* Shadow registers 5-8 are in CSR_SSHADGPRLVL1 */
  1510. uint32_t bit_pos = (idx - 4) << 3; /* (idx - 4) * 8 using bit shift */
  1511. uint32_t mask = 0xFFUL << bit_pos;
  1512. uint32_t current_val = __RV_CSR_READ(CSR_SSHADGPRLVL1);
  1513. current_val = (current_val & ~mask) | (((uint32_t)level_shifted) << bit_pos);
  1514. __RV_CSR_WRITE(CSR_SSHADGPRLVL1, current_val);
  1515. }
  1516. #endif
  1517. }
  1518. /**
  1519. * \brief Get Shadow Register Interrupt Level for a specific s-mode shadow register
  1520. * \details
  1521. * This function gets the interrupt level for a specific s-mode shadow register \em idx + 1.
  1522. * It reads CSR_SSHADGPRLVL0 and CSR_SSHADGPRLVL1 registers.
  1523. * \param [in] idx Shadow register index (0-7), corresponding to shadow registers 1-8
  1524. * (Note: shadow register 0 is fixed for first-come-first-served s-mode
  1525. * interrupt and cannot be configured)
  1526. * \return Interrupt level of the shadow register
  1527. * \remarks
  1528. * - API only available for ECLIC v2
  1529. * - idx = 0 means set SHAD1_CFG, which configures the shadow register 1
  1530. * - For RV64, all 8 shadow registers are configured in CSR_SSHADGPRLVL0
  1531. * - For RV32, shadow registers 1-4 are in lower 32 bits of CSR_SSHADGPRLVL0,
  1532. * and shadow registers 5-8 are in CSR_SSHADGPRLVL1
  1533. * \sa
  1534. * - \ref ECLIC_SetShadowLevel_S
  1535. */
  1536. __STATIC_INLINE uint8_t __ECLIC_GetShadowLevel_S(unsigned long idx)
  1537. {
  1538. /* Check if idx is valid (0-7) */
  1539. if (idx > 7) {
  1540. return 0;
  1541. }
  1542. uint8_t nlbits = (uint8_t)__ECLIC_GetCfgNlbits();
  1543. #if __RISCV_XLEN == 64
  1544. /* For RV64, all 8 shadow registers are in CSR_SSHADGPRLVL0 */
  1545. /* Calculate the bit position for the 8-bit field of the specified index */
  1546. uint32_t bit_pos = idx << 3; /* idx * 8 using bit shift */
  1547. /* Read the CSR register and extract the 8-bit field */
  1548. uint64_t current_val = __RV_CSR_READ(CSR_SSHADGPRLVL0);
  1549. uint8_t extracted_val = (uint8_t)((current_val >> bit_pos) & 0xFF);
  1550. /* Extract the level from the upper nlbits of the 8-bit field */
  1551. uint8_t level = (extracted_val >> (8 - nlbits));
  1552. return level;
  1553. #else
  1554. /* For RV32, calculate bit position and select appropriate register */
  1555. if (idx < 4) {
  1556. /* Shadow registers 1-4 are in CSR_SSHADGPRLVL0 */
  1557. uint32_t bit_pos = idx << 3; /* idx * 8 using bit shift */
  1558. /* Read the CSR register and extract the 8-bit field */
  1559. uint32_t current_val = __RV_CSR_READ(CSR_SSHADGPRLVL0);
  1560. uint8_t extracted_val = (uint8_t)((current_val >> bit_pos) & 0xFF);
  1561. /* Extract the level from the upper nlbits of the 8-bit field */
  1562. uint8_t level = (extracted_val >> (8 - nlbits));
  1563. return level;
  1564. } else {
  1565. /* Shadow registers 5-8 are in CSR_SSHADGPRLVL1 */
  1566. uint32_t bit_pos = (idx - 4) << 3; /* (idx - 4) * 8 using bit shift */
  1567. /* Read the CSR register and extract the 8-bit field */
  1568. uint32_t current_val = __RV_CSR_READ(CSR_SSHADGPRLVL1);
  1569. uint8_t extracted_val = (uint8_t)((current_val >> bit_pos) & 0xFF);
  1570. /* Extract the level from the upper nlbits of the 8-bit field */
  1571. uint8_t level = (extracted_val >> (8 - nlbits));
  1572. return level;
  1573. }
  1574. #endif
  1575. }
  1576. /**
  1577. * \brief Set Shadow Register Level Register for s-mode
  1578. * \details
  1579. * This function sets the entire shadow register level register for s-mode.
  1580. * It writes directly to CSR_SSHADGPRLVL0 register (and CSR_SSHADGPRLVL1 for RV32).
  1581. * \param [in] value 64-bit value to set for the shadow register level register
  1582. * \remarks
  1583. * - API only available for ECLIC v2
  1584. * - For RV64, all 8 shadow registers are configured in CSR_SSHADGPRLVL0
  1585. * - For RV32, shadow registers 1-4 are in lower 32 bits of CSR_SSHADGPRLVL0,
  1586. * and shadow registers 5-8 are in CSR_SSHADGPRLVL1
  1587. * - Note: shadow register 0 is fixed for first-come-first-served s-mode interrupt and cannot be configured
  1588. * \sa
  1589. * - \ref ECLIC_GetShadowLevelReg_S
  1590. */
  1591. __STATIC_INLINE void __ECLIC_SetShadowLevelReg_S(uint64_t value)
  1592. {
  1593. #if __RISCV_XLEN == 64
  1594. __RV_CSR_WRITE(CSR_SSHADGPRLVL0, value);
  1595. #else
  1596. __RV_CSR_WRITE(CSR_SSHADGPRLVL0, (uint32_t)value);
  1597. __RV_CSR_WRITE(CSR_SSHADGPRLVL1, (uint32_t)(value >> 32));
  1598. #endif
  1599. }
  1600. /**
  1601. * \brief Get Shadow Register Level Register for s-mode
  1602. * \details
  1603. * This function gets the entire shadow register level register for s-mode.
  1604. * It reads from CSR_SSHADGPRLVL0 register (and CSR_SSHADGPRLVL1 for RV32) and combines them.
  1605. * \return 64-bit value of the shadow register level register
  1606. * \remarks
  1607. * - API only available for ECLIC v2
  1608. * - For RV64, all 8 shadow registers are configured in CSR_SSHADGPRLVL0
  1609. * - For RV32, shadow registers 1-4 are in lower 32 bits of CSR_SSHADGPRLVL0,
  1610. * and shadow registers 5-8 are in CSR_SSHADGPRLVL1
  1611. * - Note: shadow register 0 is fixed for first-come-first-served s-mode interrupt and cannot be configured
  1612. * \sa
  1613. * - \ref ECLIC_SetShadowLevelReg_S
  1614. */
  1615. __STATIC_INLINE uint64_t __ECLIC_GetShadowLevelReg_S(void)
  1616. {
  1617. #if __RISCV_XLEN == 64
  1618. return __RV_CSR_READ(CSR_SSHADGPRLVL0);
  1619. #else
  1620. uint64_t value = __RV_CSR_READ(CSR_SSHADGPRLVL1);
  1621. value <<= 32;
  1622. value |= __RV_CSR_READ(CSR_SSHADGPRLVL0);
  1623. return value;
  1624. #endif
  1625. }
  1626. #endif
  1627. #endif /* defined(__TEE_PRESENT) && (__TEE_PRESENT == 1) */
  1628. /**
  1629. * \brief Set Exception entry address
  1630. * \details
  1631. * This function set exception handler address to 'CSR_MTVEC'.
  1632. * \param [in] addr Exception handler address
  1633. * \remarks
  1634. * - This function use to set exception handler address to 'CSR_MTVEC'.
  1635. * Address need to be aligned to 64 bytes.
  1636. * \sa
  1637. * - \ref __get_exc_entry
  1638. */
  1639. __STATIC_FORCEINLINE void __set_exc_entry(rv_csr_t addr)
  1640. {
  1641. addr &= (rv_csr_t)(~0x3F);
  1642. addr |= ECLIC_MODE_MTVEC_Msk;
  1643. __RV_CSR_WRITE(CSR_MTVEC, addr);
  1644. }
  1645. /**
  1646. * \brief Get Exception entry address
  1647. * \details
  1648. * This function get exception handler address from 'CSR_MTVEC'.
  1649. * \return Exception handler address
  1650. * \remarks
  1651. * - This function use to get exception handler address from 'CSR_MTVEC'.
  1652. * Address need to be aligned to 64 bytes.
  1653. * \sa
  1654. * - \ref __set_exc_entry
  1655. */
  1656. __STATIC_FORCEINLINE rv_csr_t __get_exc_entry(void)
  1657. {
  1658. unsigned long addr = __RV_CSR_READ(CSR_MTVEC);
  1659. return (addr & ~ECLIC_MODE_MTVEC_Msk);
  1660. }
  1661. /**
  1662. * \brief Set Non-vector interrupt entry address
  1663. * \details
  1664. * This function set Non-vector interrupt address.
  1665. * \param [in] addr Non-vector interrupt entry address
  1666. * \remarks
  1667. * - This function use to set non-vector interrupt entry address to 'CSR_MTVT2' if
  1668. * - CSR_MTVT2 bit0 is 1. If 'CSR_MTVT2' bit0 is 0 then set address to 'CSR_MTVEC'
  1669. * \sa
  1670. * - \ref __get_nonvec_entry
  1671. */
  1672. __STATIC_INLINE void __set_nonvec_entry(rv_csr_t addr)
  1673. {
  1674. if (__RV_CSR_READ(CSR_MTVT2) & 0x1) {
  1675. __RV_CSR_WRITE(CSR_MTVT2, addr | 0x01);
  1676. } else {
  1677. addr &= (rv_csr_t)(~0x3F);
  1678. addr |= ECLIC_MODE_MTVEC_Msk;
  1679. __RV_CSR_WRITE(CSR_MTVEC, addr);
  1680. }
  1681. }
  1682. /**
  1683. * \brief Get Non-vector interrupt entry address
  1684. * \details
  1685. * This function get Non-vector interrupt address.
  1686. * \return Non-vector interrupt handler address
  1687. * \remarks
  1688. * - This function use to get non-vector interrupt entry address from 'CSR_MTVT2' if
  1689. * - CSR_MTVT2 bit0 is 1. If 'CSR_MTVT2' bit0 is 0 then get address from 'CSR_MTVEC'.
  1690. * \sa
  1691. * - \ref __set_nonvec_entry
  1692. */
  1693. __STATIC_INLINE rv_csr_t __get_nonvec_entry(void)
  1694. {
  1695. if (__RV_CSR_READ(CSR_MTVT2) & 0x1) {
  1696. return __RV_CSR_READ(CSR_MTVT2) & (~(rv_csr_t)(0x1));
  1697. } else {
  1698. rv_csr_t addr = __RV_CSR_READ(CSR_MTVEC);
  1699. return (addr & ~ECLIC_MODE_MTVEC_Msk);
  1700. }
  1701. }
  1702. /**
  1703. * \brief Get NMI interrupt entry from 'CSR_MNVEC'
  1704. * \details
  1705. * This function get NMI interrupt address from 'CSR_MNVEC'.
  1706. * \return NMI interrupt handler address
  1707. * \remarks
  1708. * - This function use to get NMI interrupt handler address from 'CSR_MNVEC'. If CSR_MMISC_CTL[9] = 1 'CSR_MNVEC'
  1709. * - will be equal as mtvec. If CSR_MMISC_CTL[9] = 0 'CSR_MNVEC' will be equal as reset vector.
  1710. * - NMI entry is defined via \ref CSR_MMISC_CTL, writing to \ref CSR_MNVEC will be ignored.
  1711. */
  1712. __STATIC_FORCEINLINE rv_csr_t __get_nmi_entry(void)
  1713. {
  1714. return __RV_CSR_READ(CSR_MNVEC);
  1715. }
  1716. /* NOTE: SSUBM CSR is introduced in ECLIC v2, without this the S_Mode vector interrupt nesting
  1717. * and non-vector interrupt nesting will not work properly */
  1718. #if __ECLIC_VER == 2
  1719. #define SAVE_SSUBM_VAR() rv_csr_t __ssubm = __RV_CSR_READ(CSR_SSUBM);
  1720. #define RESTORE_SSUBM_VAR() __RV_CSR_WRITE(CSR_SSUBM, __ssubm);
  1721. #else
  1722. #define SAVE_SSUBM_VAR()
  1723. #define RESTORE_SSUBM_VAR()
  1724. #endif
  1725. /**
  1726. * \brief Save necessary CSRs into variables for vector interrupt nesting
  1727. * \details
  1728. * This macro is used to declare variables which are used for saving
  1729. * CSRs(MCAUSE, MEPC, MSUB), and it will read these CSR content into
  1730. * these variables, it need to be used in a vector-interrupt if nesting
  1731. * is required.
  1732. * \remarks
  1733. * - Interrupt will be enabled after this macro is called
  1734. * - It need to be used together with \ref RESTORE_IRQ_CSR_CONTEXT
  1735. * - Don't use variable names __mcause, __mpec, __msubm in your ISR code
  1736. * - If you want to enable interrupt nesting feature for vector interrupt,
  1737. * you can do it like this:
  1738. * \code
  1739. * // __INTERRUPT attribute will generates function entry and exit sequences suitable
  1740. * // for use in an interrupt handler when this attribute is present
  1741. * __INTERRUPT void eclic_mtip_handler(void)
  1742. * {
  1743. * // Must call this to save CSRs
  1744. * SAVE_IRQ_CSR_CONTEXT();
  1745. * // !!!Interrupt is enabled here!!!
  1746. * // !!!Higher priority interrupt could nest it!!!
  1747. *
  1748. * // put you own interrupt handling code here
  1749. *
  1750. * // Must call this to restore CSRs
  1751. * RESTORE_IRQ_CSR_CONTEXT();
  1752. * }
  1753. * \endcode
  1754. */
  1755. #define SAVE_IRQ_CSR_CONTEXT() \
  1756. rv_csr_t __mcause = __RV_CSR_READ(CSR_MCAUSE); \
  1757. rv_csr_t __mepc = __RV_CSR_READ(CSR_MEPC); \
  1758. rv_csr_t __msubm = __RV_CSR_READ(CSR_MSUBM); \
  1759. __enable_irq();
  1760. /*! Save necessary CSRs into variables for vector interrupt nesting in supervisor mode */
  1761. #define SAVE_IRQ_CSR_CONTEXT_S() \
  1762. rv_csr_t __scause = __RV_CSR_READ(CSR_SCAUSE); \
  1763. rv_csr_t __sepc = __RV_CSR_READ(CSR_SEPC); \
  1764. SAVE_SSUBM_VAR(); \
  1765. __enable_irq_s();
  1766. /**
  1767. * \brief Restore necessary CSRs from variables for vector interrupt nesting
  1768. * \details
  1769. * This macro is used restore CSRs(MCAUSE, MEPC, MSUB) from pre-defined variables
  1770. * in \ref SAVE_IRQ_CSR_CONTEXT macro.
  1771. * \remarks
  1772. * - Interrupt will be disabled after this macro is called
  1773. * - It need to be used together with \ref SAVE_IRQ_CSR_CONTEXT
  1774. */
  1775. #define RESTORE_IRQ_CSR_CONTEXT() \
  1776. __disable_irq(); \
  1777. __RV_CSR_WRITE(CSR_MSUBM, __msubm); \
  1778. __RV_CSR_WRITE(CSR_MEPC, __mepc); \
  1779. __RV_CSR_WRITE(CSR_MCAUSE, __mcause);
  1780. /*! Restore necessary CSRs from variables for vector interrupt nesting in supervisor mode */
  1781. #define RESTORE_IRQ_CSR_CONTEXT_S() \
  1782. __disable_irq_s(); \
  1783. RESTORE_SSUBM_VAR(); \
  1784. __RV_CSR_WRITE(CSR_SEPC, __sepc); \
  1785. __RV_CSR_WRITE(CSR_SCAUSE, __scause);
  1786. /** @} */ /* End of Doxygen Group NMSIS_Core_IntExc */
  1787. #endif /* defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1) */
  1788. #ifdef __cplusplus
  1789. }
  1790. #endif
  1791. #endif /* __CORE_FEATURE_ECLIC__ */