core_feature_timer.h 38 KB

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