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: Define whether Private System Timer is present or not.
27 * * 0: Not present
28 * * 1: Present
29 * 2. __SYSTIMER_BASEADDR: Define the base address of the System Timer.
30 */
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34
35 #if defined(__SYSTIMER_PRESENT) && (__SYSTIMER_PRESENT == 1)
36 /**
37 * \defgroup NMSIS_Core_SysTimer_Registers Register Define and Type Definitions Of System Timer
38 * \ingroup NMSIS_Core_Registers
39 * \brief Type definitions and defines for system timer registers.
40 *
41 * @{
42 */
43 /**
44 * \brief Structure type to access the System Timer (SysTimer).
45 * \details
46 * Structure definition to access the system timer(SysTimer).
47 * \remarks
48 * - MSFTRST register is introduced in Nuclei N Core version 1.3(\ref __NUCLEI_N_REV >= 0x0103)
49 * - MSTOP register is renamed to MTIMECTL register in Nuclei N Core version 1.4(\ref __NUCLEI_N_REV >= 0x0104)
50 * - CMPCLREN and CLKSRC bit in MTIMECTL register is introduced in Nuclei N Core version 1.4(\ref __NUCLEI_N_REV >= 0x0104)
51 */
52 typedef struct {
53 __IOM uint64_t MTIMER; /*!< Offset: 0x000 (R/W) System Timer current value 64bits Register */
54 __IOM uint64_t MTIMERCMP; /*!< Offset: 0x008 (R/W) System Timer compare Value 64bits Register */
55 __IOM uint32_t RESERVED0[0x3F8]; /*!< Offset: 0x010 - 0xFEC Reserved */
56 __IOM uint32_t MSFTRST; /*!< Offset: 0xFF0 (R/W) System Timer Software Core Reset Register */
57 __IOM uint32_t RESERVED1; /*!< Offset: 0xFF4 Reserved */
58 __IOM uint32_t MTIMECTL; /*!< Offset: 0xFF8 (R/W) System Timer Control Register, previously MSTOP register */
59 __IOM uint32_t MSIP; /*!< Offset: 0xFFC (R/W) System Timer SW interrupt Register */
60 } SysTimer_Type;
61
62 /* Timer Control / Status Register Definitions */
63 #define SysTimer_MTIMECTL_TIMESTOP_Pos 0U /*!< SysTick Timer MTIMECTL: TIMESTOP bit Position */
64 #define SysTimer_MTIMECTL_TIMESTOP_Msk (1UL << SysTimer_MTIMECTL_TIMESTOP_Pos) /*!< SysTick Timer MTIMECTL: TIMESTOP Mask */
65 #define SysTimer_MTIMECTL_CMPCLREN_Pos 1U /*!< SysTick Timer MTIMECTL: CMPCLREN bit Position */
66 #define SysTimer_MTIMECTL_CMPCLREN_Msk (1UL << SysTimer_MTIMECTL_CMPCLREN_Pos) /*!< SysTick Timer MTIMECTL: CMPCLREN Mask */
67 #define SysTimer_MTIMECTL_CLKSRC_Pos 2U /*!< SysTick Timer MTIMECTL: CLKSRC bit Position */
68 #define SysTimer_MTIMECTL_CLKSRC_Msk (1UL << SysTimer_MTIMECTL_CLKSRC_Pos) /*!< SysTick Timer MTIMECTL: CLKSRC Mask */
69
70 #define SysTimer_MSIP_MSIP_Pos 0U /*!< SysTick Timer MSIP: MSIP bit Position */
71 #define SysTimer_MSIP_MSIP_Msk (1UL << SysTimer_MSIP_MSIP_Pos) /*!< SysTick Timer MSIP: MSIP Mask */
72
73 #define SysTimer_MTIMER_Msk (0xFFFFFFFFFFFFFFFFULL) /*!< SysTick Timer MTIMER value Mask */
74 #define SysTimer_MTIMERCMP_Msk (0xFFFFFFFFFFFFFFFFULL) /*!< SysTick Timer MTIMERCMP value Mask */
75 #define SysTimer_MTIMECTL_Msk (0xFFFFFFFFUL) /*!< SysTick Timer MTIMECTL/MSTOP value Mask */
76 #define SysTimer_MSIP_Msk (0xFFFFFFFFUL) /*!< SysTick Timer MSIP value Mask */
77 #define SysTimer_MSFTRST_Msk (0xFFFFFFFFUL) /*!< SysTick Timer MSFTRST value Mask */
78
79 #define SysTimer_MSFRST_KEY (0x80000A5FUL) /*!< SysTick Timer Software Reset Request Key */
80
81 #ifndef __SYSTIMER_BASEADDR
82 /* Base address of SYSTIMER(__SYSTIMER_BASEADDR) should be defined in <Device.h> */
83 #error "__SYSTIMER_BASEADDR is not defined, please check!"
84 #endif
85 /* System Timer Memory mapping of Device */
86 #define SysTimer_BASE __SYSTIMER_BASEADDR /*!< SysTick Base Address */
87 #define SysTimer ((SysTimer_Type *) SysTimer_BASE) /*!< SysTick configuration struct */
88 /** @} */ /* end of group NMSIS_Core_SysTimer_Registers */
89
90 /* ################################## SysTimer function ############################################ */
91 /**
92 * \defgroup NMSIS_Core_SysTimer SysTimer Functions
93 * \brief Functions that configure the Core System Timer.
94 * @{
95 */
96 /**
97 * \brief Set system timer load value
98 * \details
99 * This function set the system timer load value in MTIMER register.
100 * \param [in] value value to set system timer MTIMER register.
101 * \remarks
102 * - Load value is 64bits wide.
103 * - \ref SysTimer_GetLoadValue
104 */
SysTimer_SetLoadValue(uint64_t value)105 __STATIC_FORCEINLINE void SysTimer_SetLoadValue(uint64_t value)
106 {
107 SysTimer->MTIMER = value;
108 }
109
110 /**
111 * \brief Get system timer load value
112 * \details
113 * This function get the system timer current value in MTIMER register.
114 * \return current value(64bit) of system timer MTIMER register.
115 * \remarks
116 * - Load value is 64bits wide.
117 * - \ref SysTimer_SetLoadValue
118 */
SysTimer_GetLoadValue(void)119 __STATIC_FORCEINLINE uint64_t SysTimer_GetLoadValue(void)
120 {
121 return SysTimer->MTIMER;
122 }
123
124 /**
125 * \brief Set system timer compare value
126 * \details
127 * This function set the system Timer compare value in MTIMERCMP register.
128 * \param [in] value compare value to set system timer MTIMERCMP register.
129 * \remarks
130 * - Compare value is 64bits wide.
131 * - If compare value is larger than current value timer interrupt generate.
132 * - Modify the load value or compare value less to clear the interrupt.
133 * - \ref SysTimer_GetCompareValue
134 */
SysTimer_SetCompareValue(uint64_t value)135 __STATIC_FORCEINLINE void SysTimer_SetCompareValue(uint64_t value)
136 {
137 SysTimer->MTIMERCMP = value;
138 }
139
140 /**
141 * \brief Get system timer compare value
142 * \details
143 * This function get the system timer compare value in MTIMERCMP register.
144 * \return compare value of system timer MTIMERCMP register.
145 * \remarks
146 * - Compare value is 64bits wide.
147 * - \ref SysTimer_SetCompareValue
148 */
SysTimer_GetCompareValue(void)149 __STATIC_FORCEINLINE uint64_t SysTimer_GetCompareValue(void)
150 {
151 return SysTimer->MTIMERCMP;
152 }
153
154 /**
155 * \brief Enable system timer counter running
156 * \details
157 * Enable system timer counter running by clear
158 * TIMESTOP bit in MTIMECTL register.
159 */
SysTimer_Start(void)160 __STATIC_FORCEINLINE void SysTimer_Start(void)
161 {
162 SysTimer->MTIMECTL &= ~(SysTimer_MTIMECTL_TIMESTOP_Msk);
163 }
164
165 /**
166 * \brief Stop system timer counter running
167 * \details
168 * Stop system timer counter running by set
169 * TIMESTOP bit in MTIMECTL register.
170 */
SysTimer_Stop(void)171 __STATIC_FORCEINLINE void SysTimer_Stop(void)
172 {
173 SysTimer->MTIMECTL |= SysTimer_MTIMECTL_TIMESTOP_Msk;
174 }
175
176 /**
177 * \brief Set system timer control value
178 * \details
179 * This function set the system timer MTIMECTL register value.
180 * \param [in] mctl value to set MTIMECTL register
181 * \remarks
182 * - Bit TIMESTOP is used to start and stop timer.
183 * Clear TIMESTOP bit to 0 to start timer, otherwise to stop timer.
184 * - Bit CMPCLREN is used to enable auto MTIMER clear to zero when MTIMER >= MTIMERCMP.
185 * Clear CMPCLREN bit to 0 to stop auto clear MTIMER feature, otherwise to enable it.
186 * - Bit CLKSRC is used to select timer clock source.
187 * Clear CLKSRC bit to 0 to use *mtime_toggle_a*, otherwise use *core_clk_aon*
188 * - \ref SysTimer_GetControlValue
189 */
SysTimer_SetControlValue(uint32_t mctl)190 __STATIC_FORCEINLINE void SysTimer_SetControlValue(uint32_t mctl)
191 {
192 SysTimer->MTIMECTL = (mctl & SysTimer_MTIMECTL_Msk);
193 }
194
195 /**
196 * \brief Get system timer control value
197 * \details
198 * This function get the system timer MTIMECTL register value.
199 * \return MTIMECTL register value
200 * \remarks
201 * - \ref SysTimer_SetControlValue
202 */
SysTimer_GetControlValue(void)203 __STATIC_FORCEINLINE uint32_t SysTimer_GetControlValue(void)
204 {
205 return (SysTimer->MTIMECTL & SysTimer_MTIMECTL_Msk);
206 }
207
208 /**
209 * \brief Trigger or set software interrupt via system timer
210 * \details
211 * This function set the system timer MSIP bit in MSIP register.
212 * \remarks
213 * - Set system timer MSIP bit and generate a SW interrupt.
214 * - \ref SysTimer_ClearSWIRQ
215 * - \ref SysTimer_GetMsipValue
216 */
SysTimer_SetSWIRQ(void)217 __STATIC_FORCEINLINE void SysTimer_SetSWIRQ(void)
218 {
219 SysTimer->MSIP |= SysTimer_MSIP_MSIP_Msk;
220 }
221
222 /**
223 * \brief Clear system timer software interrupt pending request
224 * \details
225 * This function clear the system timer MSIP bit in MSIP register.
226 * \remarks
227 * - Clear system timer MSIP bit in MSIP register to clear the software interrupt pending.
228 * - \ref SysTimer_SetSWIRQ
229 * - \ref SysTimer_GetMsipValue
230 */
SysTimer_ClearSWIRQ(void)231 __STATIC_FORCEINLINE void SysTimer_ClearSWIRQ(void)
232 {
233 SysTimer->MSIP &= ~SysTimer_MSIP_MSIP_Msk;
234 }
235
236 /**
237 * \brief Get system timer MSIP register value
238 * \details
239 * This function get the system timer MSIP register value.
240 * \return Value of Timer MSIP register.
241 * \remarks
242 * - Bit0 is SW interrupt flag.
243 * Bit0 is 1 then SW interrupt set. Bit0 is 0 then SW interrupt clear.
244 * - \ref SysTimer_SetSWIRQ
245 * - \ref SysTimer_ClearSWIRQ
246 */
SysTimer_GetMsipValue(void)247 __STATIC_FORCEINLINE uint32_t SysTimer_GetMsipValue(void)
248 {
249 return (uint32_t)(SysTimer->MSIP & SysTimer_MSIP_Msk);
250 }
251
252 /**
253 * \brief Set system timer MSIP register value
254 * \details
255 * This function set the system timer MSIP register value.
256 * \param [in] msip value to set MSIP register
257 */
SysTimer_SetMsipValue(uint32_t msip)258 __STATIC_FORCEINLINE void SysTimer_SetMsipValue(uint32_t msip)
259 {
260 SysTimer->MSIP = (msip & SysTimer_MSIP_Msk);
261 }
262
263 /**
264 * \brief Do software reset request
265 * \details
266 * This function will do software reset request through MTIMER
267 * - Software need to write \ref SysTimer_MSFRST_KEY to generate software reset request
268 * - The software request flag can be cleared by reset operation to clear
269 * \remarks
270 * - The software reset is sent to SoC, SoC need to generate reset signal and send back to Core
271 * - This function will not return, it will do while(1) to wait the Core reset happened
272 */
SysTimer_SoftwareReset(void)273 __STATIC_FORCEINLINE void SysTimer_SoftwareReset(void)
274 {
275 SysTimer->MSFTRST = SysTimer_MSFRST_KEY;
276 while(1);
277 }
278
279 #if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) && defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1)
280 /**
281 * \brief System Tick Configuration
282 * \details Initializes the System Timer and its non-vector interrupt, and starts the System Tick Timer.
283 *
284 * In our default implementation, the timer counter will be set to zero, and it will start a timer compare non-vector interrupt
285 * when it matches the ticks user set, during the timer interrupt user should reload the system tick using \ref SysTick_Reload function
286 * or similar function written by user, so it can produce period timer interrupt.
287 * \param [in] ticks Number of ticks between two interrupts.
288 * \return 0 Function succeeded.
289 * \return 1 Function failed.
290 * \remarks
291 * - For \ref __NUCLEI_N_REV >= 0x0104, the CMPCLREN bit in MTIMECTL is introduced,
292 * but we assume that the CMPCLREN bit is set to 0, so MTIMER register will not be
293 * auto cleared to 0 when MTIMER >= MTIMERCMP.
294 * - When the variable \ref __Vendor_SysTickConfig is set to 1, then the
295 * function \ref SysTick_Config is not included.
296 * - In this case, the file <b><Device>.h</b> must contain a vendor-specific implementation
297 * of this function.
298 * - If user need this function to start a period timer interrupt, then in timer interrupt handler
299 * routine code, user should call \ref SysTick_Reload with ticks to reload the timer.
300 * - This function only available when __SYSTIMER_PRESENT == 1 and __ECLIC_PRESENT == 1 and __Vendor_SysTickConfig == 0
301 * \sa
302 * - \ref SysTimer_SetCompareValue; SysTimer_SetLoadValue
303 */
SysTick_Config(uint64_t ticks)304 __STATIC_INLINE uint32_t SysTick_Config(uint64_t ticks)
305 {
306 SysTimer_SetLoadValue(0);
307 SysTimer_SetCompareValue(ticks);
308 ECLIC_SetShvIRQ(SysTimer_IRQn, ECLIC_NON_VECTOR_INTERRUPT);
309 ECLIC_SetLevelIRQ(SysTimer_IRQn, 0);
310 ECLIC_EnableIRQ(SysTimer_IRQn);
311 return (0UL);
312 }
313
314 /**
315 * \brief System Tick Reload
316 * \details Reload the System Timer Tick when the MTIMECMP reached TIME value
317 *
318 * \param [in] ticks Number of ticks between two interrupts.
319 * \return 0 Function succeeded.
320 * \return 1 Function failed.
321 * \remarks
322 * - For \ref __NUCLEI_N_REV >= 0x0104, the CMPCLREN bit in MTIMECTL is introduced,
323 * but for this \ref SysTick_Config function, we assume this CMPCLREN bit is set to 0,
324 * so in interrupt handler function, user still need to set the MTIMERCMP or MTIMER to reload
325 * the system tick, if vendor want to use this timer's auto clear feature, they can define
326 * \ref __Vendor_SysTickConfig to 1, and implement \ref SysTick_Config and \ref SysTick_Reload functions.
327 * - When the variable \ref __Vendor_SysTickConfig is set to 1, then the
328 * function \ref SysTick_Reload is not included.
329 * - In this case, the file <b><Device>.h</b> must contain a vendor-specific implementation
330 * of this function.
331 * - This function only available when __SYSTIMER_PRESENT == 1 and __ECLIC_PRESENT == 1 and __Vendor_SysTickConfig == 0
332 * - Since the MTIMERCMP value might overflow, if overflowed, MTIMER will be set to 0, and MTIMERCMP set to ticks
333 * \sa
334 * - \ref SysTimer_SetCompareValue
335 * - \ref SysTimer_SetLoadValue
336 */
SysTick_Reload(uint64_t ticks)337 __STATIC_FORCEINLINE uint32_t SysTick_Reload(uint64_t ticks)
338 {
339 uint64_t cur_ticks = SysTimer->MTIMER;
340 uint64_t reload_ticks = ticks + cur_ticks;
341
342 if (__USUALLY(reload_ticks > cur_ticks)) {
343 SysTimer->MTIMERCMP = reload_ticks;
344 } else {
345 /* When added the ticks value, then the MTIMERCMP < TIMER,
346 * which means the MTIMERCMP is overflowed,
347 * so we need to reset the counter to zero */
348 SysTimer->MTIMER = 0;
349 SysTimer->MTIMERCMP = ticks;
350 }
351
352 return (0UL);
353 }
354
355 #endif /* defined(__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) */
356 /** @} */ /* End of Doxygen Group NMSIS_Core_SysTimer */
357
358 #endif /* defined(__SYSTIMER_PRESENT) && (__SYSTIMER_PRESENT == 1) */
359
360 #ifdef __cplusplus
361 }
362 #endif
363 #endif /** __CORE_FEATURE_TIMER_H__ */
364
365