1 /*******************************************************************************
2 * @file rsi_timers.h
3 *******************************************************************************
4 * # License
5 * <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
6 *******************************************************************************
7 *
8 * SPDX-License-Identifier: Zlib
9 *
10 * The licensor of this software is Silicon Laboratories Inc.
11 *
12 * This software is provided 'as-is', without any express or implied
13 * warranty. In no event will the authors be held liable for any damages
14 * arising from the use of this software.
15 *
16 * Permission is granted to anyone to use this software for any purpose,
17 * including commercial applications, and to alter it and redistribute it
18 * freely, subject to the following restrictions:
19 *
20 * 1. The origin of this software must not be misrepresented; you must not
21 * claim that you wrote the original software. If you use this software
22 * in a product, an acknowledgment in the product documentation would be
23 * appreciated but is not required.
24 * 2. Altered source versions must be plainly marked as such, and must not be
25 * misrepresented as being the original software.
26 * 3. This notice may not be removed or altered from any source distribution.
27 *
28 ******************************************************************************/
29
30 //Include Files
31
32 #include "rsi_ccp_common.h"
33 #include "rsi_error.h"
34
35 #ifndef RSI_TIMERS_H
36 #define RSI_TIMERS_H
37
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41
42 // LOCAL OR GLOBAL DEFINES
43
44 #define RSI_TIMERS_API_VERSION RSI_DRIVER_VERSION_MAJOR_MINOR(2, 00) // API version 0.1
45 #define RSI_TIMERS_DRV_VERSION RSI_DRIVER_VERSION_MAJOR_MINOR(00, 01) // driver version 0.1
46
47 #define MICRO_SEC_MODE 1
48 #define _256_MICRO_SEC_MODE 2
49 #define COUNTER_DOWN_MODE 0
50
51 // TIMERS Events
52 #define RSI_TIMERS_EVENT_TIMER0_TIMEOUT (1UL << 0) // Timer0 timeout interrupt
53 #define RSI_TIMERS_EVENT_TIMER1_TIMEOUT (1UL << 1) // Timer1 timeout interrupt
54 #define RSI_TIMERS_EVENT_TIMER2_TIMEOUT (1UL << 2) // Timer2 timeout interrupt
55 #define RSI_TIMERS_EVENT_TIMER3_TIMEOUT (1UL << 3) // Timer3 timeout interrupt
56
57 #define TIMER_MODE 0x18
58
59 // Example defines
60 #define TIMER_0 0
61 #define TIMER_1 1
62 #define TIMER_2 2
63 #define TIMER_3 3
64
65 #define ULP_TIMER_RF_REF_CLK 0
66 #define ULP_TIMER_ULP_32KHZ_RO_CLK 1
67 #define ULP_TIMER_ULP_32KHZ_RC_CLK 2
68 #define ULP_TIMER_ULP_32KHZ_XTAL_CLK 3
69 #define ULP_TIMER_ULP_MHZ_RC_CLK 4
70 #define ULP_TIMER_ULP_20MHZ_RO_CLK 5
71 #define ULP_TIMER_SOC_CLK 6
72
73 #define ULP_TIMER_CLK_DIV_FACT 0
74
75 #define PERIODIC_TIMER 1
76 #define ONESHOT_TIMER 0
77
78 typedef TIMERS_Type RSI_TIMERS_T;
79
80 // brief TIMERS Driver Capabilities.
81 typedef struct {
82 unsigned int timerCount : 4; // Number of Timers
83 unsigned int microSecMode : 1; // supports Micro second mode
84 } RSI_TIMERS_CAPABILITIES_T;
85
86 /// @brief Enumeration to represent ulp-timer direction
87 typedef enum {
88 DOWN_COUNTER, ///< For ULP Timer up-counting direction
89 UP_COUNTER, ///< For ULP Timer down-counting direction
90 LAST_DIRECTION, ///< Last member of enum for validation
91 } ulp_timer_dir_t;
92
93 /*===================================================*/
94 /**
95 * @fn rsi_error_t RSI_TIMERS_SetDirection(RSI_TIMERS_T *pTIMER, uint8_t timerNum, boolean_t countDir)
96 * @brief This API is used to set direction of the timer
97 * @param[in] pTIMER : Pointer to the TIMERS instance register area
98 * @param[in] timerNum : Timer number(0 to 3)
99 * @param[in] countDir : counter direction
100 * - \ref UP_COUNTER
101 * - \ref DOWN_COUNTER
102 * @return return the timer error code
103 */
RSI_TIMERS_SetDirection(RSI_TIMERS_T * pTIMER,uint8_t timerNum,ulp_timer_dir_t countDir)104 STATIC INLINE rsi_error_t RSI_TIMERS_SetDirection(RSI_TIMERS_T *pTIMER, uint8_t timerNum, ulp_timer_dir_t countDir)
105 {
106 if (timerNum <= TIMER_3) {
107 if (countDir == UP_COUNTER) {
108 pTIMER->MATCH_CTRL[timerNum].MCUULP_TMR_CNTRL_b.COUNTER_UP = ENABLE;
109 } else if (countDir == DOWN_COUNTER) {
110 pTIMER->MATCH_CTRL[timerNum].MCUULP_TMR_CNTRL_b.COUNTER_UP = DISABLE;
111 } else {
112 return ERROR_INVAL_COUNTER_DIR;
113 }
114 } else {
115 return ERROR_INVAL_TIMER_NUM;
116 }
117 return RSI_OK;
118 }
119
120 /*===================================================*/
121 /**
122 * @fn uint32_t RSI_TIMERS_getDirection(const RSI_TIMERS_T *pTIMER, uint8_t timerNum)
123 * @brief This API is used to get direction of the timer
124 * @param[in] pTIMER : Pointer to the TIMERS instance register area
125 * @param[in] timerNum : Timer number(0 to 3)
126 *
127 * @return countDir : counter direction
128 * - 1 for UP_COUNTER
129 * - 0 for DOWN_COUNTER
130 */
RSI_TIMERS_getDirection(const RSI_TIMERS_T * pTIMER,uint8_t timerNum)131 STATIC INLINE uint32_t RSI_TIMERS_getDirection(const RSI_TIMERS_T *pTIMER, uint8_t timerNum)
132 {
133 uint8_t counterDir;
134 if (timerNum <= TIMER_3) {
135 counterDir = pTIMER->MATCH_CTRL[timerNum].MCUULP_TMR_CNTRL_b.COUNTER_UP;
136 return counterDir;
137 } else {
138 return ERROR_INVAL_TIMER_NUM;
139 }
140 }
141
142 /*===================================================*/
143 /**
144 * @fn uint32_t RSI_TIMERS_GetTimerMode(const RSI_TIMERS_T *pTIMER, uint8_t timerNum)
145 * @brief This API is used to get the mode of timer
146 * @param[in] pTIMER : Pointer to the TIMERS instance register area
147 * @param[in] timerNum : Timer number(0 to 3)
148 * @return return the type of timer if valid timer else error code
149 */
RSI_TIMERS_GetTimerMode(const RSI_TIMERS_T * pTIMER,uint8_t timerNum)150 STATIC INLINE uint32_t RSI_TIMERS_GetTimerMode(const RSI_TIMERS_T *pTIMER, uint8_t timerNum)
151 {
152 if (timerNum <= TIMER_3) {
153 return (pTIMER->MATCH_CTRL[timerNum].MCUULP_TMR_CNTRL_b.TMR_MODE);
154 } else {
155 return ERROR_INVAL_TIMER_NUM;
156 }
157 }
158 /*===================================================*/
159 /**
160 * @fn rsi_error_t RSI_TIMERS_TimerStart(RSI_TIMERS_T *pTIMER, uint8_t timerNum)
161 * @brief This API is used to start the timer
162 * @param[in] pTIMER : Pointer to the TIMERS instance register area
163 * @param[in] timerNum : Timer number(0 to 3)
164 * @return return the timer error code
165 */
RSI_TIMERS_TimerStart(RSI_TIMERS_T * pTIMER,uint8_t timerNum)166 STATIC INLINE rsi_error_t RSI_TIMERS_TimerStart(RSI_TIMERS_T *pTIMER, uint8_t timerNum)
167 {
168 if (timerNum <= TIMER_3) {
169 pTIMER->MATCH_CTRL[timerNum].MCUULP_TMR_CNTRL_b.TMR_START = ENABLE;
170 } else {
171 return ERROR_INVAL_TIMER_NUM;
172 }
173 return RSI_OK;
174 }
175
176 /*===================================================*/
177 /**
178 * @fn rsi_error_t RSI_TIMERS_TimerStop(RSI_TIMERS_T *pTIMER, uint8_t timerNum)
179 * @brief This API is used to stop the timer
180 * @param[in] pTIMER : Pointer to the TIMERS instance register area
181 * @param[in] timerNum : Timer number(0 to 3)
182 * @return return the timer error code
183 */
RSI_TIMERS_TimerStop(RSI_TIMERS_T * pTIMER,uint8_t timerNum)184 STATIC INLINE rsi_error_t RSI_TIMERS_TimerStop(RSI_TIMERS_T *pTIMER, uint8_t timerNum)
185 {
186 if (timerNum <= TIMER_3) {
187 pTIMER->MATCH_CTRL[timerNum].MCUULP_TMR_CNTRL_b.TMR_STOP = ENABLE;
188 } else {
189 return ERROR_INVAL_TIMER_NUM;
190 }
191 return RSI_OK;
192 }
193
194 /*===================================================*/
195 /**
196 * @fn rsi_error_t RSI_TIMERS_InterruptEnable(RSI_TIMERS_T *pTIMER , uint8_t timerNum)
197 * @brief This API is used to enable the timer interrupt
198 * @param[in] pTIMER : Pointer to the TIMERS instance register area
199 * @param[in] timerNum : Timer number(0 to 3)
200 * @return return the timer error code
201 */
RSI_TIMERS_InterruptEnable(RSI_TIMERS_T * pTIMER,uint8_t timerNum)202 STATIC INLINE rsi_error_t RSI_TIMERS_InterruptEnable(RSI_TIMERS_T *pTIMER, uint8_t timerNum)
203 {
204 if (timerNum <= TIMER_3) {
205 pTIMER->MATCH_CTRL[timerNum].MCUULP_TMR_CNTRL_b.TMR_INTR_ENABLE = ENABLE;
206 } else {
207 return ERROR_INVAL_TIMER_NUM;
208 }
209 return RSI_OK;
210 }
211
212 /*===================================================*/
213 /**
214 * @fn rsi_error_t RSI_TIMERS_InterruptDisable(RSI_TIMERS_T *pTIMER , uint8_t timerNum)
215 * @brief This API is used to disable the timer interrupt
216 * @param[in] pTIMER : Pointer to the TIMERS instance register area
217 * @param[in] timerNum : Timer number(0 to 3)
218 * @return return the timer error code
219 */
RSI_TIMERS_InterruptDisable(RSI_TIMERS_T * pTIMER,uint8_t timerNum)220 STATIC INLINE rsi_error_t RSI_TIMERS_InterruptDisable(RSI_TIMERS_T *pTIMER, uint8_t timerNum)
221 {
222 if (timerNum <= TIMER_3) {
223 pTIMER->MATCH_CTRL[timerNum].MCUULP_TMR_CNTRL_b.TMR_INTR_ENABLE = DISABLE;
224 } else {
225 return ERROR_INVAL_TIMER_NUM;
226 }
227 return RSI_OK;
228 }
229
230 /*===================================================*/
231 /**
232 * @fn rsi_error_t RSI_TIMERS_InterruptClear(RSI_TIMERS_T *pTIMER , uint8_t timerNum)
233 * @brief This API is used to clear the timer interrupt
234 * @param[in] pTIMER : Pointer to the TIMERS instance register area
235 * @param[in] timerNum : Timer number(0 to 3)
236 * @return return the timer error code
237 */
RSI_TIMERS_InterruptClear(RSI_TIMERS_T * pTIMER,uint8_t timerNum)238 STATIC INLINE rsi_error_t RSI_TIMERS_InterruptClear(RSI_TIMERS_T *pTIMER, uint8_t timerNum)
239 {
240 if (timerNum <= TIMER_3) {
241 pTIMER->MATCH_CTRL[timerNum].MCUULP_TMR_CNTRL_b.TMR_INTR_CLR = ENABLE;
242 } else {
243 return ERROR_INVAL_TIMER_NUM;
244 }
245 return RSI_OK;
246 }
247
248 /*===================================================*/
249 /**
250 * @fn rsi_error_t RSI_TIMERS_SetMatch( RSI_TIMERS_T *pTIMER, uint8_t timerNum, uint32_t match)
251 * @brief This API is used to disable the timer interrupt
252 * @param[in] pTIMER : Pointer to the TIMERS instance register area
253 * @param[in] timerNum : Timer number(0 to 3)
254 * @param[in] match : delay time
255 * @return return the timer error code
256 */
RSI_TIMERS_SetMatch(RSI_TIMERS_T * pTIMER,uint8_t timerNum,uint32_t match)257 STATIC INLINE rsi_error_t RSI_TIMERS_SetMatch(RSI_TIMERS_T *pTIMER, uint8_t timerNum, uint32_t match)
258 {
259 if (timerNum <= TIMER_3) {
260 pTIMER->MATCH_CTRL[timerNum].MCUULP_TMR_MATCH = match;
261 } else {
262 return ERROR_INVAL_TIMER_NUM;
263 }
264 return RSI_OK;
265 }
266
267 /*===================================================*/
268 /**
269 * @fn rsi_error_t RSI_TIMERS_InterruptStatus(const RSI_TIMERS_T *pTIMER , uint8_t timerNum)
270 * @brief This API is used to get the timer interrupt status
271 * @param[in] pTIMER : Pointer to the TIMERS instance register area
272 * @param[in] timerNum : Timer number(0 to 3)
273 * @return return the timer interrupt status if valid timer else 0.
274 */
RSI_TIMERS_InterruptStatus(const RSI_TIMERS_T * pTIMER,uint8_t timerNum)275 STATIC INLINE uint8_t RSI_TIMERS_InterruptStatus(const RSI_TIMERS_T *pTIMER, uint8_t timerNum)
276 {
277 if (timerNum <= TIMER_3) {
278 return (uint8_t)(pTIMER->MCUULP_TMR_INTR_STAT & (1 << timerNum));
279 } else {
280 return 0;
281 }
282 }
283
284 /*===================================================*/
285 /**
286 * @fn rsi_error_t RSI_TIMERS_SetTimerType( RSI_TIMERS_T *pTIMER, uint8_t timerType, uint8_t timerNum)
287 * @brief This API is used to set the timer type
288 * @param[in] pTIMER : Pointer to the TIMERS instance register area
289 * @param[in] timerType : timer type
290 * - \ref MICRO_SEC_MODE
291 * - \ref _256_MICRO_SEC_MODE
292 * - \ref COUNTER_DOWN_MODE
293 * @param[in] timerNum : Timer number(0 to 3)
294 * @return return the timer error code
295 */
RSI_TIMERS_SetTimerType(RSI_TIMERS_T * pTIMER,uint8_t timerType,uint8_t timerNum)296 STATIC INLINE rsi_error_t RSI_TIMERS_SetTimerType(RSI_TIMERS_T *pTIMER, uint8_t timerType, uint8_t timerNum)
297 {
298 if (timerNum <= TIMER_3) {
299 if ((timerType == MICRO_SEC_MODE) || (timerType == _256_MICRO_SEC_MODE) || (timerType == COUNTER_DOWN_MODE)) {
300 pTIMER->MATCH_CTRL[timerNum].MCUULP_TMR_CNTRL_b.TMR_TYPE = (unsigned int)(timerType & 0x03);
301 } else {
302 return ERROR_INVAL_TIMERTYPE;
303 }
304 } else {
305 return ERROR_INVAL_TIMER_NUM;
306 }
307 return RSI_OK;
308 }
309
310 /*===================================================*/
311 /**
312 * @fn rsi_error_t RSI_TIMERS_SetTimerMode(RSI_TIMERS_T *pTIMER, boolean_t mode,uint8_t timerNum)
313 * @brief This API is used to set the timer mode
314 * @param[in] pTIMER : Pointer to the TIMERS instance register area
315 * @param[in] mode : in which mode timer run
316 * - \ref PERIODIC_TIMER
317 * - \ref ONESHOT_TIMER
318 * @param[in] timerNum : Timer number(0 to 3)
319 * @return return the timer error code
320 */
RSI_TIMERS_SetTimerMode(RSI_TIMERS_T * pTIMER,boolean_t mode,uint8_t timerNum)321 STATIC INLINE rsi_error_t RSI_TIMERS_SetTimerMode(RSI_TIMERS_T *pTIMER, boolean_t mode, uint8_t timerNum)
322 {
323 if (timerNum <= TIMER_3) {
324 if ((mode == PERIODIC_TIMER) || (mode == ONESHOT_TIMER)) {
325 pTIMER->MATCH_CTRL[timerNum].MCUULP_TMR_CNTRL_b.TMR_MODE = (unsigned int)(mode & 0x01);
326 } else {
327 return ERROR_INVAL_TIMER_MODE;
328 }
329 } else {
330 return ERROR_INVAL_TIMER_NUM;
331 }
332 return RSI_OK;
333 }
334
335 /*===================================================*/
336 /**
337 * @fn uint32_t RSI_TIMERS_GetTimerType(const RSI_TIMERS_T *pTIMER, uint8_t timerNum)
338 * @brief This API is used to get the type of timer
339 * @param[in] pTIMER : Pointer to the TIMERS instance register area
340 * @param[in] timerNum : Timer number(0 to 3)
341 * @return return the type of timer if valid timer else error code
342 */
RSI_TIMERS_GetTimerType(const RSI_TIMERS_T * pTIMER,uint8_t timerNum)343 STATIC INLINE uint32_t RSI_TIMERS_GetTimerType(const RSI_TIMERS_T *pTIMER, uint8_t timerNum)
344 {
345 if (timerNum <= TIMER_3) {
346 return (pTIMER->MATCH_CTRL[timerNum].MCUULP_TMR_CNTRL_b.TMR_TYPE);
347 } else {
348 return ERROR_INVAL_TIMER_NUM;
349 }
350 }
351
352 // TIMERS FUNCTION PROTOTYPES
353 RSI_DRIVER_VERSION_M4 RSI_TIMERS_GetVersion(void);
354
355 RSI_TIMERS_CAPABILITIES_T RSI_TIMERS_GetCapabilities(void);
356
357 rsi_error_t timers_microsec_timer_config(RSI_TIMERS_T *pTIMER,
358 uint8_t timerNum,
359 uint16_t integer,
360 uint8_t fractional,
361 uint8_t mode);
362 uint32_t timers_read_timer(RSI_TIMERS_T *pTIMER, uint8_t timerNum, boolean_t countDir);
363 void IRQ002_Handler();
364
365 #ifdef __cplusplus
366 }
367 #endif
368
369 #endif // RSI_TIMERS_H
370