core_feature_timer.h 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082
  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_TIMER_H__
  19. #define __CORE_FEATURE_TIMER_H__
  20. /*!
  21. * @file core_feature_timer.h
  22. * @brief System Timer feature API header file for Nuclei N/NX Core
  23. */
  24. /*
  25. * System Timer Feature Configuration Macro:
  26. * 1. __SYSTIMER_PRESENT: Must, Define whether Private System Timer is present or not.
  27. * * 0: Not present
  28. * * 1: Present
  29. * 2. __SYSTIMER_BASEADDR: Must, Define the base address of the System Timer.
  30. * 3. __SYSTIMER_HARTID: Optional, Define the system timer hart index of the cpu, important for case when cpu hartid and cpu hart index are different, only set it if your cpu is single core.
  31. */
  32. #ifdef __cplusplus
  33. extern "C" {
  34. #endif
  35. #include "core_feature_base.h"
  36. #if defined(__SYSTIMER_PRESENT) && (__SYSTIMER_PRESENT == 1)
  37. /**
  38. * \defgroup NMSIS_Core_SysTimer_Registers Register Define and Type Definitions Of System Timer
  39. * \ingroup NMSIS_Core_Registers
  40. * \brief Type definitions and defines for system timer registers.
  41. *
  42. * @{
  43. */
  44. /**
  45. * \brief Structure type to access the System Timer (SysTimer).
  46. * \details
  47. * Structure definition to access the system timer(SysTimer).
  48. * \remarks
  49. * - MSFTRST register is introduced in Nuclei N Core version 1.3(\ref __NUCLEI_N_REV >= 0x0103)
  50. * - MSTOP register is renamed to MTIMECTL register in Nuclei N Core version 1.4(\ref __NUCLEI_N_REV >= 0x0104)
  51. * - CMPCLREN and CLKSRC bit in MTIMECTL register is introduced in Nuclei N Core version 1.4(\ref __NUCLEI_N_REV >= 0x0104)
  52. */
  53. typedef struct {
  54. #if defined(CPU_SERIES) && CPU_SERIES == 100
  55. __IOM uint32_t MTIMER; /*!< Offset: 0x000 (R/W) System Timer current value 32bits Register for N100 */
  56. __IOM uint32_t RESERVED1; /*!< Offset: 0x004 (R/W) Reserved, not available */
  57. __IOM uint32_t MTIMERCMP; /*!< Offset: 0x008 (R/W) System Timer compare Value 32bits Register for N100 */
  58. __IOM uint32_t RESERVED2; /*!< Offset: 0x00C (R/W) Reserved, not available */
  59. #else
  60. __IOM uint64_t MTIMER; /*!< Offset: 0x000 (R/W) System Timer current value 64bits Register */
  61. __IOM uint64_t MTIMERCMP; /*!< Offset: 0x008 (R/W) System Timer compare Value 64bits Register */
  62. #endif
  63. __IOM uint32_t RESERVED0[0x3F7]; /*!< Offset: 0x010 - 0xFE8 Reserved */
  64. __IOM uint32_t MTIME_SRW_CTRL; /*!< Offset: 0xFEC (R/W) Control S-mode can access this timer or not, not present in N100 */
  65. __IOM uint32_t MSFTRST; /*!< Offset: 0xFF0 (R/W) System Timer Software Core Reset Register */
  66. __IOM uint32_t SSIP; /*!< Offset: 0xFF4 (R/W) S-Mode System Timer SW interrupt Register, not present in N100 */
  67. __IOM uint32_t MTIMECTL; /*!< Offset: 0xFF8 (R/W) System Timer Control Register, previously MSTOP register */
  68. __IOM uint32_t MSIP; /*!< Offset: 0xFFC (R/W) M-Mode System Timer SW interrupt Register */
  69. } SysTimer_Type;
  70. /* Timer Control / Status Register Definitions */
  71. #define SysTimer_MTIMECTL_TIMESTOP_Pos 0U /*!< SysTick Timer MTIMECTL: TIMESTOP bit Position */
  72. #define SysTimer_MTIMECTL_TIMESTOP_Msk (1UL << SysTimer_MTIMECTL_TIMESTOP_Pos) /*!< SysTick Timer MTIMECTL: TIMESTOP Mask */
  73. #define SysTimer_MTIMECTL_CMPCLREN_Pos 1U /*!< SysTick Timer MTIMECTL: CMPCLREN bit Position */
  74. #define SysTimer_MTIMECTL_CMPCLREN_Msk (1UL << SysTimer_MTIMECTL_CMPCLREN_Pos) /*!< SysTick Timer MTIMECTL: CMPCLREN Mask */
  75. #define SysTimer_MTIMECTL_CLKSRC_Pos 2U /*!< SysTick Timer MTIMECTL: CLKSRC bit Position */
  76. #define SysTimer_MTIMECTL_CLKSRC_Msk (1UL << SysTimer_MTIMECTL_CLKSRC_Pos) /*!< SysTick Timer MTIMECTL: CLKSRC Mask */
  77. #define SysTimer_MTIMECTL_HDBG_Pos 3U /*!< SysTick Timer MTIMECTL: HDBG bit Position */
  78. #define SysTimer_MTIMECTL_HDBG_Msk (1UL << SysTimer_MTIMECTL_HDBG_Pos) /*!< SysTick Timer MTIMECTL: HDBG Mask */
  79. #define SysTimer_MTIMECTL_MTIME_SRC_Pos 4U /*!< SysTick Timer MTIMECTL: MTIME_SRC bit Position */
  80. #define SysTimer_MTIMECTL_MTIME_SRC_Msk (1UL << SysTimer_MTIMECTL_MTIME_SRC_Pos) /*!< SysTick Timer MTIMECTL: MTIME_SRC Mask */
  81. #define SysTimer_MSIP_MSIP_Pos 0U /*!< SysTick Timer MSIP: MSIP bit Position */
  82. #define SysTimer_MSIP_MSIP_Msk (1UL << SysTimer_MSIP_MSIP_Pos) /*!< SysTick Timer MSIP: MSIP Mask */
  83. #define SysTimer_SSIP_SSIP_Pos 0U /*!< SysTick Timer SSIP: SSIP bit Position */
  84. #define SysTimer_SSIP_SSIP_Msk (1UL << SysTimer_SSIP_SSIP_Pos) /*!< SysTick Timer SSIP: SSIP Mask */
  85. #define SysTimer_MTIME_SRW_CTRL_SRW_Pos 0U /*!< SysTick Timer MTIME_SRW_CTRL: SRW bit Position */
  86. #define SysTimer_MTIME_SRW_CTRL_SRW_Msk (1UL << SysTimer_MTIME_SRW_CTRL_SRW_Pos) /*!< SysTick Timer MTIME_SRW_CTRL: SRW Mask */
  87. #if defined(CPU_SERIES) && CPU_SERIES == 100
  88. #define SysTimer_MTIMER_Msk (0xFFFFFFFFUL) /*!< SysTick Timer MTIMER value Mask for N100 */
  89. #define SysTimer_MTIMERCMP_Msk (0xFFFFFFFFUL) /*!< SysTick Timer MTIMERCMP value Mask for N100 */
  90. #else
  91. #define SysTimer_MTIMER_Msk (0xFFFFFFFFFFFFFFFFULL) /*!< SysTick Timer MTIMER value Mask */
  92. #define SysTimer_MTIMERCMP_Msk (0xFFFFFFFFFFFFFFFFULL) /*!< SysTick Timer MTIMERCMP value Mask */
  93. #endif
  94. #define SysTimer_MTIMECTL_Msk (0xFFFFFFFFUL) /*!< SysTick Timer MTIMECTL/MSTOP value Mask */
  95. #define SysTimer_MSIP_Msk (0xFFFFFFFFUL) /*!< SysTick Timer MSIP value Mask */
  96. #define SysTimer_MSFTRST_Msk (0xFFFFFFFFUL) /*!< SysTick Timer MSFTRST value Mask */
  97. #define SysTimer_MSFRST_KEY (0x80000A5FUL) /*!< SysTick Timer Software Reset Request Key */
  98. #define SysTimer_CLINT_MSIP_OFS (0x1000UL) /*!< Machine Mode Software interrupt register offset of clint mode in SysTick Timer */
  99. #define SysTimer_CLINT_MTIMECMP_OFS (0x5000UL) /*!< MTIMECMP register offset of clint mode in SysTick Timer */
  100. #define SysTimer_CLINT_MTIME_OFS (0xCFF8UL) /*!< MTIME register offset of clint mode in SysTick Timer */
  101. #define SysTimer_CLINT_SSIP_OFS (0xD000UL) /*!< Supervisor Mode Software interrupt register offset of clint mode in SysTick Timer */
  102. #ifndef __SYSTIMER_BASEADDR
  103. /* Base address of SYSTIMER(__SYSTIMER_BASEADDR) should be defined in <Device.h> */
  104. #error "__SYSTIMER_BASEADDR is not defined, please check!"
  105. #endif
  106. /* System Timer Memory mapping of Device */
  107. #define SysTimer_BASE __SYSTIMER_BASEADDR /*!< SysTick Base Address */
  108. #define SysTimer ((SysTimer_Type *) SysTimer_BASE) /*!< SysTick configuration struct */
  109. /* System Timer Clint register base */
  110. #define SysTimer_CLINT_MSIP_BASE(hartid) (unsigned long)((SysTimer_BASE) + (SysTimer_CLINT_MSIP_OFS) + ((hartid) << 2))
  111. #define SysTimer_CLINT_MTIMECMP_BASE(hartid) (unsigned long)((SysTimer_BASE) + (SysTimer_CLINT_MTIMECMP_OFS) + ((hartid) << 3))
  112. #define SysTimer_CLINT_MTIME_BASE (unsigned long)((SysTimer_BASE) + (SysTimer_CLINT_MTIME_OFS))
  113. #define SysTimer_CLINT_SSIP_BASE(hartid) (unsigned long)((SysTimer_BASE) + (SysTimer_CLINT_SSIP_OFS) + ((hartid) << 2))
  114. /** @} */ /* end of group NMSIS_Core_SysTimer_Registers */
  115. /* ################################## SysTimer function ############################################ */
  116. /**
  117. * \defgroup NMSIS_Core_SysTimer SysTimer Functions
  118. * \brief Functions that configure the Core System Timer.
  119. * @{
  120. */
  121. /**
  122. * SysTimer_GetHartID() is used to get timer hartid which might not be the same as cpu hart id,
  123. * for example, cpu hartid may be 1, but timer hartid may be 0, then timer hartid offset is 1.
  124. * If defined __SYSTIMER_HARTID, it will use __SYSTIMER_HARTID as timer hartid,
  125. * otherwise, it will use __get_hart_index().
  126. * The cpu hartid is get by using __get_hart_id function
  127. */
  128. #ifndef __SYSTIMER_HARTID
  129. #define SysTimer_GetHartID() (__get_hart_index())
  130. #else
  131. #define SysTimer_GetHartID() (__SYSTIMER_HARTID)
  132. #endif
  133. #if defined(__SSTC_PRESENT) && (__SSTC_PRESENT == 1)
  134. #ifndef __SYSTIMER_HARTID
  135. #define SysTimer_GetHartID_S() (__get_hart_index_s())
  136. #else
  137. #define SysTimer_GetHartID_S() (__SYSTIMER_HARTID)
  138. #endif
  139. #endif
  140. /**
  141. * \brief Set system timer load value
  142. * \details
  143. * This function set the system timer load value in MTIMER register.
  144. * \param [in] value value to set system timer MTIMER register.
  145. * \remarks
  146. * - Load value is 64bits wide for non-n100 cpu
  147. * - \ref SysTimer_GetLoadValue
  148. */
  149. __STATIC_INLINE void SysTimer_SetLoadValue(rv_counter_t value)
  150. {
  151. #if (__RISCV_XLEN == 32) && !(defined(CPU_SERIES) && CPU_SERIES == 100)
  152. uint8_t *addr;
  153. addr = (uint8_t *)(&(SysTimer->MTIMER));
  154. __SW(addr, 0); // prevent carry
  155. __SW(addr + 4, (uint32_t)(value >> 32));
  156. __SW(addr, (uint32_t)(value));
  157. #else
  158. SysTimer->MTIMER = value;
  159. #endif
  160. }
  161. /**
  162. * \brief Get system timer load value
  163. * \details
  164. * This function get the system timer current value in MTIMER register.
  165. * \return current value(64bit) of system timer MTIMER register.
  166. * \remarks
  167. * - Load value is 64bits wide.
  168. * - \ref SysTimer_SetLoadValue
  169. */
  170. __STATIC_INLINE rv_counter_t SysTimer_GetLoadValue(void)
  171. {
  172. #if (__RISCV_XLEN == 32) && !(defined(CPU_SERIES) && CPU_SERIES == 100)
  173. volatile uint32_t high0, low, high;
  174. uint64_t full;
  175. uint8_t *addr;
  176. addr = (uint8_t *)(&(SysTimer->MTIMER));
  177. high0 = __LW(addr + 4);
  178. low = __LW(addr);
  179. high = __LW(addr + 4);
  180. if (high0 != high) {
  181. low = __LW(addr);
  182. }
  183. full = (((uint64_t)high) << 32) | low;
  184. return full;
  185. #else
  186. return SysTimer->MTIMER;
  187. #endif
  188. }
  189. /**
  190. * \brief Set system timer compare value by hartid
  191. * \details
  192. * This function set the system Timer compare value in MTIMERCMP register.
  193. * \param [in] value compare value to set system timer MTIMERCMP register.
  194. * \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
  195. * \remarks
  196. * - Compare value is 64bits wide.
  197. * - If compare value is larger than current value timer interrupt generate.
  198. * - Modify the load value or compare value less to clear the interrupt.
  199. * - In S-mode, hartid can't be get by using __get_hart_id function, so this api suits S-mode particularly.
  200. * - \ref SysTimer_GetHartCompareValue
  201. */
  202. __STATIC_INLINE void SysTimer_SetHartCompareValue(rv_counter_t value, unsigned long hartid)
  203. {
  204. #if (defined(CPU_SERIES) && CPU_SERIES == 100)
  205. SysTimer->MTIMERCMP = value;
  206. #else
  207. if (hartid == 0) {
  208. #if __RISCV_XLEN == 32
  209. uint8_t *addr;
  210. addr = (uint8_t *)(&(SysTimer->MTIMERCMP));
  211. __SW(addr, -1U); // prevent load > timecmp
  212. __SW(addr + 4, (uint32_t)(value >> 32));
  213. __SW(addr, (uint32_t)(value));
  214. #else
  215. SysTimer->MTIMERCMP = value;
  216. #endif
  217. } else {
  218. uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MTIMECMP_BASE(hartid));
  219. #if __RISCV_XLEN == 32
  220. __SW(addr, -1U); // prevent load > timecmp
  221. __SW(addr + 4, (uint32_t)(value >> 32));
  222. __SW(addr, (uint32_t)value);
  223. #else
  224. __SD(addr, value);
  225. #endif
  226. }
  227. #endif
  228. }
  229. /**
  230. * \brief Set system timer compare value in machine mode
  231. * \details
  232. * This function set the system Timer compare value in MTIMERCMP register.
  233. * \param [in] value compare value to set system timer MTIMERCMP register.
  234. * \remarks
  235. * - Compare value is 64bits wide.
  236. * - If compare value is larger than current value timer interrupt generate.
  237. * - Modify the load value or compare value less to clear the interrupt.
  238. * - __get_hart_id function can only be accessed in machine mode, or else exception will occur.
  239. * - \ref SysTimer_GetCompareValue
  240. */
  241. __STATIC_FORCEINLINE void SysTimer_SetCompareValue(rv_counter_t value)
  242. {
  243. #if (defined(CPU_SERIES) && CPU_SERIES == 100)
  244. SysTimer->MTIMERCMP = value;
  245. #else
  246. unsigned long hartid = SysTimer_GetHartID();
  247. SysTimer_SetHartCompareValue(value, hartid);
  248. #endif
  249. }
  250. /**
  251. * \brief Get system timer compare value by hartid
  252. * \details
  253. * This function get the system timer compare value in MTIMERCMP register.
  254. * \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
  255. * \return compare value of system timer MTIMERCMP register.
  256. * \remarks
  257. * - Compare value is 64bits wide.
  258. * - In S-mode, hartid can't be get by using __get_hart_id function, so this api suits S-mode particularly.
  259. * - \ref SysTimer_SetHartCompareValue
  260. */
  261. __STATIC_INLINE rv_counter_t SysTimer_GetHartCompareValue(unsigned long hartid)
  262. {
  263. #if (defined(CPU_SERIES) && CPU_SERIES == 100)
  264. return SysTimer->MTIMERCMP;
  265. #else
  266. if (hartid == 0) {
  267. return SysTimer->MTIMERCMP;
  268. } else {
  269. uint64_t full;
  270. uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MTIMECMP_BASE(hartid));
  271. #if __RISCV_XLEN == 32
  272. // MTIMECMP didn't increase
  273. uint32_t high, low;
  274. high = __LW(addr + 4);
  275. low = __LW(addr);
  276. full = (((uint64_t)high) << 32) | low;
  277. #else
  278. full = __LD(addr);
  279. #endif
  280. return full;
  281. }
  282. #endif
  283. }
  284. /**
  285. * \brief Get system timer compare value in machine mode
  286. * \details
  287. * This function get the system timer compare value in MTIMERCMP register.
  288. * \return compare value of system timer MTIMERCMP register.
  289. * \remarks
  290. * - Compare value is 64bits wide.
  291. * - \ref SysTimer_SetCompareValue
  292. */
  293. __STATIC_FORCEINLINE rv_counter_t SysTimer_GetCompareValue(void)
  294. {
  295. #if (defined(CPU_SERIES) && CPU_SERIES == 100)
  296. return SysTimer->MTIMERCMP;
  297. #else
  298. unsigned long hartid = SysTimer_GetHartID();
  299. return SysTimer_GetHartCompareValue(hartid);
  300. #endif
  301. }
  302. /**
  303. * \brief Enable system timer counter running
  304. * \details
  305. * Enable system timer counter running by clear
  306. * TIMESTOP bit in MTIMECTL register.
  307. */
  308. __STATIC_FORCEINLINE void SysTimer_Start(void)
  309. {
  310. SysTimer->MTIMECTL &= ~(SysTimer_MTIMECTL_TIMESTOP_Msk);
  311. }
  312. /**
  313. * \brief Stop system timer counter running
  314. * \details
  315. * Stop system timer counter running by set
  316. * TIMESTOP bit in MTIMECTL register.
  317. */
  318. __STATIC_FORCEINLINE void SysTimer_Stop(void)
  319. {
  320. SysTimer->MTIMECTL |= SysTimer_MTIMECTL_TIMESTOP_Msk;
  321. }
  322. /**
  323. * \brief Set system timer control value
  324. * \details
  325. * This function set the system timer MTIMECTL register value.
  326. * \param [in] mctl value to set MTIMECTL register
  327. * \remarks
  328. * - Bit TIMESTOP is used to start and stop timer.
  329. * Clear TIMESTOP bit to 0 to start timer, otherwise to stop timer.
  330. * - Bit CMPCLREN is used to enable auto MTIMER clear to zero when MTIMER >= MTIMERCMP.
  331. * Clear CMPCLREN bit to 0 to stop auto clear MTIMER feature, otherwise to enable it.
  332. * - Bit CLKSRC is used to select timer clock source.
  333. * Clear CLKSRC bit to 0 to use *mtime_toggle_a*, otherwise use *core_clk_aon*
  334. * - \ref SysTimer_GetControlValue
  335. */
  336. __STATIC_FORCEINLINE void SysTimer_SetControlValue(uint32_t mctl)
  337. {
  338. SysTimer->MTIMECTL = (mctl & SysTimer_MTIMECTL_Msk);
  339. }
  340. /**
  341. * \brief Get system timer control value
  342. * \details
  343. * This function get the system timer MTIMECTL register value.
  344. * \return MTIMECTL register value
  345. * \remarks
  346. * - \ref SysTimer_SetControlValue
  347. */
  348. __STATIC_FORCEINLINE uint32_t SysTimer_GetControlValue(void)
  349. {
  350. return (SysTimer->MTIMECTL & SysTimer_MTIMECTL_Msk);
  351. }
  352. /**
  353. * \brief Trigger or set software interrupt via system timer by hartid
  354. * \details
  355. * This function set the system timer MSIP bit in MSIP register.
  356. * \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
  357. * \remarks
  358. * - Set system timer MSIP bit and generate a machine mode software interrupt.
  359. * - In S-mode, hartid can't be get by using __get_hart_id function, so this api suite S-mode particularly when MTIME_SRW_CTRL.SRW equal 0.
  360. * - \ref SysTimer_ClearHartSWIRQ
  361. * - \ref SysTimer_GetHartMsipValue
  362. */
  363. __STATIC_FORCEINLINE void SysTimer_SetHartSWIRQ(unsigned long hartid)
  364. {
  365. #if (defined(CPU_SERIES) && CPU_SERIES == 100)
  366. SysTimer->MSIP |= SysTimer_MSIP_MSIP_Msk;
  367. #else
  368. if (hartid == 0) {
  369. SysTimer->MSIP |= SysTimer_MSIP_MSIP_Msk;
  370. } else {
  371. uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MSIP_BASE(hartid));
  372. __SW(addr, SysTimer_MSIP_MSIP_Msk);
  373. }
  374. #endif
  375. }
  376. /**
  377. * \brief Trigger or set software interrupt via system timer in machine mode
  378. * \details
  379. * This function set the system timer MSIP bit in MSIP register.
  380. * \remarks
  381. * - Set system timer MSIP bit and generate a SW interrupt.
  382. * - \ref SysTimer_ClearSWIRQ
  383. * - \ref SysTimer_GetMsipValue
  384. */
  385. __STATIC_FORCEINLINE void SysTimer_SetSWIRQ(void)
  386. {
  387. #if (defined(CPU_SERIES) && CPU_SERIES == 100)
  388. SysTimer->MSIP |= SysTimer_MSIP_MSIP_Msk;
  389. #else
  390. unsigned long hartid = SysTimer_GetHartID();
  391. SysTimer_SetHartSWIRQ(hartid);
  392. #endif
  393. }
  394. /**
  395. * \brief Clear system timer software interrupt pending request by hartid
  396. * \details
  397. * This function clear the system timer MSIP bit in MSIP register.
  398. * \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
  399. * \remarks
  400. * - Clear system timer MSIP bit in MSIP register to clear the software interrupt pending.
  401. * - In S-mode, hartid can't be get by using __get_hart_id function, so this api suits S-mode particularly.
  402. * - \ref SysTimer_SetHartSWIRQ
  403. * - \ref SysTimer_GetHartMsipValue
  404. */
  405. __STATIC_FORCEINLINE void SysTimer_ClearHartSWIRQ(unsigned long hartid)
  406. {
  407. #if (defined(CPU_SERIES) && CPU_SERIES == 100)
  408. SysTimer->MSIP &= ~SysTimer_MSIP_MSIP_Msk;
  409. #else
  410. if (hartid == 0) {
  411. SysTimer->MSIP &= ~SysTimer_MSIP_MSIP_Msk;
  412. } else {
  413. uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MSIP_BASE(hartid));
  414. __SW(addr, 0);
  415. }
  416. #endif
  417. }
  418. /**
  419. * \brief Clear system timer software interrupt pending request in machine mode
  420. * \details
  421. * This function clear the system timer MSIP bit in MSIP register.
  422. * \remarks
  423. * - Clear system timer MSIP bit in MSIP register to clear the software interrupt pending.
  424. * - \ref SysTimer_SetSWIRQ
  425. * - \ref SysTimer_GetMsipValue
  426. */
  427. __STATIC_FORCEINLINE void SysTimer_ClearSWIRQ(void)
  428. {
  429. #if (defined(CPU_SERIES) && CPU_SERIES == 100)
  430. SysTimer->MSIP &= ~SysTimer_MSIP_MSIP_Msk;
  431. #else
  432. unsigned long hartid = SysTimer_GetHartID();
  433. SysTimer_ClearHartSWIRQ(hartid);
  434. #endif
  435. }
  436. /**
  437. * \brief Get system timer MSIP register value by hartid
  438. * \details
  439. * This function get the system timer MSIP register value.
  440. * \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
  441. * \return Value of Timer MSIP register.
  442. * \remarks
  443. * - Bit0 is SW interrupt flag.
  444. * Bit0 is 1 then SW interrupt set. Bit0 is 0 then SW interrupt clear.
  445. * - In S-mode, hartid can't be get by using __get_hart_id function, so this api suits S-mode particularly.
  446. * - \ref SysTimer_SetHartSWIRQ
  447. * - \ref SysTimer_ClearHartSWIRQ
  448. * - \ref SysTimer_SetHartMsipValue
  449. */
  450. __STATIC_FORCEINLINE uint32_t SysTimer_GetHartMsipValue(unsigned long hartid)
  451. {
  452. #if (defined(CPU_SERIES) && CPU_SERIES == 100)
  453. return (uint32_t)(SysTimer->MSIP);
  454. #else
  455. if (hartid == 0) {
  456. return (uint32_t)(SysTimer->MSIP);
  457. } else {
  458. uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MSIP_BASE(hartid));
  459. return __LW(addr);
  460. }
  461. #endif
  462. }
  463. /**
  464. * \brief Get system timer MSIP register value in machine mode
  465. * \details
  466. * This function get the system timer MSIP register value.
  467. * \return Value of Timer MSIP register.
  468. * \remarks
  469. * - Bit0 is SW interrupt flag.
  470. * Bit0 is 1 then SW interrupt set. Bit0 is 0 then SW interrupt clear.
  471. * - \ref SysTimer_SetSWIRQ
  472. * - \ref SysTimer_ClearSWIRQ
  473. * - \ref SysTimer_SetMsipValue
  474. */
  475. __STATIC_FORCEINLINE uint32_t SysTimer_GetMsipValue(void)
  476. {
  477. #if (defined(CPU_SERIES) && CPU_SERIES == 100)
  478. return (uint32_t)(SysTimer->MSIP);
  479. #else
  480. unsigned long hartid = SysTimer_GetHartID();
  481. return SysTimer_GetHartMsipValue(hartid);
  482. #endif
  483. }
  484. /**
  485. * \brief Set system timer MSIP register value by hartid
  486. * \details
  487. * This function set the system timer MSIP register value.
  488. * \param [in] msip value to set MSIP register
  489. * \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
  490. * \remarks
  491. * - In S-mode, hartid can't be get using __get_hart_id function, so this api suits S-mode particularly.
  492. * - \ref SysTimer_GetHartMsipValue
  493. */
  494. __STATIC_FORCEINLINE void SysTimer_SetHartMsipValue(uint32_t msip, unsigned long hartid)
  495. {
  496. #if (defined(CPU_SERIES) && CPU_SERIES == 100)
  497. SysTimer->MSIP = (msip);
  498. #else
  499. if (hartid == 0) {
  500. SysTimer->MSIP = (msip);
  501. } else {
  502. uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MSIP_BASE(hartid));
  503. __SW(addr, msip);
  504. }
  505. #endif
  506. }
  507. /**
  508. * \brief Set system timer MSIP register value in machine mode
  509. * \details
  510. * This function set the system timer MSIP register value.
  511. * \param [in] msip value to set MSIP register
  512. * - \ref SysTimer_GetMsipValue
  513. */
  514. __STATIC_FORCEINLINE void SysTimer_SetMsipValue(uint32_t msip)
  515. {
  516. #if (defined(CPU_SERIES) && CPU_SERIES == 100)
  517. SysTimer->MSIP = (msip);
  518. #else
  519. unsigned long hartid = SysTimer_GetHartID();
  520. SysTimer_SetHartMsipValue(msip, hartid);
  521. #endif
  522. }
  523. #if defined(__SSTC_PRESENT) && (__SSTC_PRESENT == 1)
  524. /**
  525. * \brief Set system timer smode compare value
  526. * \details
  527. * This function set the system timer smode compare value in STIMECMP and STIMECMPH CSR register.
  528. * \param [in] value compare value to set system timer smode compare register.
  529. * \remarks
  530. * - smode timer compare regiser required the SSTC extension
  531. * - smode timer compare value located in stimecmp/stimecmph for rv32 and stimecmp for rv64.
  532. * - If compare value is larger than current value smode timer interrupt generate.
  533. * - Modify the load value or compare value less to clear the interrupt.
  534. * - \ref SysTimer_GetCompareValue_S
  535. */
  536. __STATIC_INLINE void SysTimer_SetCompareValue_S(uint64_t value)
  537. {
  538. #if __RISCV_XLEN == 32
  539. __RV_CSR_WRITE(CSR_STIMECMP, -1U); // prevent load > timecmp
  540. __RV_CSR_WRITE(CSR_STIMECMPH, (uint32_t)(value >> 32));
  541. __RV_CSR_WRITE(CSR_STIMECMP, (uint32_t)value);
  542. #else
  543. __RV_CSR_WRITE(CSR_STIMECMP, value);
  544. #endif
  545. }
  546. /**
  547. * \brief Get system timer smode compare value
  548. * \details
  549. * This function get the system timer smode compare value in STIMERCMP and STIMECMPH CSR register.
  550. * \return compare value of system timer smode compare csr register in 64bit.
  551. * \remarks
  552. * - Compare value is 64bits wide.
  553. * - \ref SysTimer_SetCompareValue_S
  554. */
  555. __STATIC_INLINE uint64_t SysTimer_GetCompareValue_S(void)
  556. {
  557. uint64_t full;
  558. #if __RISCV_XLEN == 32
  559. uint32_t high, low;
  560. high = __RV_CSR_READ(CSR_STIMECMPH);
  561. low = __RV_CSR_READ(CSR_STIMECMP);
  562. full = (((uint64_t)high) << 32) | low;
  563. #else
  564. full = __RV_CSR_READ(CSR_STIMECMP);
  565. #endif
  566. return full;
  567. }
  568. /**
  569. * \brief Trigger or set supervisor mode software interrupt via system timer by hartid
  570. * \details
  571. * This function set the system timer SSIP bit in SSIP register.
  572. * \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
  573. * \remarks
  574. * - Set system timer SSIP bit and generate a supervisor mode software interrupt.
  575. * - \ref SysTimer_ClearHartSWIRQ_S
  576. * - \ref SysTimer_GetHartSsipValue
  577. */
  578. __STATIC_FORCEINLINE void SysTimer_SetHartSWIRQ_S(unsigned long hartid)
  579. {
  580. if (hartid == 0) {
  581. SysTimer->SSIP |= SysTimer_SSIP_SSIP_Msk;
  582. } else {
  583. uint8_t *addr = (uint8_t *)(SysTimer_CLINT_SSIP_BASE(hartid));
  584. __SW(addr, SysTimer_SSIP_SSIP_Msk);
  585. }
  586. }
  587. /**
  588. * \brief Trigger or set supervisor software interrupt via system timer
  589. * \details
  590. * This function set the system timer SSIP bit in SSIP register.
  591. * \remarks
  592. * - Set system timer SSIP bit and generate a supervisor mode SW interrupt.
  593. * - \ref SysTimer_ClearSWIRQ_S
  594. * - \ref SysTimer_GetSsipValue
  595. */
  596. __STATIC_FORCEINLINE void SysTimer_SetSWIRQ_S(void)
  597. {
  598. unsigned long hartid = SysTimer_GetHartID_S();
  599. SysTimer_SetHartSWIRQ_S(hartid);
  600. }
  601. /**
  602. * \brief Clear system timer supervisor mode software interrupt pending request by hartid
  603. * \details
  604. * This function clear the system timer SSIP bit in SSIP register.
  605. * \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
  606. * \remarks
  607. * - Clear system timer SSIP bit in SSIP register to clear the supervisor mode software interrupt pending.
  608. * - \ref SysTimer_SetHartSWIRQ_S
  609. * - \ref SysTimer_GetHartSsipValue
  610. */
  611. __STATIC_FORCEINLINE void SysTimer_ClearHartSWIRQ_S(unsigned long hartid)
  612. {
  613. if (hartid == 0) {
  614. SysTimer->SSIP &= ~SysTimer_SSIP_SSIP_Msk;
  615. } else {
  616. uint8_t *addr = (uint8_t *)(SysTimer_CLINT_SSIP_BASE(hartid));
  617. __SW(addr, 0);
  618. }
  619. }
  620. /**
  621. * \brief Clear system timer supervisor mode software interrupt pending request
  622. * \details
  623. * This function clear the system timer SSIP bit in SSIP register.
  624. * \remarks
  625. * - Clear system timer SSIP bit in SSIP register to clear the supervisor mode software interrupt pending.
  626. * - \ref SysTimer_SetSWIRQ_S
  627. * - \ref SysTimer_GetSsipValue
  628. */
  629. __STATIC_FORCEINLINE void SysTimer_ClearSWIRQ_S(void)
  630. {
  631. unsigned long hartid = SysTimer_GetHartID_S();
  632. SysTimer_ClearHartSWIRQ_S(hartid);
  633. }
  634. /**
  635. * \brief Get system timer SSIP register value by hartid
  636. * \details
  637. * This function get the system timer SSIP register value.
  638. * \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
  639. * \return Value of Timer SSIP register.
  640. * \remarks
  641. * - Bit0 is SW interrupt flag.
  642. * Bit0 is 1 then SW interrupt set. Bit0 is 0 then SW interrupt clear.
  643. * - \ref SysTimer_SetHartSWIRQ_S
  644. * - \ref SysTimer_ClearHartSWIRQ_S
  645. * - \ref SysTimer_SetHartSsipValue
  646. */
  647. __STATIC_FORCEINLINE uint32_t SysTimer_GetHartSsipValue(unsigned long hartid)
  648. {
  649. if (hartid == 0) {
  650. return (uint32_t)(SysTimer->SSIP);
  651. } else {
  652. uint8_t *addr = (uint8_t *)(SysTimer_CLINT_SSIP_BASE(hartid));
  653. return __LW(addr);
  654. }
  655. }
  656. /**
  657. * \brief Get system timer SSIP register value
  658. * \details
  659. * This function get the system timer MSIP register value.
  660. * \return Value of Timer MSIP register.
  661. * \remarks
  662. * - Bit0 is SW interrupt flag.
  663. * Bit0 is 1 then SW interrupt set. Bit0 is 0 then SW interrupt clear.
  664. * - \ref SysTimer_SetSWIRQ_S
  665. * - \ref SysTimer_ClearSWIRQ_S
  666. * - \ref SysTimer_SetSsipValue
  667. */
  668. __STATIC_FORCEINLINE uint32_t SysTimer_GetSsipValue(void)
  669. {
  670. unsigned long hartid = SysTimer_GetHartID_S();
  671. return SysTimer_GetHartSsipValue(hartid);
  672. }
  673. /**
  674. * \brief Set system timer SSIP register value by hartid
  675. * \details
  676. * This function set the system timer SSIP register value.
  677. * \param [in] msip value to set SSIP register
  678. * \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
  679. * \remarks
  680. * - \ref SysTimer_GetHartSsipValue
  681. */
  682. __STATIC_FORCEINLINE void SysTimer_SetHartSsipValue(uint32_t ssip, unsigned long hartid)
  683. {
  684. if (hartid == 0) {
  685. SysTimer->SSIP = (ssip);
  686. } else {
  687. uint8_t *addr = (uint8_t *)(SysTimer_CLINT_SSIP_BASE(hartid));
  688. __SW(addr, ssip);
  689. }
  690. }
  691. /**
  692. * \brief Set system timer SSIP register value
  693. * \details
  694. * This function set the system timer SSIP register value.
  695. * \param [in] msip value to set SSIP register
  696. * - \ref SysTimer_GetSsipValue
  697. */
  698. __STATIC_FORCEINLINE void SysTimer_SetSsipValue(uint32_t ssip)
  699. {
  700. unsigned long hartid = SysTimer_GetHartID();
  701. SysTimer_SetHartSsipValue(ssip, hartid);
  702. }
  703. /**
  704. * \brief send ipi to target hart using Systimer Clint SSIP
  705. * \details
  706. * This function send ipi using clint timer's sSIP register.
  707. * \param [in] hart target hart
  708. */
  709. __STATIC_FORCEINLINE void SysTimer_SendIPI_S(unsigned long hartid)
  710. {
  711. uint8_t *addr = (uint8_t *)(SysTimer_CLINT_SSIP_BASE(hartid));
  712. __SW(addr, 1);
  713. }
  714. /**
  715. * \brief clear ipi to target hart using Systimer Clint SSIP
  716. * \details
  717. * This function clear ipi using clint timer's SSIP register.
  718. * \param [in] hart target hart
  719. */
  720. __STATIC_FORCEINLINE void SysTimer_ClearIPI_S(unsigned long hartid)
  721. {
  722. uint8_t *addr = (uint8_t *)(SysTimer_CLINT_SSIP_BASE(hartid));
  723. __SW(addr, 0);
  724. }
  725. /**
  726. * \brief Enable SSTC access right for supervisor mode
  727. * \details
  728. * This will enable SSTC stimecmp(h) csr register read/write access right in supervisor mode
  729. * and make time(h) csr can be read
  730. * \attention This can be only executed in machine mode
  731. */
  732. __STATIC_FORCEINLINE void SysTimer_EnableSSTC(void)
  733. {
  734. __RV_CSR_SET(CSR_MCOUNTEREN, MCOUNTEREN_TIME);
  735. #if __RISCV_XLEN == 32
  736. __RV_CSR_SET(CSR_MENVCFGH, MENVCFGH_STCE);
  737. #else
  738. __RV_CSR_SET(CSR_MENVCFG, MENVCFG_STCE);
  739. #endif
  740. }
  741. /**
  742. * \brief Disable SSTC stimecmp csr access right for supervisor mode
  743. * \details
  744. * This will disable SSTC stimecmp(h) csr register read/write access right in supervisor mode
  745. * and make time(h) csr can not be read
  746. */
  747. __STATIC_FORCEINLINE void SysTimer_DisableSSTC(void)
  748. {
  749. __RV_CSR_CLEAR(CSR_MCOUNTEREN, MCOUNTEREN_TIME);
  750. #if __RISCV_XLEN == 32
  751. __RV_CSR_CLEAR(CSR_MENVCFGH, MENVCFGH_STCE);
  752. #else
  753. __RV_CSR_CLEAR(CSR_MENVCFG, MENVCFG_STCE);
  754. #endif
  755. }
  756. #endif
  757. /**
  758. * \brief Do software reset request
  759. * \details
  760. * This function will do software reset request through MTIMER
  761. * - Software need to write \ref SysTimer_MSFRST_KEY to generate software reset request
  762. * - The software request flag can be cleared by reset operation to clear
  763. * \remarks
  764. * - The software reset is sent to SoC, SoC need to generate reset signal and send back to Core
  765. * - This function will not return, it will do while(1) to wait the Core reset happened
  766. */
  767. __STATIC_FORCEINLINE void SysTimer_SoftwareReset(void)
  768. {
  769. SysTimer->MSFTRST = SysTimer_MSFRST_KEY;
  770. // will reset cpu, never return
  771. while (1);
  772. }
  773. /**
  774. * \brief send ipi to target hart using Systimer Clint MSIP
  775. * \details
  776. * This function send ipi using clint timer's MSIP register.
  777. * \param [in] hart target hart
  778. */
  779. __STATIC_FORCEINLINE void SysTimer_SendIPI(unsigned long hartid)
  780. {
  781. #if (defined(CPU_SERIES) && CPU_SERIES == 100)
  782. SysTimer->MSIP = 1;
  783. #else
  784. uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MSIP_BASE(hartid));
  785. __SW(addr, 1);
  786. #endif
  787. }
  788. /**
  789. * \brief clear ipi to target hart using Systimer Clint MSIP
  790. * \details
  791. * This function clear ipi using clint timer's MSIP register.
  792. * \param [in] hart target hart
  793. */
  794. __STATIC_FORCEINLINE void SysTimer_ClearIPI(unsigned long hartid)
  795. {
  796. #if (defined(CPU_SERIES) && CPU_SERIES == 100)
  797. SysTimer->MSIP = 0;
  798. #else
  799. uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MSIP_BASE(hartid));
  800. __SW(addr, 0);
  801. #endif
  802. }
  803. /**
  804. * \brief Enable supervisor mode systimer register read/write access right
  805. * \details
  806. * This will make some systimer registers can be accessed in supervisor mode, which is reset state.
  807. * \attention This can be only executed in machine mode
  808. */
  809. __STATIC_FORCEINLINE void SysTimer_EnableSAccess(void)
  810. {
  811. SysTimer->MTIME_SRW_CTRL &= ~SysTimer_MTIME_SRW_CTRL_SRW_Msk;
  812. }
  813. /**
  814. * \brief Disable supervisor mode systimer register read/write access right
  815. * \details
  816. * This will make some systimer registers can not be accessed in supervisor mode.
  817. * \attention This can be only executed in machine mode
  818. */
  819. __STATIC_FORCEINLINE void SysTimer_DisableSAccess(void)
  820. {
  821. SysTimer->MTIME_SRW_CTRL |= SysTimer_MTIME_SRW_CTRL_SRW_Msk;
  822. }
  823. #if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
  824. /**
  825. * \brief System Tick Configuration
  826. * \details Initializes the System Timer and its non-vector interrupt, and starts the System Tick Timer.
  827. *
  828. * In our default implementation, the timer counter will be set to zero, and it will start a timer compare non-vector interrupt
  829. * when it matchs the ticks user set, during the timer interrupt user should reload the system tick using \ref SysTick_Reload function
  830. * or similar function written by user, so it can produce period timer interrupt.
  831. * \param [in] ticks Number of ticks between two interrupts.
  832. * \return 0 Function succeeded.
  833. * \return 1 Function failed.
  834. * \remarks
  835. * - For \ref __NUCLEI_N_REV >= 0x0104, the CMPCLREN bit in MTIMECTL is introduced,
  836. * but we assume that the CMPCLREN bit is set to 0, so MTIMER register will not be
  837. * auto cleared to 0 when MTIMER >= MTIMERCMP.
  838. * - When the variable \ref __Vendor_SysTickConfig is set to 1, then the
  839. * function \ref SysTick_Config is not included.
  840. * - In this case, the file <b><Device>.h</b> must contain a vendor-specific implementation
  841. * of this function.
  842. * - If user need this function to start a period timer interrupt, then in timer interrupt handler
  843. * routine code, user should call \ref SysTick_Reload with ticks to reload the timer.
  844. * - This function only available when __SYSTIMER_PRESENT == 1 and __ECLIC_PRESENT == 1 and __Vendor_SysTickConfig == 0
  845. * \sa
  846. * - \ref SysTimer_SetCompareValue; SysTimer_SetLoadValue
  847. */
  848. __STATIC_INLINE uint32_t SysTick_Config(rv_counter_t ticks)
  849. {
  850. rv_counter_t loadticks = SysTimer_GetLoadValue();
  851. SysTimer_SetCompareValue(ticks + loadticks);
  852. #if defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1)
  853. ECLIC_SetShvIRQ(SysTimer_IRQn, ECLIC_NON_VECTOR_INTERRUPT);
  854. ECLIC_SetLevelIRQ(SysTimer_IRQn, 0);
  855. ECLIC_EnableIRQ(SysTimer_IRQn);
  856. #endif
  857. return (0UL);
  858. }
  859. /**
  860. * \brief System Tick Configuration By hartid
  861. * \details Initializes the System Timer and its non-vector interrupt, and starts the System Tick Timer.
  862. *
  863. * In our default implementation, the timer counter will be set to zero, and it will start a timer compare non-vector interrupt
  864. * when it matchs the ticks user set, during the timer interrupt user should reload the system tick using \ref SysTick_Reload function
  865. * or similar function written by user, so it can produce period timer interrupt.
  866. * \param [in] ticks Number of ticks between two interrupts.
  867. * \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
  868. * \return 0 Function succeeded.
  869. * \return 1 Function failed.
  870. * \remarks
  871. * - For \ref __NUCLEI_N_REV >= 0x0104, the CMPCLREN bit in MTIMECTL is introduced,
  872. * but we assume that the CMPCLREN bit is set to 0, so MTIMER register will not be
  873. * auto cleared to 0 when MTIMER >= MTIMERCMP.
  874. * - When the variable \ref __Vendor_SysTickConfig is set to 1, then the
  875. * function \ref SysTick_Config is not included.
  876. * - In this case, the file <b><Device>.h</b> must contain a vendor-specific implementation
  877. * of this function.
  878. * - If user need this function to start a period timer interrupt, then in timer interrupt handler
  879. * routine code, user should call \ref SysTick_Reload with ticks to reload the timer.
  880. * - This function only available __Vendor_SysTickConfig == 0
  881. * - When ECLIC present, it will set eclic timer interrupt as non-vector mode, and level configured to 0, and enable it
  882. * - In S-mode, hartid can't be get by using __get_hart_id function, so this api suits S-mode particularly.
  883. * \sa
  884. * - \ref SysTimer_SetCompareValue; SysTimer_SetLoadValue
  885. */
  886. __STATIC_INLINE uint32_t SysTick_HartConfig(rv_counter_t ticks, unsigned long hartid)
  887. {
  888. rv_counter_t loadticks = SysTimer_GetLoadValue();
  889. SysTimer_SetHartCompareValue(ticks + loadticks, hartid);
  890. #if defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1)
  891. ECLIC_SetShvIRQ(SysTimer_IRQn, ECLIC_NON_VECTOR_INTERRUPT);
  892. ECLIC_SetLevelIRQ(SysTimer_IRQn, 0);
  893. ECLIC_EnableIRQ(SysTimer_IRQn);
  894. #endif
  895. return (0UL);
  896. }
  897. /**
  898. * \brief System Tick Reload
  899. * \details Reload the System Timer Tick when the MTIMECMP reached TIME value
  900. *
  901. * \param [in] ticks Number of ticks between two interrupts.
  902. * \return 0 Function succeeded.
  903. * \return 1 Function failed.
  904. * \remarks
  905. * - For \ref __NUCLEI_N_REV >= 0x0104, the CMPCLREN bit in MTIMECTL is introduced,
  906. * but for this \ref SysTick_Config function, we assume this CMPCLREN bit is set to 0,
  907. * so in interrupt handler function, user still need to set the MTIMERCMP or MTIMER to reload
  908. * the system tick, if vendor want to use this timer's auto clear feature, they can define
  909. * \ref __Vendor_SysTickConfig to 1, and implement \ref SysTick_Config and \ref SysTick_Reload functions.
  910. * - When the variable \ref __Vendor_SysTickConfig is set to 1, then the
  911. * function \ref SysTick_Reload is not included.
  912. * - In this case, the file <b><Device>.h</b> must contain a vendor-specific implementation
  913. * of this function.
  914. * - This function only available when __SYSTIMER_PRESENT == 1
  915. * - Since the MTIMERCMP value might overflow, if overflowed, MTIMER will be set to 0, and MTIMERCMP set to ticks
  916. * \sa
  917. * - \ref SysTimer_SetCompareValue
  918. * - \ref SysTimer_SetLoadValue
  919. */
  920. __STATIC_INLINE uint32_t SysTick_Reload(rv_counter_t ticks)
  921. {
  922. rv_counter_t cur_ticks = SysTimer_GetLoadValue();
  923. rv_counter_t reload_ticks = ticks + cur_ticks;
  924. SysTimer_SetCompareValue(reload_ticks);
  925. return (0UL);
  926. }
  927. /**
  928. * \brief System Tick Reload By hartid
  929. * \details Reload the System Timer Tick when the MTIMECMP reached TIME value
  930. *
  931. * \param [in] ticks Number of ticks between two interrupts.
  932. * \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
  933. * \return 0 Function succeeded.
  934. * \return 1 Function failed.
  935. * \remarks
  936. * - For \ref __NUCLEI_N_REV >= 0x0104, the CMPCLREN bit in MTIMECTL is introduced,
  937. * but for this \ref SysTick_Config function, we assume this CMPCLREN bit is set to 0,
  938. * so in interrupt handler function, user still need to set the MTIMERCMP or MTIMER to reload
  939. * the system tick, if vendor want to use this timer's auto clear feature, they can define
  940. * \ref __Vendor_SysTickConfig to 1, and implement \ref SysTick_Config and \ref SysTick_Reload functions.
  941. * - When the variable \ref __Vendor_SysTickConfig is set to 1, then the
  942. * function \ref SysTick_Reload is not included.
  943. * - In this case, the file <b><Device>.h</b> must contain a vendor-specific implementation
  944. * of this function.
  945. * - This function only available when __SYSTIMER_PRESENT == 1 and __ECLIC_PRESENT == 1 and __Vendor_SysTickConfig == 0
  946. * - Since the MTIMERCMP value might overflow, if overflowed, MTIMER will be set to 0, and MTIMERCMP set to ticks
  947. * - In S-mode, hartid can't be get by using __get_hart_id function, so this api suits S-mode particularly.
  948. * \sa
  949. * - \ref SysTimer_SetCompareValue
  950. * - \ref SysTimer_SetLoadValue
  951. */
  952. __STATIC_INLINE uint32_t SysTick_HartReload(rv_counter_t ticks, unsigned long hartid)
  953. {
  954. rv_counter_t cur_ticks = SysTimer_GetLoadValue();
  955. rv_counter_t reload_ticks = ticks + cur_ticks;
  956. SysTimer_SetHartCompareValue(reload_ticks, hartid);
  957. return (0UL);
  958. }
  959. #if defined(__SSTC_PRESENT) && (__SSTC_PRESENT == 1)
  960. /**
  961. * \brief System Tick Configuration in supervisor mode
  962. * \details Initializes the system timer supervisor mode interrupt and registered as non-vector interrupt
  963. *
  964. * The smode timecmp csr register will be set to proper value according to the ticks passed
  965. * when it matchs the ticks user set, during the smode timer interrupt user should reload the system tick using \ref SysTick_Reload_S function
  966. * or similar function written by user, so it can produce period smode timer interrupt.
  967. * \param [in] ticks Number of ticks between two interrupts.
  968. * \return 0 Function succeeded.
  969. */
  970. __STATIC_INLINE uint32_t SysTick_Config_S(rv_counter_t ticks)
  971. {
  972. rv_counter_t loadticks = __get_rv_time();
  973. SysTimer_SetCompareValue_S(ticks + loadticks);
  974. #if defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1)
  975. #if defined(__TEE_PRESENT) && (__TEE_PRESENT == 1)
  976. ECLIC_SetShvIRQ_S(SysTimer_S_IRQn, ECLIC_NON_VECTOR_INTERRUPT);
  977. ECLIC_SetLevelIRQ_S(SysTimer_S_IRQn, 0);
  978. ECLIC_EnableIRQ_S(SysTimer_S_IRQn);
  979. #endif
  980. #endif
  981. return (0UL);
  982. }
  983. /**
  984. * \brief System Tick Reload in supervisor mode
  985. * \details Reload the System Timer Tick when the STIMECMP CSR reached TIME value
  986. *
  987. * \param [in] ticks Number of ticks between two interrupts.
  988. * \return 0 Function succeeded.
  989. * \return 1 Function failed.
  990. */
  991. __STATIC_INLINE uint32_t SysTick_Reload_S(rv_counter_t ticks)
  992. {
  993. rv_counter_t cur_ticks = __get_rv_time();
  994. rv_counter_t reload_ticks = ticks + cur_ticks;
  995. SysTimer_SetCompareValue_S(reload_ticks);
  996. return (0UL);
  997. }
  998. #endif
  999. #endif /* defined(__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) */
  1000. /** @} */ /* End of Doxygen Group NMSIS_Core_SysTimer */
  1001. #endif /* defined(__SYSTIMER_PRESENT) && (__SYSTIMER_PRESENT == 1) */
  1002. #ifdef __cplusplus
  1003. }
  1004. #endif
  1005. #endif /* __CORE_FEATURE_TIMER_H__ */