1 /***************************************************************************//**
2  * @file
3  * @brief Backup Real Time Counter (BURTC) peripheral API
4  * @author Energy Micro AS
5  * @version 3.0.0
6  *******************************************************************************
7  * @section License
8  * <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.com</b>
9  *******************************************************************************
10  *
11  * Permission is granted to anyone to use this software for any purpose,
12  * including commercial applications, and to alter it and redistribute it
13  * freely, subject to the following restrictions:
14  *
15  * 1. The origin of this software must not be misrepresented; you must not
16  *    claim that you wrote the original software.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  *    misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  *
21  * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
22  * obligation to support this Software. Energy Micro AS is providing the
23  * Software "AS IS", with no express or implied warranties of any kind,
24  * including, but not limited to, any implied warranties of merchantability
25  * or fitness for any particular purpose or warranties against infringement
26  * of any proprietary rights of a third party.
27  *
28  * Energy Micro AS will not be liable for any consequential, incidental, or
29  * special damages, or any other relief, or for any claim by any third party,
30  * arising from your use of this Software.
31  *
32  ******************************************************************************/
33 #ifndef __EM_BURTC_H
34 #define __EM_BURTC_H
35 
36 #include <stdbool.h>
37 #include "em_part.h"
38 
39 #if defined(BURTC_PRESENT)
40 
41 #include "em_assert.h"
42 #include "em_bitband.h"
43 
44 #ifdef __cplusplus
45 extern "C" {
46 #endif
47 
48 /***************************************************************************//**
49  * @addtogroup EM_Library
50  * @{
51  ******************************************************************************/
52 
53 /***************************************************************************//**
54  * @addtogroup BURTC
55  * @{
56  ******************************************************************************/
57 
58 /*******************************************************************************
59  *******************************   DEFINES   ***********************************
60  ******************************************************************************/
61 
62 #define burtcClkDiv_1      1
63 #define burtcClkDiv_2      2
64 #define burtcClkDiv_4      4
65 #define burtcClkDiv_8      8
66 #define burtcClkDiv_16     16
67 #define burtcClkDiv_32     32
68 #define burtcClkDiv_64     64
69 #define burtcClkDiv_128    128
70 
71 /*******************************************************************************
72  ********************************   ENUMS   ************************************
73  ******************************************************************************/
74 
75 /** BURTC clock selection */
76 typedef enum
77 {
78   /** Ultra low frequency (1 kHz) clock */
79   burtcClkSelULFRCO = BURTC_CTRL_CLKSEL_ULFRCO,
80   /** Low frequency RC oscillator */
81   burtcClkSelLFRCO  = BURTC_CTRL_CLKSEL_LFRCO,
82   /** Low frequency crystal osciallator */
83   burtcClkSelLFXO   = BURTC_CTRL_CLKSEL_LFXO
84 } BURTC_ClkSel_TypeDef;
85 
86 
87 /** BURTC mode of operation */
88 typedef enum
89 {
90   /** Disable BURTC */
91   burtcModeDisable = BURTC_CTRL_MODE_DISABLE,
92   /** Enable and start BURTC counter in EM0 to EM2 */
93   burtcModeEM2     = BURTC_CTRL_MODE_EM2EN,
94   /** Enable and start BURTC counter in EM0 to EM3 */
95   burtcModeEM3     = BURTC_CTRL_MODE_EM3EN,
96   /** Enable and start BURTC counter in EM0 to EM4 */
97   burtcModeEM4     = BURTC_CTRL_MODE_EM4EN,
98 } BURTC_Mode_TypeDef;
99 
100 /** BURTC low power mode */
101 typedef enum
102 {
103   /** Low Power Mode is disabled */
104   burtcLPDisable = BURTC_LPMODE_LPMODE_DISABLE,
105   /** Low Power Mode is always enabled */
106   burtcLPEnable  = BURTC_LPMODE_LPMODE_ENABLE,
107   /** Low Power Mode when system enters backup mode */
108   burtcLPBU      = BURTC_LPMODE_LPMODE_BUEN
109 } BURTC_LP_TypeDef;
110 
111 /*******************************************************************************
112  *******************************   STRUCTS   ***********************************
113  ******************************************************************************/
114 
115 /** BURTC initialization structure. */
116 typedef struct
117 {
118   bool                 enable;       /** Enable BURTC after initialization (starts counter) */
119 
120   BURTC_Mode_TypeDef   mode;         /**< Configure energy mode operation */
121   bool                 debugRun;     /**< If true, counter will keep running under debug halt */
122   BURTC_ClkSel_TypeDef clkSel;       /**< Select clock source */
123   uint32_t             clkDiv;       /**< Clock divider; for ULFRCO 1Khz or 2kHz operation */
124 
125   uint32_t             lowPowerComp; /**< Number of least significantt clock bits to ignore in low power mode */
126   bool                 timeStamp;    /**< Enable time stamp on entering backup power domain */
127 
128   bool                 compare0Top;  /**< Set if Compare Value 0 is also top value (counter restart) */
129 
130   BURTC_LP_TypeDef     lowPowerMode; /**< Low power operation mode, requires LFXO or LFRCO */
131 } BURTC_Init_TypeDef;
132 
133 /** Default configuration for BURTC init structure */
134 #define BURTC_INIT_DEFAULT \
135   { true,                  \
136     burtcModeEM2,          \
137     false,                 \
138     burtcClkSelULFRCO,     \
139     burtcClkDiv_1,         \
140     0,                     \
141     true,                  \
142     false,                 \
143     burtcLPDisable,        \
144   }
145 
146 /*******************************************************************************
147  *****************************   PROTOTYPES   **********************************
148  ******************************************************************************/
149 
150 /***************************************************************************//**
151  * @brief
152  *   Clear one or more pending BURTC interrupts.
153  *
154  * @param[in] flags
155  *   BURTC interrupt sources to clear. Use a set of interrupt flags OR-ed
156  *   together to clear multiple interrupt sources for the BURTC module
157  *   (BURTC_IFS_nnn).
158  ******************************************************************************/
BURTC_IntClear(uint32_t flags)159 __STATIC_INLINE void BURTC_IntClear(uint32_t flags)
160 {
161   BURTC->IFC = flags;
162 }
163 
164 
165 /***************************************************************************//**
166  * @brief
167  *   Disable one or more BURTC interrupts.
168  *
169  * @param[in] flags
170  *   BURTC interrupt sources to disable. Use a set of interrupt flags OR-ed
171  *   together to disable multiple interrupt sources for the BURTC module
172  *   (BURTC_IFS_nnn).
173  ******************************************************************************/
BURTC_IntDisable(uint32_t flags)174 __STATIC_INLINE void BURTC_IntDisable(uint32_t flags)
175 {
176   BURTC->IEN &= ~(flags);
177 }
178 
179 
180 /***************************************************************************//**
181  * @brief
182  *   Enable one or more BURTC interrupts.
183  *
184  * @note
185  *   Depending on the use, a pending interrupt may already be set prior to
186  *   enabling the interrupt. Consider using BURTC_IntClear() prior to enabling
187  *   if such a pending interrupt should be ignored.
188  *
189  * @param[in] flags
190  *   BURTC interrupt sources to enable. Use a set of interrupt flags OR-ed
191  *   together to set multiple interrupt sources for the BURTC module
192  *   (BURTC_IFS_nnn).
193  ******************************************************************************/
BURTC_IntEnable(uint32_t flags)194 __STATIC_INLINE void BURTC_IntEnable(uint32_t flags)
195 {
196   BURTC->IEN |= flags;
197 }
198 
199 
200 /***************************************************************************//**
201  * @brief
202  *   Get pending BURTC interrupt flags.
203  *
204  * @note
205  *   The event bits are not cleared by the use of this function.
206  *
207  * @return
208  *   Pending BURTC interrupt sources. Returns a set of interrupt flags OR-ed
209  *   together for multiple interrupt sources in the BURTC module (BURTC_IFS_nnn).
210  ******************************************************************************/
BURTC_IntGet(void)211 __STATIC_INLINE uint32_t BURTC_IntGet(void)
212 {
213   return(BURTC->IF);
214 }
215 
216 
217 /***************************************************************************//**
218  * @brief
219  *   Get enabled and pending BURTC interrupt flags.
220  *
221  * @note
222  *   The event bits are not cleared by the use of this function.
223  *
224  * @return
225  *   Pending BURTC interrupt sources that is also enabled. Returns a set of
226  *   interrupt flags OR-ed together for multiple interrupt sources in the
227  *   BURTC module (BURTC_IFS_nnn).
228  ******************************************************************************/
BURTC_IntGetEnabled(void)229 __STATIC_INLINE uint32_t BURTC_IntGetEnabled(void)
230 {
231   uint32_t tmp;
232 
233   /* Get enabled interrupts */
234   tmp = BURTC->IEN;
235 
236   /* Return set intterupts */
237   return BURTC->IF & tmp;
238 }
239 
240 
241 /***************************************************************************//**
242  * @brief
243  *   Set one or more pending BURTC interrupts from SW.
244  *
245  * @param[in] flags
246  *   BURTC interrupt sources to set to pending. Use a set of interrupt flags
247  *   OR-ed together to set multiple interrupt sources for the BURTC module
248  *   (BURTC_IFS_nnn).
249  ******************************************************************************/
BURTC_IntSet(uint32_t flags)250 __STATIC_INLINE void BURTC_IntSet(uint32_t flags)
251 {
252   BURTC->IFS = flags;
253 }
254 
255 
256 /***************************************************************************//**
257  * @brief
258  *   Status of BURTC RAM, timestamp and LP Mode
259  *
260  * @return A mask logially OR-ed status bits
261  ******************************************************************************/
BURTC_Status(void)262 __STATIC_INLINE uint32_t BURTC_Status(void)
263 {
264   return BURTC->STATUS;
265 }
266 
267 
268 /***************************************************************************//**
269  * @brief
270  *   Clear and reset BURTC status register
271  ******************************************************************************/
BURTC_StatusClear(void)272 __STATIC_INLINE void BURTC_StatusClear(void)
273 {
274   BURTC->CMD = BURTC_CMD_CLRSTATUS;
275 }
276 
277 
278 /***************************************************************************//**
279  * @brief
280  *   Enable or Disable BURTC peripheral reset and start counter
281  * @param[in] enable
282  *   If true; asserts reset to BURTC, halts counter, if false; deassert reset
283  ******************************************************************************/
BURTC_Enable(bool enable)284 __STATIC_INLINE void BURTC_Enable(bool enable)
285 {
286   /* Note! If mode is disabled, BURTC counter will not start */
287   EFM_ASSERT(((enable == true) && ((BURTC->CTRL & _BURTC_CTRL_MODE_MASK) != BURTC_CTRL_MODE_DISABLE))
288              || (enable == false));
289   if( enable )
290   {
291     BITBAND_Peripheral(&BURTC->CTRL, _BURTC_CTRL_RSTEN_SHIFT, 0);
292   }
293   else
294   {
295     BITBAND_Peripheral(&BURTC->CTRL, _BURTC_CTRL_RSTEN_SHIFT, 1);
296   }
297 }
298 
299 
300 /***************************************************************************//**
301  * @brief Get BURTC counter
302  *
303  * @return
304  *   BURTC counter value
305  ******************************************************************************/
BURTC_CounterGet(void)306 __STATIC_INLINE uint32_t BURTC_CounterGet(void)
307 {
308   return BURTC->CNT;
309 }
310 
311 
312 /***************************************************************************//**
313  * @brief Get BURTC timestamp for entering BU
314  *
315  * @return
316  *   BURTC Time Stamp value
317  ******************************************************************************/
BURTC_TimestampGet(void)318 __STATIC_INLINE uint32_t BURTC_TimestampGet(void)
319 {
320   return BURTC->TIMESTAMP;
321 }
322 
323 
324 /***************************************************************************//**
325  * @brief Freeze register updates until enabled
326  * @param[in] enable If true, registers are not updated until enabled again.
327  ******************************************************************************/
BURTC_FreezeEnable(bool enable)328 __STATIC_INLINE void BURTC_FreezeEnable(bool enable)
329 {
330   BITBAND_Peripheral(&BURTC->FREEZE, _BURTC_FREEZE_REGFREEZE_SHIFT, enable);
331 }
332 
333 
334 /***************************************************************************//**
335  * @brief Shut down power to rentention register bank.
336  * @param[in] enable
337  *     If true, shuts off power to retention registers.
338  * @note
339  *    When power rentention is disabled, it cannot be enabled again (until
340  *    reset).
341  ******************************************************************************/
BURTC_Powerdown(bool enable)342 __STATIC_INLINE void BURTC_Powerdown(bool enable)
343 {
344   BITBAND_Peripheral(&BURTC->POWERDOWN, _BURTC_POWERDOWN_RAM_SHIFT, enable);
345 }
346 
347 
348 /***************************************************************************//**
349  * @brief
350  *   Set a value in one of the retention registers
351  *
352  * @param[in] num
353  *   Register to set
354  * @param[in] data
355  *   Value to put into register
356  ******************************************************************************/
BURTC_RetRegSet(uint32_t num,uint32_t data)357 __STATIC_INLINE void BURTC_RetRegSet(uint32_t num, uint32_t data)
358 {
359   EFM_ASSERT(num <= 127);
360 
361   BURTC->RET[num].REG = data;
362 }
363 
364 
365 /***************************************************************************//**
366  * @brief
367  *   Read a value from one of the retention registers
368  *
369  * @param[in] num
370  *   Retention Register to read
371  ******************************************************************************/
BURTC_RetRegGet(uint32_t num)372 __STATIC_INLINE uint32_t BURTC_RetRegGet(uint32_t num)
373 {
374   EFM_ASSERT(num <= 127);
375 
376   return BURTC->RET[num].REG;
377 }
378 
379 
380 /***************************************************************************//**
381  * @brief
382  *   Lock BURTC registers, will protect from writing new config settings
383  ******************************************************************************/
BURTC_Lock(void)384 __STATIC_INLINE void BURTC_Lock(void)
385 {
386   BURTC->LOCK = BURTC_LOCK_LOCKKEY_LOCK;
387 }
388 
389 
390 /***************************************************************************//**
391  * @brief
392  *   Unlock BURTC registers, enable write access to change configuration
393  ******************************************************************************/
BURTC_Unlock(void)394 __STATIC_INLINE void BURTC_Unlock(void)
395 {
396   BURTC->LOCK = BURTC_LOCK_LOCKKEY_UNLOCK;
397 }
398 
399 
400 void BURTC_Reset(void);
401 void BURTC_Init(const BURTC_Init_TypeDef *burtcInit);
402 void BURTC_CounterReset(void);
403 void BURTC_CompareSet(unsigned int comp, uint32_t value);
404 uint32_t BURTC_CompareGet(unsigned int comp);
405 
406 
407 /** @} (end addtogroup BURTC) */
408 /** @} (end addtogroup EM_Library) */
409 
410 #ifdef __cplusplus
411 }
412 #endif
413 
414 #endif /* BURTC_PRESENT */
415 
416 #endif /* __EM_BURTC_H */
417