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