1 /***************************************************************************//**
2 * @file
3 * @brief Backup Real Time Counter (BURTC) peripheral API
4 *******************************************************************************
5 * # License
6 * <b>Copyright 2018 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 EM_BURTC_H
32 #define EM_BURTC_H
33
34 #include "em_device.h"
35 #if defined(BURTC_PRESENT)
36
37 #include <stdbool.h>
38 #include "em_assert.h"
39 #include "em_bus.h"
40
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44
45 /***************************************************************************//**
46 * @addtogroup burtc
47 * @{
48 ******************************************************************************/
49
50 /*******************************************************************************
51 ******************************* DEFINES ***********************************
52 ******************************************************************************/
53
54 /** BURTC clock divisors. These values are valid for the BURTC prescaler. */
55 #define burtcClkDiv_1 1 /**< Divide clock by 1. */
56 #define burtcClkDiv_2 2 /**< Divide clock by 2. */
57 #define burtcClkDiv_4 4 /**< Divide clock by 4. */
58 #define burtcClkDiv_8 8 /**< Divide clock by 8. */
59 #define burtcClkDiv_16 16 /**< Divide clock by 16. */
60 #define burtcClkDiv_32 32 /**< Divide clock by 32. */
61 #define burtcClkDiv_64 64 /**< Divide clock by 64. */
62 #define burtcClkDiv_128 128 /**< Divide clock by 128. */
63
64 /*******************************************************************************
65 ******************************** ENUMS ************************************
66 ******************************************************************************/
67
68 #if defined(_SILICON_LABS_32B_SERIES_0)
69 /** BURTC clock selection. */
70 typedef enum {
71 /** Ultra low frequency (1 kHz) clock. */
72 burtcClkSelULFRCO = BURTC_CTRL_CLKSEL_ULFRCO,
73 /** Low frequency RC oscillator. */
74 burtcClkSelLFRCO = BURTC_CTRL_CLKSEL_LFRCO,
75 /** Low frequency crystal osciallator. */
76 burtcClkSelLFXO = BURTC_CTRL_CLKSEL_LFXO
77 } BURTC_ClkSel_TypeDef;
78
79 /** BURTC mode of operation. */
80 typedef enum {
81 /** Disable BURTC */
82 burtcModeDisable = BURTC_CTRL_MODE_DISABLE,
83 /** Enable and start BURTC counter in EM0 to EM2. */
84 burtcModeEM2 = BURTC_CTRL_MODE_EM2EN,
85 /** Enable and start BURTC counter in EM0 to EM3. */
86 burtcModeEM3 = BURTC_CTRL_MODE_EM3EN,
87 /** Enable and start BURTC counter in EM0 to EM4. */
88 burtcModeEM4 = BURTC_CTRL_MODE_EM4EN,
89 } BURTC_Mode_TypeDef;
90
91 /** BURTC low power mode. */
92 typedef enum {
93 /** Low Power Mode is disabled. */
94 burtcLPDisable = BURTC_LPMODE_LPMODE_DISABLE,
95 /** Low Power Mode is always enabled. */
96 burtcLPEnable = BURTC_LPMODE_LPMODE_ENABLE,
97 /** Low Power Mode when system enters backup mode. */
98 burtcLPBU = BURTC_LPMODE_LPMODE_BUEN
99 } BURTC_LP_TypeDef;
100 #endif
101
102 /*******************************************************************************
103 ******************************* STRUCTS ***********************************
104 ******************************************************************************/
105
106 #if defined(_SILICON_LABS_32B_SERIES_0)
107 /** BURTC initialization structure for Series 0 devices. */
108 typedef struct {
109 bool enable; /**< Enable BURTC after initialization (starts counter). */
110
111 BURTC_Mode_TypeDef mode; /**< Configure energy mode operation. */
112 bool debugRun; /**< If true, counter will keep running under debug halt. */
113 BURTC_ClkSel_TypeDef clkSel; /**< Select clock source. */
114 uint32_t clkDiv; /**< Clock divider; for ULFRCO 1Khz or 2kHz operation. */
115
116 uint32_t lowPowerComp; /**< Number of least significantt clock bits to ignore in low power mode. */
117 bool timeStamp; /**< Enable time stamp on entering backup power domain. */
118
119 bool compare0Top; /**< Set if Compare Value 0 is also top value (counter restart). */
120
121 BURTC_LP_TypeDef lowPowerMode; /**< Low power operation mode, requires LFXO or LFRCO. */
122 } BURTC_Init_TypeDef;
123
124 /** Default configuration for BURTC initialization structure. */
125 #define BURTC_INIT_DEFAULT \
126 { \
127 true, \
128 burtcModeEM2, \
129 false, \
130 burtcClkSelULFRCO, \
131 burtcClkDiv_1, \
132 0, \
133 true, \
134 false, \
135 burtcLPDisable, \
136 }
137
138 #elif defined(_SILICON_LABS_32B_SERIES_2)
139 /** BURTC initialization structure for Series 2 devices. */
140 typedef struct {
141 bool start; /**< Start BURTC after initialization */
142 bool debugRun; /**< If true, counter will keep running under debug halt */
143 uint32_t clkDiv; /**< Clock divider. Supported range is 1-32768 */
144 bool compare0Top; /**< Set if Compare Value 0 is also top value (counter restart) */
145 bool em4comp; /**< Enable EM4 wakeup on compare match. */
146 bool em4overflow; /**< Enable EM4 wakeup on counter overflow. */
147 } BURTC_Init_TypeDef;
148
149 /** Default configuration for BURTC init structure */
150 #define BURTC_INIT_DEFAULT \
151 { \
152 true, \
153 false, \
154 1, \
155 0, \
156 false, \
157 false, \
158 }
159 #endif
160
161 /*******************************************************************************
162 ***************************** PROTOTYPES **********************************
163 ******************************************************************************/
164
165 /***************************************************************************//**
166 * @brief
167 * Clear one or more pending BURTC interrupts.
168 *
169 * @param[in] flags
170 * BURTC interrupt sources to clear. Use a set of interrupt flags OR-ed
171 * together to clear multiple interrupt sources for the BURTC module
172 * (BURTC_IFS_nnn).
173 ******************************************************************************/
BURTC_IntClear(uint32_t flags)174 __STATIC_INLINE void BURTC_IntClear(uint32_t flags)
175 {
176 #if defined(BURTC_HAS_SET_CLEAR)
177 BURTC->IF_CLR = flags;
178 #else
179 BURTC->IFC = flags;
180 #endif
181 }
182
183 /***************************************************************************//**
184 * @brief
185 * Disable one or more BURTC interrupts.
186 *
187 * @param[in] flags
188 * BURTC interrupt sources to disable. Use a set of interrupt flags OR-ed
189 * together to disable multiple interrupt sources for the BURTC module
190 * (BURTC_IFS_nnn).
191 ******************************************************************************/
BURTC_IntDisable(uint32_t flags)192 __STATIC_INLINE void BURTC_IntDisable(uint32_t flags)
193 {
194 #if defined(BURTC_HAS_SET_CLEAR)
195 BURTC->IEN_CLR = flags;
196 #else
197 BURTC->IEN &= ~(flags);
198 #endif
199 }
200
201 /***************************************************************************//**
202 * @brief
203 * Enable one or more BURTC interrupts.
204 *
205 * @note
206 * Depending on use, a pending interrupt may already be set prior to
207 * enabling the interrupt. Consider using BURTC_IntClear() prior to enabling
208 * if a pending interrupt should be ignored.
209 *
210 * @param[in] flags
211 * BURTC interrupt sources to enable. Use a set of interrupt flags OR-ed
212 * together to set multiple interrupt sources for the BURTC module
213 * (BURTC_IFS_nnn).
214 ******************************************************************************/
BURTC_IntEnable(uint32_t flags)215 __STATIC_INLINE void BURTC_IntEnable(uint32_t flags)
216 {
217 #if defined(BURTC_HAS_SET_CLEAR)
218 BURTC->IEN_SET = flags;
219 #else
220 BURTC->IEN |= flags;
221 #endif
222 }
223
224 /***************************************************************************//**
225 * @brief
226 * Get pending BURTC interrupt flags.
227 *
228 * @note
229 * This function does not clear the event bits.
230 *
231 * @return
232 * Pending BURTC interrupt sources. Returns a set of interrupt flags OR-ed
233 * together for multiple interrupt sources in the BURTC module (BURTC_IFS_nnn).
234 ******************************************************************************/
BURTC_IntGet(void)235 __STATIC_INLINE uint32_t BURTC_IntGet(void)
236 {
237 return BURTC->IF;
238 }
239
240 /***************************************************************************//**
241 * @brief
242 * Get enabled and pending BURTC interrupt flags.
243 *
244 * @note
245 * The event bits are not cleared by the use of this function.
246 *
247 * @return
248 * Pending BURTC interrupt sources that is also enabled. Returns a set of
249 * interrupt flags OR-ed together for multiple interrupt sources in the
250 * BURTC module (BURTC_IFS_nnn).
251 ******************************************************************************/
BURTC_IntGetEnabled(void)252 __STATIC_INLINE uint32_t BURTC_IntGetEnabled(void)
253 {
254 uint32_t tmp;
255
256 /* Get enabled interrupts */
257 tmp = BURTC->IEN;
258
259 /* Return set interrupts */
260 return BURTC->IF & tmp;
261 }
262
263 /***************************************************************************//**
264 * @brief
265 * Set one or more pending BURTC interrupts from SW.
266 *
267 * @param[in] flags
268 * BURTC interrupt sources to set to pending. Use a set of interrupt flags
269 * OR-ed together to set multiple interrupt sources for the BURTC module
270 * (BURTC_IFS_nnn).
271 ******************************************************************************/
BURTC_IntSet(uint32_t flags)272 __STATIC_INLINE void BURTC_IntSet(uint32_t flags)
273 {
274 #if defined(BURTC_HAS_SET_CLEAR)
275 BURTC->IF_SET = flags;
276 #else
277 BURTC->IFS = flags;
278 #endif
279 }
280
281 /***************************************************************************//**
282 * @brief
283 * Status of BURTC RAM, timestamp and LP Mode
284 *
285 * @return A mask logially OR-ed status bits
286 ******************************************************************************/
BURTC_Status(void)287 __STATIC_INLINE uint32_t BURTC_Status(void)
288 {
289 return BURTC->STATUS;
290 }
291
292 #if defined(BURTC_CMD_CLRSTATUS)
293 /***************************************************************************//**
294 * @brief
295 * Clear and reset BURTC status register
296 ******************************************************************************/
BURTC_StatusClear(void)297 __STATIC_INLINE void BURTC_StatusClear(void)
298 {
299 BURTC->CMD = BURTC_CMD_CLRSTATUS;
300 }
301 #endif
302
303 /***************************************************************************//**
304 * @brief
305 * Wait for the BURTC to complete all synchronization of register changes
306 * and commands.
307 ******************************************************************************/
BURTC_SyncWait(void)308 __STATIC_INLINE void BURTC_SyncWait(void)
309 {
310 #if defined(_SILICON_LABS_32B_SERIES_2)
311 while ((BURTC->EN != 0U) && (BURTC->SYNCBUSY != 0U)) {
312 /* Wait for previous synchronization to finish */
313 }
314 #else
315 while (BURTC->SYNCBUSY != 0U) {
316 /* Wait for previous synchronization to finish */
317 }
318 #endif
319 }
320
321 #if defined(_SILICON_LABS_32B_SERIES_2)
322 /***************************************************************************//**
323 * @brief
324 * Start BURTC counter.
325 *
326 * This function will send a start command to the BURTC peripheral. The BURTC
327 * peripheral will use some LF clock ticks before the command is executed.
328 * The @ref BURTC_SyncWait() function can be used to wait for the start command
329 * to be executed.
330 *
331 * @note
332 * This function requires the BURTC to be enabled.
333 ******************************************************************************/
BURTC_Start(void)334 __STATIC_INLINE void BURTC_Start(void)
335 {
336 BURTC_SyncWait();
337 BURTC->CMD = BURTC_CMD_START;
338 }
339
340 /***************************************************************************//**
341 * @brief
342 * Stop the BURTC counter.
343 *
344 * This function will send a stop command to the BURTC peripheral. The BURTC
345 * peripheral will use some LF clock ticks before the command is executed.
346 * The @ref BURTC_SyncWait() function can be used to wait for the stop command
347 * to be executed.
348 *
349 * @note
350 * This function requires the BURTC to be enabled.
351 ******************************************************************************/
BURTC_Stop(void)352 __STATIC_INLINE void BURTC_Stop(void)
353 {
354 BURTC_SyncWait();
355 BURTC->CMD = BURTC_CMD_STOP;
356 }
357 #endif
358
359 /***************************************************************************//**
360 * @brief Get BURTC counter
361 *
362 * @return
363 * BURTC counter value
364 ******************************************************************************/
BURTC_CounterGet(void)365 __STATIC_INLINE uint32_t BURTC_CounterGet(void)
366 {
367 return BURTC->CNT;
368 }
369
370 #if defined(_SILICON_LABS_32B_SERIES_0)
371 /***************************************************************************//**
372 * @brief Get BURTC timestamp for entering BU
373 *
374 * @return
375 * BURTC Time Stamp value
376 ******************************************************************************/
BURTC_TimestampGet(void)377 __STATIC_INLINE uint32_t BURTC_TimestampGet(void)
378 {
379 return BURTC->TIMESTAMP;
380 }
381
382 /***************************************************************************//**
383 * @brief Freeze register updates until enabled
384 * @param[in] enable If true, registers are not updated until enabled again.
385 ******************************************************************************/
BURTC_FreezeEnable(bool enable)386 __STATIC_INLINE void BURTC_FreezeEnable(bool enable)
387 {
388 BUS_RegBitWrite(&BURTC->FREEZE, _BURTC_FREEZE_REGFREEZE_SHIFT, enable);
389 }
390
391 /***************************************************************************//**
392 * @brief Shut down power to rentention register bank.
393 * @param[in] enable
394 * If true, shuts off power to retention registers.
395 * @note
396 * When power rentention is disabled, it cannot be enabled again (until
397 * reset).
398 ******************************************************************************/
BURTC_Powerdown(bool enable)399 __STATIC_INLINE void BURTC_Powerdown(bool enable)
400 {
401 BUS_RegBitWrite(&BURTC->POWERDOWN, _BURTC_POWERDOWN_RAM_SHIFT, enable);
402 }
403
404 /***************************************************************************//**
405 * @brief
406 * Set a value in one of the retention registers
407 *
408 * @param[in] num
409 * Register to set
410 * @param[in] data
411 * Value to put into register
412 ******************************************************************************/
BURTC_RetRegSet(uint32_t num,uint32_t data)413 __STATIC_INLINE void BURTC_RetRegSet(uint32_t num, uint32_t data)
414 {
415 EFM_ASSERT(num <= 127);
416
417 BURTC->RET[num].REG = data;
418 }
419
420 /***************************************************************************//**
421 * @brief
422 * Read a value from one of the retention registers
423 *
424 * @param[in] num
425 * Retention Register to read
426 *
427 * @return
428 * Value of the retention register
429 ******************************************************************************/
BURTC_RetRegGet(uint32_t num)430 __STATIC_INLINE uint32_t BURTC_RetRegGet(uint32_t num)
431 {
432 EFM_ASSERT(num <= 127);
433
434 return BURTC->RET[num].REG;
435 }
436 #endif
437
438 /***************************************************************************//**
439 * @brief
440 * Lock BURTC registers, will protect from writing new config settings
441 ******************************************************************************/
BURTC_Lock(void)442 __STATIC_INLINE void BURTC_Lock(void)
443 {
444 BURTC->LOCK = 0x0;
445 }
446
447 /***************************************************************************//**
448 * @brief
449 * Unlock BURTC registers, enable write access to change configuration
450 ******************************************************************************/
BURTC_Unlock(void)451 __STATIC_INLINE void BURTC_Unlock(void)
452 {
453 BURTC->LOCK = BURTC_LOCK_LOCKKEY_UNLOCK;
454 }
455
456 void BURTC_Reset(void);
457 void BURTC_Init(const BURTC_Init_TypeDef *burtcInit);
458 void BURTC_Enable(bool enable);
459 void BURTC_CounterReset(void);
460 void BURTC_CompareSet(unsigned int comp, uint32_t value);
461 uint32_t BURTC_CompareGet(unsigned int comp);
462 #if defined(_BURTC_CTRL_MASK)
463 uint32_t BURTC_ClockFreqGet(void);
464 #endif
465
466 /** @} (end addtogroup burtc) */
467
468 #ifdef __cplusplus
469 }
470 #endif
471
472 #endif /* BURTC_PRESENT */
473 #endif /* EM_BURTC_H */
474