1 /***************************************************************************//**
2  * @file
3  * @brief System Real Time Counter (SYSRTC) peripheral API
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
7  *******************************************************************************
8  *
9  * SPDX-License-Identifier: Zlib
10  *
11  * The licensor of this software is Silicon Laboratories Inc.
12  *
13  * This software is provided 'as-is', without any express or implied
14  * warranty. In no event will the authors be held liable for any damages
15  * arising from the use of this software.
16  *
17  * Permission is granted to anyone to use this software for any purpose,
18  * including commercial applications, and to alter it and redistribute it
19  * freely, subject to the following restrictions:
20  *
21  * 1. The origin of this software must not be misrepresented; you must not
22  *    claim that you wrote the original software. If you use this software
23  *    in a product, an acknowledgment in the product documentation would be
24  *    appreciated but is not required.
25  * 2. Altered source versions must be plainly marked as such, and must not be
26  *    misrepresented as being the original software.
27  * 3. This notice may not be removed or altered from any source distribution.
28  *
29  ******************************************************************************/
30 
31 #ifndef SL_HAL_SYSRTC_H
32 #define SL_HAL_SYSRTC_H
33 
34 #include "em_device.h"
35 
36 #if defined(SYSRTC_COUNT) && (SYSRTC_COUNT > 0)
37 #include <stdbool.h>
38 #include "sl_code_classification.h"
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 #include <stdbool.h>
45 #include "sl_hal_sysrtc_compat.h"
46 #include "sl_enum.h"
47 
48 /***************************************************************************//**
49  * @addtogroup sysrtc
50  * @{
51  ******************************************************************************/
52 
53 /*******************************************************************************
54  *******************************   DEFINES   ***********************************
55  ******************************************************************************/
56 
57 /// Minimum compare channels for SYSRTC group.
58 #define SYSRTC_GROUP_MIN_CHANNEL_COMPARE  1u
59 /// Maximum compare channels for SYSRTC group.
60 #define SYSRTC_GROUP_MAX_CHANNEL_COMPARE  2u
61 
62 /// Minimum capture channels for SYSRTC group.
63 #define SYSRTC_GROUP_MIN_CHANNEL_CAPTURE  0u
64 /// Maximum capture channels for SYSRTC group.
65 #define SYSRTC_GROUP_MAX_CHANNEL_CAPTURE  1u
66 
67 /// Sysrtc group number.
68 #if !defined(SYSRTC_GROUP_NUMBER)
69 #define SYSRTC_GROUP_NUMBER   1u
70 #endif
71 
72 /// Validation of valid SYSRTC group for assert statements.
73 #define SYSRTC_GROUP_VALID(group)    ((unsigned)(group) < SYSRTC_GROUP_NUMBER)
74 
75 /*******************************************************************************
76  *********************************   ENUM   ************************************
77  ******************************************************************************/
78 
79 /// Capture input edge select.
SL_ENUM(sl_hal_sysrtc_capture_edge_t)80 SL_ENUM(sl_hal_sysrtc_capture_edge_t) {
81   SL_HAL_SYSRTC_CAPTURE_EDGE_RISING = 0,  ///< Rising edges detected.
82   SL_HAL_SYSRTC_CAPTURE_EDGE_FALLING,     ///< Falling edges detected.
83   SL_HAL_SYSRTC_CAPTURE_EDGE_BOTH         ///< Both edges detected.
84 };
85 
86 /// Compare match output action mode.
SL_ENUM(sl_hal_sysrtc_compare_match_out_action_t)87 SL_ENUM(sl_hal_sysrtc_compare_match_out_action_t) {
88   SL_HAL_SYSRTC_COMPARE_MATCH_OUT_ACTION_CLEAR = 0, ///< Clear output.
89   SL_HAL_SYSRTC_COMPARE_MATCH_OUT_ACTION_SET,       ///< Set output.
90   SL_HAL_SYSRTC_COMPARE_MATCH_OUT_ACTION_PULSE,     ///< Generate a pulse.
91   SL_HAL_SYSRTC_COMPARE_MATCH_OUT_ACTION_TOGGLE,    ///< Toggle output.
92   SL_HAL_SYSRTC_COMPARE_MATCH_OUT_ACTION_CMPIF      ///< Export CMPIF.
93 };
94 
95 /*******************************************************************************
96  *******************************   STRUCTS   ***********************************
97  ******************************************************************************/
98 
99 /// SYSRTC configuration structure.
100 typedef struct {
101   bool enable_debug_run;      ///< Counter shall keep running during debug halt.
102 } sl_hal_sysrtc_config_t;
103 
104 /// Suggested default values for SYSRTC configuration structure.
105 #define SYSRTC_CONFIG_DEFAULT                        \
106   {                                                  \
107     false, /* Disable updating during debug halt. */ \
108   }
109 
110 /// Compare channel configuration structure.
111 typedef struct {
112   sl_hal_sysrtc_compare_match_out_action_t  compare_match_out_action; ///< Compare mode channel match output action.
113 } sl_hal_sysrtc_group_channel_compare_config_t;
114 
115 /// Capture channel configuration structure.
116 typedef struct {
117   sl_hal_sysrtc_capture_edge_t  capture_input_edge; ///< Capture mode channel input edge.
118 } sl_hal_sysrtc_group_channel_capture_config_t;
119 
120 /// Group configuration structure.
121 typedef struct {
122   bool compare_channel0_enable;                                                  ///< Enable/Disable compare channel 0
123   bool compare_channel1_enable;                                                  ///< Enable/Disable compare channel 1
124   bool capture_channel0_enable;                                                  ///< Enable/Disable capture channel 0
125   sl_hal_sysrtc_group_channel_compare_config_t const *p_compare_channel0_config; ///< Pointer to compare channel 0 config
126   sl_hal_sysrtc_group_channel_compare_config_t const *p_compare_channel1_config; ///< Pointer to compare channel 1 config
127   sl_hal_sysrtc_group_channel_capture_config_t const *p_capture_channel0_config; ///< Pointer to capture channel 0 config
128 } sl_hal_sysrtc_group_config_t;
129 
130 /// Suggested default values for compare channel configuration structure.
131 #define SYSRTC_GROUP_CHANNEL_COMPARE_CONFIG_DEFAULT \
132   {                                                 \
133     SL_HAL_SYSRTC_COMPARE_MATCH_OUT_ACTION_PULSE    \
134   }
135 
136 /// Compare channel configuration for starting HFXO using PRS.
137 #define SYSRTC_GROUP_CHANNEL_COMPARE_CONFIG_EARLY_WAKEUP \
138   {                                                      \
139     SL_HAL_SYSRTC_COMPARE_MATCH_OUT_ACTION_CMPIF         \
140   }
141 
142 /// Suggested default values for capture channel configuration structure.
143 #define SYSRTC_GROUP_CHANNEL_CAPTURE_CONFIG_DEFAULT \
144   {                                                 \
145     SL_HAL_SYSRTC_CAPTURE_EDGE_RISING               \
146   }
147 
148 /// Suggested default values for SYSRTC group configuration structure.
149 #define SYSRTC_GROUP_CONFIG_DEFAULT                                          \
150   {                                                                          \
151     true, /* Enable compare channel 0. */                                    \
152     false, /* Disable compare channel 1. */                                  \
153     false, /* Disable capture channel 0. */                                  \
154     NULL, /* NULL Pointer to configuration structure for compare channel 0*/ \
155     NULL, /* NULL Pointer to configuration structure for compare channel 1*/ \
156     NULL /* NULL Pointer to configuration structure for capture channel 0*/  \
157   }
158 
159 /*******************************************************************************
160  *****************************   PROTOTYPES   **********************************
161  ******************************************************************************/
162 
163 /***************************************************************************//**
164  * Initializes SYSRTC module.
165  *
166  * Note that the compare values must be set separately with
167  * (sl_hal_sysrtc_set_group_compare_channel_value()), which should probably be
168  * done prior to the use of this function if configuring the SYSRTC to start
169  * when initialization is completed.
170  *
171  * @param[in] p_config  A pointer to the SYSRTC initialization structure
172  *                      variable.
173  ******************************************************************************/
174 void sl_hal_sysrtc_init(const sl_hal_sysrtc_config_t *p_config);
175 
176 /***************************************************************************//**
177  * Enables SYSRTC counting.
178  ******************************************************************************/
179 void sl_hal_sysrtc_enable(void);
180 
181 /***************************************************************************//**
182  * Disables SYSRTC counting.
183  ******************************************************************************/
184 void sl_hal_sysrtc_disable(void);
185 
186 /***************************************************************************//**
187  * Waits for the SYSRTC to complete all synchronization of register changes
188  * and commands.
189  ******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC,SL_CODE_CLASS_TIME_CRITICAL)190 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC, SL_CODE_CLASS_TIME_CRITICAL)
191 __INLINE void sl_hal_sysrtc_wait_sync(void)
192 {
193   while ((SYSRTC0->EN & SYSRTC_EN_EN) && (SYSRTC0->SYNCBUSY != 0U)) {
194     // Wait for all synchronizations to finish
195   }
196 }
197 
198 /***************************************************************************//**
199  * Waits for the SYSRTC to complete reseting or disabling procedure.
200  ******************************************************************************/
sl_hal_sysrtc_wait_ready(void)201 __INLINE void sl_hal_sysrtc_wait_ready(void)
202 {
203   while ((SYSRTC0->SWRST & _SYSRTC_SWRST_RESETTING_MASK) || (SYSRTC0->EN & _SYSRTC_EN_DISABLING_MASK) || (SYSRTC0->SYNCBUSY != 0U)) {
204     // Wait for all synchronizations to finish
205   }
206 }
207 
208 /***************************************************************************//**
209  * Starts SYSRTC counter.
210  *
211  * This function will send a start command to the SYSRTC peripheral. The SYSRTC
212  * peripheral will use some LF clock ticks before the command is executed.
213  * The sl_hal_sysrtc_wait_sync() function can be used to wait for the start
214  * command to be executed.
215  *
216  * @note  This function requires the SYSRTC to be enabled.
217  ******************************************************************************/
sl_hal_sysrtc_start(void)218 __INLINE void sl_hal_sysrtc_start(void)
219 {
220   sl_hal_sysrtc_wait_sync();
221   SYSRTC0->CMD = SYSRTC_CMD_START;
222 }
223 
224 /***************************************************************************//**
225  * Stops the SYSRTC counter.
226  *
227  * This function will send a stop command to the SYSRTC peripheral. The SYSRTC
228  * peripheral will use some LF clock ticks before the command is executed.
229  * The sl_hal_sysrtc_wait_sync() function can be used to wait for the stop
230  * command to be executed.
231  *
232  * @note  This function requires the SYSRTC to be enabled.
233  ******************************************************************************/
sl_hal_sysrtc_stop(void)234 __INLINE void sl_hal_sysrtc_stop(void)
235 {
236   sl_hal_sysrtc_wait_sync();
237   SYSRTC0->CMD = SYSRTC_CMD_STOP;
238 }
239 
240 /***************************************************************************//**
241  * Restores SYSRTC to its reset state.
242  ******************************************************************************/
243 void sl_hal_sysrtc_reset(void);
244 
245 /***************************************************************************//**
246  * Gets SYSRTC STATUS register value.
247  *
248  * @return  Current STATUS register value.
249  ******************************************************************************/
sl_hal_sysrtc_get_status(void)250 __INLINE uint32_t sl_hal_sysrtc_get_status(void)
251 {
252   return SYSRTC0->STATUS;
253 }
254 
255 /***************************************************************************//**
256  * Locks SYSRTC registers.
257  *
258  * @note  When SYSRTC registers are locked SYSRTC_EN, SYSRTC_CFG, SYSRTC_CMD,
259  *        SYSRTC_SWRST, SYSRTC_CNT and SYSRTC_TOPCNT registers cannot be written
260  *        to.
261  ******************************************************************************/
sl_hal_sysrtc_lock(void)262 __INLINE void sl_hal_sysrtc_lock(void)
263 {
264   SYSRTC0->LOCK = ~SYSRTC_LOCK_LOCKKEY_UNLOCK;
265 }
266 
267 /***************************************************************************//**
268  * Unlocks SYSRTC registers.
269  *
270  * @note  When SYSRTC registers are locked SYSRTC_EN, SYSRTC_CFG, SYSRTC_CMD,
271  *        SYSRTC_SWRST, SYSRTC_CNT and SYSRTC_TOPCNT registers cannot be written
272  *        to.
273  ******************************************************************************/
sl_hal_sysrtc_unlock(void)274 __INLINE void sl_hal_sysrtc_unlock(void)
275 {
276   SYSRTC0->LOCK = SYSRTC_LOCK_LOCKKEY_UNLOCK;
277 }
278 
279 /***************************************************************************//**
280  * Gets SYSRTC counter value.
281  *
282  * @return  Current SYSRTC counter value.
283  ******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC,SL_CODE_CLASS_TIME_CRITICAL)284 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC, SL_CODE_CLASS_TIME_CRITICAL)
285 __INLINE uint32_t sl_hal_sysrtc_get_counter(void)
286 {
287   // Wait for Counter to synchronize before getting value
288   sl_hal_sysrtc_wait_sync();
289 
290   return SYSRTC0->CNT;
291 }
292 
293 /***************************************************************************//**
294  * Sets the SYSRTC counter value.
295  *
296  * @param[in] value   The new SYSRTC counter value.
297  ******************************************************************************/
sl_hal_sysrtc_set_counter(uint32_t value)298 __INLINE void sl_hal_sysrtc_set_counter(uint32_t value)
299 {
300   // Wait for Counter to synchronize before getting value
301   sl_hal_sysrtc_wait_sync();
302 
303   SYSRTC0->CNT = value;
304 }
305 
306 /***************************************************************************//**
307  * Initializes the selected SYSRTC group.
308  *
309  * @param[in] group_number  SYSRTC group number to use.
310  *
311  * @param[in] p_group_config  Pointer to group configuration structure
312  *                            variable.
313  ******************************************************************************/
314 void sl_hal_sysrtc_init_group(uint8_t group_number,
315                               sl_hal_sysrtc_group_config_t const *p_group_config);
316 
317 /***************************************************************************//**
318  * Enables one or more SYSRTC interrupts for the given group.
319  *
320  * @note  Depending on the use, a pending interrupt may already be set prior to
321  *        enabling the interrupt. To ignore a pending interrupt, consider using
322  *        sl_hal_sysrtc_clear_group_interrupts() prior to enabling the interrupt.
323  *
324  * @param[in] group_number  SYSRTC group number to use.
325  *
326  * @param[in] flags   SYSRTC interrupt sources to enable.
327  *                    Use a set of interrupt flags OR-ed together to set
328  *                    multiple interrupt sources for the given SYSRTC group.
329  ******************************************************************************/
330 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC, SL_CODE_CLASS_TIME_CRITICAL)
331 void sl_hal_sysrtc_enable_group_interrupts(uint8_t group_number,
332                                            uint32_t flags);
333 
334 /***************************************************************************//**
335  * Disables one or more SYSRTC interrupts for the given group.
336  *
337  * @param[in] group_number  SYSRTC group number to use.
338  *
339  * @param[in] flags   SYSRTC interrupt sources to disable.
340  *                    Use a set of interrupt flags OR-ed together to disable
341  *                    multiple interrupt sources for the given SYSRTC group.
342  ******************************************************************************/
343 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC, SL_CODE_CLASS_TIME_CRITICAL)
344 void sl_hal_sysrtc_disable_group_interrupts(uint8_t group_number,
345                                             uint32_t flags);
346 
347 /***************************************************************************//**
348  * Clears one or more pending SYSRTC interrupts for the given group.
349  *
350  * @param[in] group_number  SYSRTC group number to use.
351  *
352  * @param[in] flags   SYSRTC interrupt sources to clear.
353  *                    Use a set of interrupt flags OR-ed together to clear
354  *                    multiple interrupt sources for the given SYSRTC group.
355  ******************************************************************************/
356 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC, SL_CODE_CLASS_TIME_CRITICAL)
357 void sl_hal_sysrtc_clear_group_interrupts(uint8_t group_number,
358                                           uint32_t flags);
359 
360 /***************************************************************************//**
361  * Gets pending SYSRTC interrupt flags for the given group.
362  *
363  * @note  Event bits are not cleared by using this function.
364  *
365  * @param[in] group_number  SYSRTC group number to use.
366  *
367  * @return  Pending SYSRTC interrupt sources.
368  *          Returns a set of interrupt flags OR-ed together for multiple
369  *          interrupt sources in the SYSRTC group.
370  ******************************************************************************/
371 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC, SL_CODE_CLASS_TIME_CRITICAL)
372 uint32_t sl_hal_sysrtc_get_group_interrupts(uint8_t group_number);
373 
374 /***************************************************************************//**
375  * Gets enabled and pending SYSRTC interrupt flags.
376  * Useful for handling more interrupt sources in the same interrupt handler.
377  *
378  * @note  Interrupt flags are not cleared by using this function.
379  *
380  * @param[in] group_number  SYSRTC group number to use.
381  *
382  * @return  Pending and enabled SYSRTC interrupt sources.
383  *          The return value is the bitwise AND of
384  *          - the enabled interrupt sources in SYSRTC_GRPx_IEN and
385  *          - the pending interrupt flags SYSRTC_GRPx_IF.
386  ******************************************************************************/
387 uint32_t sl_hal_sysrtc_get_group_enabled_interrupts(uint8_t group_number);
388 
389 /***************************************************************************//**
390  * Sets one or more pending SYSRTC interrupts for the given group from Software.
391  *
392  * @param[in] group_number  SYSRTC group number to use.
393  *
394  * @param[in] flags   SYSRTC interrupt sources to set to pending.
395  *                    Use a set of interrupt flags OR-ed together to set
396  *                    multiple interrupt sources for the SYSRTC group.
397  ******************************************************************************/
398 void sl_hal_sysrtc_set_group_interrupts(uint8_t group_number,
399                                         uint32_t flags);
400 
401 /***************************************************************************//**
402  * Gets SYSRTC compare register value for selected channel of given group.
403  *
404  * @param[in] group_number  SYSRTC group number to use.
405  *
406  * @param[in] channel   Channel selector.
407  *
408  * @return  Compare register value.
409  ******************************************************************************/
410 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC, SL_CODE_CLASS_TIME_CRITICAL)
411 uint32_t sl_hal_sysrtc_get_group_compare_channel_value(uint8_t group_number,
412                                                        uint8_t channel);
413 
414 /***************************************************************************//**
415  * Sets SYSRTC compare register value for selected channel of given group.
416  *
417  * @param[in] group_number  SYSRTC group number to use.
418  *
419  * @param[in] channel   Channel selector.
420  *
421  * @param[in] value   Compare register value.
422  ******************************************************************************/
423 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC, SL_CODE_CLASS_TIME_CRITICAL)
424 void sl_hal_sysrtc_set_group_compare_channel_value(uint8_t group_number,
425                                                    uint8_t channel,
426                                                    uint32_t value);
427 
428 /***************************************************************************//**
429  * Gets SYSRTC input capture register value for capture channel of given group.
430  *
431  * @param[in] group_number  SYSRTC group number to use.
432  *
433  * @return  Capture register value.
434  ******************************************************************************/
435 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_SYSRTC, SL_CODE_CLASS_TIME_CRITICAL)
436 uint32_t sl_hal_sysrtc_get_group_capture_channel_value(uint8_t group_number);
437 
438 /** @} (end addtogroup sysrtc) */
439 
440 #ifdef __cplusplus
441 }
442 #endif
443 
444 #endif /* defined(SYSRTC_COUNT) && (SYSRTC_COUNT > 0) */
445 #endif /* SL_HAL_SYSRTC_H */
446