1 /***************************************************************************//**
2  * @file
3  * @brief System Real Time Counter (SYSRTC) peripheral API
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2020 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 PERIPHERAL_SYSRTC_H
32 #define PERIPHERAL_SYSRTC_H
33 
34 #include "em_device.h"
35 #if defined(SYSRTC_COUNT) && (SYSRTC_COUNT > 0)
36 
37 #include <stdbool.h>
38 
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 
43 /***************************************************************************//**
44  * @addtogroup sysrtc
45  * @{
46  ******************************************************************************/
47 
48 /*******************************************************************************
49  *******************************   DEFINES   ***********************************
50  ******************************************************************************/
51 
52 /// Minimum compare channels for SYSRTC group.
53 #define SYSRTC_GROUP_MIN_CHANNEL_COMPARE  1u
54 /// Maximum compare channels for SYSRTC group.
55 #define SYSRTC_GROUP_MAX_CHANNEL_COMPARE  2u
56 
57 /// Minimum capture channels for SYSRTC group.
58 #define SYSRTC_GROUP_MIN_CHANNEL_CAPTURE  0u
59 /// Maximum capture channels for SYSRTC group.
60 #define SYSRTC_GROUP_MAX_CHANNEL_CAPTURE  1u
61 
62 /// Sysrtc group number.
63 #ifdef _SILICON_LABS_32B_SERIES_2
64 #if !defined(SYSRTC_GROUP_NUMBER)
65 #define SYSRTC_GROUP_NUMBER   1u
66 #endif
67 #endif
68 
69 /// Validation of valid SYSRTC group for assert statements.
70 #define SYSRTC_GROUP_VALID(group)    ((unsigned)(group) < SYSRTC_GROUP_NUMBER)
71 
72 /*******************************************************************************
73  *********************************   ENUM   ************************************
74  ******************************************************************************/
75 
76 /// Capture input edge select.
77 typedef enum {
78   SL_SYSRTC_CAPTURE_EDGE_RISING = 0,  ///< Rising edges detected.
79   SL_SYSRTC_CAPTURE_EDGE_FALLING,     ///< Falling edges detected.
80   SL_SYSRTC_CAPTURE_EDGE_BOTH         ///< Both edges detected.
81 } sl_sysrtc_capture_edge_t;
82 
83 /// Compare match output action mode.
84 typedef enum {
85   SL_SYSRTC_COMPARE_MATCH_OUT_ACTION_CLEAR = 0, ///< Clear output.
86   SL_SYSRTC_COMPARE_MATCH_OUT_ACTION_SET,       ///< Set output.
87   SL_SYSRTC_COMPARE_MATCH_OUT_ACTION_PULSE,     ///< Generate a pulse.
88   SL_SYSRTC_COMPARE_MATCH_OUT_ACTION_TOGGLE,    ///< Toggle output.
89   SL_SYSRTC_COMPARE_MATCH_OUT_ACTION_CMPIF      ///< Export CMPIF.
90 } sl_sysrtc_compare_match_out_action_t;
91 
92 /*******************************************************************************
93  *******************************   STRUCTS   ***********************************
94  ******************************************************************************/
95 
96 /// SYSRTC configuration structure.
97 typedef struct {
98   bool enable_debug_run;      ///< Counter shall keep running during debug halt.
99 } sl_sysrtc_config_t;
100 
101 /// Suggested default values for SYSRTC configuration structure.
102 #define SYSRTC_CONFIG_DEFAULT                        \
103   {                                                  \
104     false, /* Disable updating during debug halt. */ \
105   }
106 
107 /// Compare channel configuration structure.
108 typedef struct {
109   sl_sysrtc_compare_match_out_action_t  compare_match_out_action; ///< Compare mode channel match output action.
110 } sl_sysrtc_group_channel_compare_config_t;
111 
112 /// Capture channel configuration structure.
113 typedef struct {
114   sl_sysrtc_capture_edge_t  capture_input_edge; ///< Capture mode channel input edge.
115 } sl_sysrtc_group_channel_capture_config_t;
116 
117 /// Group configuration structure.
118 typedef struct {
119   bool compare_channel0_enable;                                             ///< Enable/Disable compare channel 0
120   bool compare_channel1_enable;                                             ///< Enable/Disable compare channel 1
121   bool capture_channel0_enable;                                             ///< Enable/Disable capture channel 0
122   sl_sysrtc_group_channel_compare_config_t const *p_compare_channel0_config; ///< Pointer to compare channel 0 config
123   sl_sysrtc_group_channel_compare_config_t const *p_compare_channel1_config; ///< Pointer to compare channel 1 config
124   sl_sysrtc_group_channel_capture_config_t const *p_capture_channel0_config; ///< Pointer to capture channel 0 config
125 } sl_sysrtc_group_config_t;
126 
127 /// Suggested default values for compare channel configuration structure.
128 #define SYSRTC_GROUP_CHANNEL_COMPARE_CONFIG_DEFAULT \
129   {                                                 \
130     SL_SYSRTC_COMPARE_MATCH_OUT_ACTION_PULSE        \
131   }
132 
133 /// Compare channel configuration for starting HFXO using PRS.
134 #define SYSRTC_GROUP_CHANNEL_COMPARE_CONFIG_EARLY_WAKEUP \
135   {                                                      \
136     SL_SYSRTC_COMPARE_MATCH_OUT_ACTION_CMPIF             \
137   }
138 
139 /// Suggested default values for capture channel configuration structure.
140 #define SYSRTC_GROUP_CHANNEL_CAPTURE_CONFIG_DEFAULT \
141   {                                                 \
142     SL_SYSRTC_CAPTURE_EDGE_RISING                   \
143   }
144 
145 /// Suggested default values for SYSRTC group configuration structure.
146 #define SYSRTC_GROUP_CONFIG_DEFAULT                                          \
147   {                                                                          \
148     true, /* Enable compare channel 0. */                                    \
149     false, /* Disable compare channel 1. */                                  \
150     false, /* Disable capture channel 0. */                                  \
151     NULL, /* NULL Pointer to configuration structure for compare channel 0*/ \
152     NULL, /* NULL Pointer to configuration structure for compare channel 1*/ \
153     NULL /* NULL Pointer to configuration structure for capture channel 0*/  \
154   }
155 
156 /*******************************************************************************
157  *****************************   PROTOTYPES   **********************************
158  ******************************************************************************/
159 
160 /***************************************************************************//**
161  * Initializes SYSRTC module.
162  *
163  * Note that the compare values must be set separately with
164  * (sl_sysrtc_set_group_compare_channel_value()), which should probably be
165  * done prior to the use of this function if configuring the SYSRTC to start
166  * when initialization is completed.
167  *
168  * @param[in] p_config  A pointer to the SYSRTC initialization structure
169  *                      variable.
170  ******************************************************************************/
171 void sl_sysrtc_init(const sl_sysrtc_config_t *p_config);
172 
173 /***************************************************************************//**
174  * Enables SYSRTC counting.
175  ******************************************************************************/
176 void sl_sysrtc_enable(void);
177 
178 /***************************************************************************//**
179  * Disables SYSRTC counting.
180  ******************************************************************************/
181 void sl_sysrtc_disable(void);
182 
183 /***************************************************************************//**
184  * Waits for the SYSRTC to complete all synchronization of register changes
185  * and commands.
186  ******************************************************************************/
sl_sysrtc_wait_sync(void)187 __STATIC_INLINE void sl_sysrtc_wait_sync(void)
188 {
189   while ((SYSRTC0->EN & SYSRTC_EN_EN) && (SYSRTC0->SYNCBUSY != 0U)) {
190     // Wait for all synchronizations to finish
191   }
192 }
193 
194 /***************************************************************************//**
195  * Waits for the SYSRTC to complete reseting or disabling procedure.
196  ******************************************************************************/
sl_sysrtc_wait_ready(void)197 __STATIC_INLINE void sl_sysrtc_wait_ready(void)
198 {
199   while ((SYSRTC0->SWRST & _SYSRTC_SWRST_RESETTING_MASK) || (SYSRTC0->EN & _SYSRTC_EN_DISABLING_MASK) || (SYSRTC0->SYNCBUSY != 0U)) {
200     // Wait for all synchronizations to finish
201   }
202 }
203 
204 /***************************************************************************//**
205  * Starts SYSRTC counter.
206  *
207  * This function will send a start command to the SYSRTC peripheral. The SYSRTC
208  * peripheral will use some LF clock ticks before the command is executed.
209  * The sl_sysrtc_wait_sync() function can be used to wait for the start
210  * command to be executed.
211  *
212  * @note  This function requires the SYSRTC to be enabled.
213  ******************************************************************************/
sl_sysrtc_start(void)214 __STATIC_INLINE void sl_sysrtc_start(void)
215 {
216   sl_sysrtc_wait_sync();
217   SYSRTC0->CMD = SYSRTC_CMD_START;
218 }
219 
220 /***************************************************************************//**
221  * Stops the SYSRTC counter.
222  *
223  * This function will send a stop command to the SYSRTC peripheral. The SYSRTC
224  * peripheral will use some LF clock ticks before the command is executed.
225  * The sl_sysrtc_wait_sync() function can be used to wait for the stop
226  * command to be executed.
227  *
228  * @note  This function requires the SYSRTC to be enabled.
229  ******************************************************************************/
sl_sysrtc_stop(void)230 __STATIC_INLINE void sl_sysrtc_stop(void)
231 {
232   sl_sysrtc_wait_sync();
233   SYSRTC0->CMD = SYSRTC_CMD_STOP;
234 }
235 
236 /***************************************************************************//**
237  * Restores SYSRTC to its reset state.
238  ******************************************************************************/
239 void sl_sysrtc_reset(void);
240 
241 /***************************************************************************//**
242  * Gets SYSRTC STATUS register value.
243  *
244  * @return  Current STATUS register value.
245  ******************************************************************************/
sl_sysrtc_get_status(void)246 __STATIC_INLINE uint32_t sl_sysrtc_get_status(void)
247 {
248   return SYSRTC0->STATUS;
249 }
250 
251 /***************************************************************************//**
252  * Locks SYSRTC registers.
253  *
254  * @note  When SYSRTC registers are locked SYSRTC_EN, SYSRTC_CFG, SYSRTC_CMD,
255  *        SYSRTC_SWRST, SYSRTC_CNT and SYSRTC_TOPCNT registers cannot be written
256  *        to.
257  ******************************************************************************/
sl_sysrtc_lock(void)258 __STATIC_INLINE void sl_sysrtc_lock(void)
259 {
260   SYSRTC0->LOCK = ~SYSRTC_LOCK_LOCKKEY_UNLOCK;
261 }
262 
263 /***************************************************************************//**
264  * Unlocks SYSRTC registers.
265  *
266  * @note  When SYSRTC registers are locked SYSRTC_EN, SYSRTC_CFG, SYSRTC_CMD,
267  *        SYSRTC_SWRST, SYSRTC_CNT and SYSRTC_TOPCNT registers cannot be written
268  *        to.
269  ******************************************************************************/
sl_sysrtc_unlock(void)270 __STATIC_INLINE void sl_sysrtc_unlock(void)
271 {
272   SYSRTC0->LOCK = SYSRTC_LOCK_LOCKKEY_UNLOCK;
273 }
274 
275 /***************************************************************************//**
276  * Gets SYSRTC counter value.
277  *
278  * @return  Current SYSRTC counter value.
279  ******************************************************************************/
sl_sysrtc_get_counter(void)280 __STATIC_INLINE uint32_t sl_sysrtc_get_counter(void)
281 {
282   // Wait for Counter to synchronize before getting value
283   sl_sysrtc_wait_sync();
284 
285   return SYSRTC0->CNT;
286 }
287 
288 /***************************************************************************//**
289  * Sets the SYSRTC counter value.
290  *
291  * @param[in] value   The new SYSRTC counter value.
292  ******************************************************************************/
sl_sysrtc_set_counter(uint32_t value)293 __STATIC_INLINE void sl_sysrtc_set_counter(uint32_t value)
294 {
295   // Wait for Counter to synchronize before getting value
296   sl_sysrtc_wait_sync();
297 
298   SYSRTC0->CNT = value;
299 }
300 
301 /***************************************************************************//**
302  * Initializes the selected SYSRTC group.
303  *
304  * @param[in] group_number  SYSRTC group number to use.
305  *
306  * @param[in] p_group_config  Pointer to group configuration structure
307  *                            variable.
308  ******************************************************************************/
309 void sl_sysrtc_init_group(uint8_t group_number,
310                           sl_sysrtc_group_config_t const *p_group_config);
311 
312 /***************************************************************************//**
313  * Enables one or more SYSRTC interrupts for the given group.
314  *
315  * @note  Depending on the use, a pending interrupt may already be set prior to
316  *        enabling the interrupt. To ignore a pending interrupt, consider using
317  *        sl_sysrtc_clear_group_interrupts() prior to enabling the interrupt.
318  *
319  * @param[in] group_number  SYSRTC group number to use.
320  *
321  * @param[in] flags   SYSRTC interrupt sources to enable.
322  *                    Use a set of interrupt flags OR-ed together to set
323  *                    multiple interrupt sources for the given SYSRTC group.
324  ******************************************************************************/
325 void sl_sysrtc_enable_group_interrupts(uint8_t group_number,
326                                        uint32_t flags);
327 
328 /***************************************************************************//**
329  * Disables one or more SYSRTC interrupts for the given group.
330  *
331  * @param[in] group_number  SYSRTC group number to use.
332  *
333  * @param[in] flags   SYSRTC interrupt sources to disable.
334  *                    Use a set of interrupt flags OR-ed together to disable
335  *                    multiple interrupt sources for the given SYSRTC group.
336  ******************************************************************************/
337 void sl_sysrtc_disable_group_interrupts(uint8_t group_number,
338                                         uint32_t flags);
339 
340 /***************************************************************************//**
341  * Clears one or more pending SYSRTC interrupts for the given group.
342  *
343  * @param[in] group_number  SYSRTC group number to use.
344  *
345  * @param[in] flags   SYSRTC interrupt sources to clear.
346  *                    Use a set of interrupt flags OR-ed together to clear
347  *                    multiple interrupt sources for the given SYSRTC group.
348  ******************************************************************************/
349 void sl_sysrtc_clear_group_interrupts(uint8_t group_number,
350                                       uint32_t flags);
351 
352 /***************************************************************************//**
353  * Gets pending SYSRTC interrupt flags for the given group.
354  *
355  * @note  Event bits are not cleared by using this function.
356  *
357  * @param[in] group_number  SYSRTC group number to use.
358  *
359  * @return  Pending SYSRTC interrupt sources.
360  *          Returns a set of interrupt flags OR-ed together for multiple
361  *          interrupt sources in the SYSRTC group.
362  ******************************************************************************/
363 uint32_t sl_sysrtc_get_group_interrupts(uint8_t group_number);
364 
365 /***************************************************************************//**
366  * Gets enabled and pending SYSRTC interrupt flags.
367  * Useful for handling more interrupt sources in the same interrupt handler.
368  *
369  * @note  Interrupt flags are not cleared by using this function.
370  *
371  * @param[in] group_number  SYSRTC group number to use.
372  *
373  * @return  Pending and enabled SYSRTC interrupt sources.
374  *          The return value is the bitwise AND of
375  *          - the enabled interrupt sources in SYSRTC_GRPx_IEN and
376  *          - the pending interrupt flags SYSRTC_GRPx_IF.
377  ******************************************************************************/
378 uint32_t sl_sysrtc_get_group_enabled_interrupts(uint8_t group_number);
379 
380 /***************************************************************************//**
381  * Sets one or more pending SYSRTC interrupts for the given group from Software.
382  *
383  * @param[in] group_number  SYSRTC group number to use.
384  *
385  * @param[in] flags   SYSRTC interrupt sources to set to pending.
386  *                    Use a set of interrupt flags OR-ed together to set
387  *                    multiple interrupt sources for the SYSRTC group.
388  ******************************************************************************/
389 void sl_sysrtc_set_group_interrupts(uint8_t group_number,
390                                     uint32_t flags);
391 
392 /***************************************************************************//**
393  * Gets SYSRTC compare register value for selected channel of given group.
394  *
395  * @param[in] group_number  SYSRTC group number to use.
396  *
397  * @param[in] channel   Channel selector.
398  *
399  * @return  Compare register value.
400  ******************************************************************************/
401 uint32_t sl_sysrtc_get_group_compare_channel_value(uint8_t group_number,
402                                                    uint8_t channel);
403 
404 /***************************************************************************//**
405  * Sets SYSRTC compare register value for selected channel of given group.
406  *
407  * @param[in] group_number  SYSRTC group number to use.
408  *
409  * @param[in] channel   Channel selector.
410  *
411  * @param[in] value   Compare register value.
412  ******************************************************************************/
413 void sl_sysrtc_set_group_compare_channel_value(uint8_t group_number,
414                                                uint8_t channel,
415                                                uint32_t value);
416 
417 /***************************************************************************//**
418  * Gets SYSRTC input capture register value for capture channel of given group.
419  *
420  * @param[in] group_number  SYSRTC group number to use.
421  *
422  * @return  Capture register value.
423  ******************************************************************************/
424 uint32_t sl_sysrtc_get_group_capture_channel_value(uint8_t group_number);
425 
426 /** @} (end addtogroup sysrtc) */
427 
428 #ifdef __cplusplus
429 }
430 #endif
431 
432 #endif /* defined(SYSRTC_COUNT) && (SYSRTC_COUNT > 0) */
433 #endif /* PERIPHERAL_SYSRTC_H */
434