1 /***************************************************************************//**
2  * @file
3  * @brief Real Time Counter (RTCC) 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_RTCC_H
32 #define EM_RTCC_H
33 
34 #include "em_device.h"
35 #if defined(RTCC_COUNT) && (RTCC_COUNT == 1)
36 
37 #include <stdbool.h>
38 #include "em_assert.h"
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 /***************************************************************************//**
45  * @addtogroup rtcc
46  * @{
47  ******************************************************************************/
48 
49 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
50 #if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_84) \
51   || defined(_SILICON_LABS_GECKO_INTERNAL_SDID_89)
52 /* Enable fix for errata "RTCC_E203 - Potential Stability Issue with RTCC
53  * Registers". */
54 #define ERRATA_FIX_RTCC_E203
55 #endif
56 
57 #if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_84)
58 /* Enable fix for errata "RTCC_E204 - Disabling the RTCC Backup RAM may consume extra
59  * current". */
60 #define ERRATA_FIX_RTCC_E204
61 #endif
62 /** @endcond */
63 
64 /*******************************************************************************
65  *********************************   ENUM   ************************************
66  ******************************************************************************/
67 
68 #if defined (_RTCC_CTRL_CNTMODE_MASK)
69 /** Operational mode of the counter. */
70 typedef enum {
71   /** Normal counter mode. The counter is incremented by 1 for each tick. */
72   rtccCntModeNormal = _RTCC_CTRL_CNTMODE_NORMAL,
73 
74   /** Calendar mode. Refer to the RTCC chapter of the Reference Manual for more
75    *  details on the calendar mode. */
76   rtccCntModeCalendar = _RTCC_CTRL_CNTMODE_CALENDAR
77 } RTCC_CntMode_TypeDef;
78 #endif
79 
80 /** Counter prescaler selection. */
81 #if defined (_RTCC_CTRL_CNTPRESC_DIV1)
82 typedef enum {
83   rtccCntPresc_1     = _RTCC_CTRL_CNTPRESC_DIV1,      /**< Divide clock by 1.     */
84   rtccCntPresc_2     = _RTCC_CTRL_CNTPRESC_DIV2,      /**< Divide clock by 2.     */
85   rtccCntPresc_4     = _RTCC_CTRL_CNTPRESC_DIV4,      /**< Divide clock by 4.     */
86   rtccCntPresc_8     = _RTCC_CTRL_CNTPRESC_DIV8,      /**< Divide clock by 8.     */
87   rtccCntPresc_16    = _RTCC_CTRL_CNTPRESC_DIV16,     /**< Divide clock by 16.    */
88   rtccCntPresc_32    = _RTCC_CTRL_CNTPRESC_DIV32,     /**< Divide clock by 32.    */
89   rtccCntPresc_64    = _RTCC_CTRL_CNTPRESC_DIV64,     /**< Divide clock by 64.    */
90   rtccCntPresc_128   = _RTCC_CTRL_CNTPRESC_DIV128,    /**< Divide clock by 128.   */
91   rtccCntPresc_256   = _RTCC_CTRL_CNTPRESC_DIV256,    /**< Divide clock by 256.   */
92   rtccCntPresc_512   = _RTCC_CTRL_CNTPRESC_DIV512,    /**< Divide clock by 512.   */
93   rtccCntPresc_1024  = _RTCC_CTRL_CNTPRESC_DIV1024,   /**< Divide clock by 1024.  */
94   rtccCntPresc_2048  = _RTCC_CTRL_CNTPRESC_DIV2048,   /**< Divide clock by 2048.  */
95   rtccCntPresc_4096  = _RTCC_CTRL_CNTPRESC_DIV4096,   /**< Divide clock by 4096.  */
96   rtccCntPresc_8192  = _RTCC_CTRL_CNTPRESC_DIV8192,   /**< Divide clock by 8192.  */
97   rtccCntPresc_16384 = _RTCC_CTRL_CNTPRESC_DIV16384,  /**< Divide clock by 16384. */
98   rtccCntPresc_32768 = _RTCC_CTRL_CNTPRESC_DIV32768   /**< Divide clock by 32768. */
99 } RTCC_CntPresc_TypeDef;
100 
101 #elif defined (_RTCC_CFG_CNTPRESC_DIV1)
102 typedef enum {
103   rtccCntPresc_1     = _RTCC_CFG_CNTPRESC_DIV1,      /**< Divide clock by 1. */
104   rtccCntPresc_2     = _RTCC_CFG_CNTPRESC_DIV2,      /**< Divide clock by 2. */
105   rtccCntPresc_4     = _RTCC_CFG_CNTPRESC_DIV4,      /**< Divide clock by 4. */
106   rtccCntPresc_8     = _RTCC_CFG_CNTPRESC_DIV8,      /**< Divide clock by 8. */
107   rtccCntPresc_16    = _RTCC_CFG_CNTPRESC_DIV16,     /**< Divide clock by 16. */
108   rtccCntPresc_32    = _RTCC_CFG_CNTPRESC_DIV32,     /**< Divide clock by 32. */
109   rtccCntPresc_64    = _RTCC_CFG_CNTPRESC_DIV64,     /**< Divide clock by 64. */
110   rtccCntPresc_128   = _RTCC_CFG_CNTPRESC_DIV128,    /**< Divide clock by 128. */
111   rtccCntPresc_256   = _RTCC_CFG_CNTPRESC_DIV256,    /**< Divide clock by 256. */
112   rtccCntPresc_512   = _RTCC_CFG_CNTPRESC_DIV512,    /**< Divide clock by 512. */
113   rtccCntPresc_1024  = _RTCC_CFG_CNTPRESC_DIV1024,   /**< Divide clock by 1024. */
114   rtccCntPresc_2048  = _RTCC_CFG_CNTPRESC_DIV2048,   /**< Divide clock by 2048. */
115   rtccCntPresc_4096  = _RTCC_CFG_CNTPRESC_DIV4096,   /**< Divide clock by 4096. */
116   rtccCntPresc_8192  = _RTCC_CFG_CNTPRESC_DIV8192,   /**< Divide clock by 8192. */
117   rtccCntPresc_16384 = _RTCC_CFG_CNTPRESC_DIV16384,  /**< Divide clock by 16384. */
118   rtccCntPresc_32768 = _RTCC_CFG_CNTPRESC_DIV32768   /**< Divide clock by 32768. */
119 } RTCC_CntPresc_TypeDef;
120 #endif
121 
122 /** Prescaler mode of the RTCC counter. */
123 #if defined (_RTCC_CTRL_CNTTICK_MASK)
124 typedef enum {
125   /** CNT register ticks according to prescaler value. */
126   rtccCntTickPresc = _RTCC_CTRL_CNTTICK_PRESC,
127 
128   /** CNT register ticks when PRECNT matches the 15 least significant bits of
129    *  ch. 0 CCV register. */
130   rtccCntTickCCV0Match = _RTCC_CTRL_CNTTICK_CCV0MATCH
131 } RTCC_PrescMode_TypeDef;
132 
133 #elif defined (_RTCC_CFG_CNTTICK_MASK)
134 typedef enum {
135   /** CNT register ticks according to the prescaler value. */
136   rtccCntTickPresc = _RTCC_CFG_CNTTICK_PRESC,
137 
138   /** CNT register ticks when PRECNT matches the 15 least significant bits of
139    *  ch. 0 CCV register. */
140   rtccCntTickCCV0Match = _RTCC_CFG_CNTTICK_CCV0MATCH
141 } RTCC_PrescMode_TypeDef;
142 #endif
143 
144 /** Capture/Compare channel mode. */
145 typedef enum {
146   rtccCapComChModeOff     = _RTCC_CC_CTRL_MODE_OFF,           /**< Capture/Compare channel turned off. */
147   rtccCapComChModeCapture = _RTCC_CC_CTRL_MODE_INPUTCAPTURE,  /**< Capture mode. */
148   rtccCapComChModeCompare = _RTCC_CC_CTRL_MODE_OUTPUTCOMPARE, /**< Compare mode. */
149 } RTCC_CapComChMode_TypeDef;
150 
151 /** Compare match output action mode. */
152 typedef enum {
153   rtccCompMatchOutActionPulse  = _RTCC_CC_CTRL_CMOA_PULSE,  /**< Generate a pulse. */
154   rtccCompMatchOutActionToggle = _RTCC_CC_CTRL_CMOA_TOGGLE, /**< Toggle output. */
155   rtccCompMatchOutActionClear  = _RTCC_CC_CTRL_CMOA_CLEAR,  /**< Clear output. */
156   rtccCompMatchOutActionSet    = _RTCC_CC_CTRL_CMOA_SET     /**< Set output. */
157 } RTCC_CompMatchOutAction_TypeDef;
158 
159 /** PRS channel number. This type is used when configuring input capture mode on
160  *  a RTCC channel. */
161 typedef uint8_t RTCC_PRSSel_TypeDef;
162 
163 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
164 /** Deprecated PRS channel values. New code should use an integer instead of
165  *  using these deprecated enum values. */
166 #define rtccPRSCh0    0U
167 #define rtccPRSCh1    1U
168 #define rtccPRSCh2    2U
169 #define rtccPRSCh3    3U
170 #define rtccPRSCh4    4U
171 #define rtccPRSCh5    5U
172 #define rtccPRSCh6    6U
173 #define rtccPRSCh7    7U
174 #define rtccPRSCh8    8U
175 #define rtccPRSCh9    9U
176 #define rtccPRSCh10  10U
177 #define rtccPRSCh11  11U
178 /** @endcond */
179 
180 /** Input edge select. */
181 typedef enum {
182   rtccInEdgeRising  = _RTCC_CC_CTRL_ICEDGE_RISING,  /**< Rising edges detected. */
183   rtccInEdgeFalling = _RTCC_CC_CTRL_ICEDGE_FALLING, /**< Falling edges detected. */
184   rtccInEdgeBoth    = _RTCC_CC_CTRL_ICEDGE_BOTH,    /**< Both edges detected. */
185   rtccInEdgeNone    = _RTCC_CC_CTRL_ICEDGE_NONE     /**< No edge detection, signal is left as is. */
186 } RTCC_InEdgeSel_TypeDef;
187 
188 /** Capture/Compare channel compare mode. */
189 typedef enum {
190   /** CCVx is compared with the CNT register. */
191   rtccCompBaseCnt = _RTCC_CC_CTRL_COMPBASE_CNT,
192 
193   /** CCVx is compared with a CNT[16:0] and PRECNT[14:0]. */
194   rtccCompBasePreCnt = _RTCC_CC_CTRL_COMPBASE_PRECNT
195 } RTCC_CompBase_TypeDef;
196 
197 #if defined (_RTCC_CC_CTRL_DAYCC_MASK)
198 /** Day compare mode. */
199 typedef enum {
200   rtccDayCompareModeMonth = _RTCC_CC_CTRL_DAYCC_MONTH,  /**< Day of month is selected for Capture/Compare. */
201   rtccDayCompareModeWeek  = _RTCC_CC_CTRL_DAYCC_WEEK    /**< Day of week is selected for Capture/Compare. */
202 } RTCC_DayCompareMode_TypeDef;
203 #endif
204 
205 /*******************************************************************************
206  *******************************   STRUCTS   ***********************************
207  ******************************************************************************/
208 
209 /** RTCC initialization structure. */
210 typedef struct {
211   /** Enable/disable counting when initialization is completed. */
212   bool                   enable;
213 
214   /** Enable/disable timer counting during debug halt. */
215   bool                   debugRun;
216 
217   /** Enable/disable pre-counter wrap on ch. 0 CCV value. */
218   bool                   precntWrapOnCCV0;
219 
220   /** Enable/disable counter wrap on ch. 1 CCV value. */
221   bool                   cntWrapOnCCV1;
222 
223   /** Counter prescaler. */
224   RTCC_CntPresc_TypeDef  presc;
225 
226   /** Prescaler mode. */
227   RTCC_PrescMode_TypeDef prescMode;
228 
229 #if defined(_RTCC_CTRL_BUMODETSEN_MASK)
230   /** Enable/disable storing RTCC counter value in RTCC_CCV2 upon backup mode
231    *  entry. */
232   bool                   enaBackupModeSet;
233 #endif
234 
235 #if defined(_RTCC_CTRL_OSCFDETEN_MASK)
236   /** Enable/disable the check that sets OSCFFAIL interrupt flag if no
237    *  LFCLK-RTCC ticks are detected within one ULFRCO cycles. */
238   bool                   enaOSCFailDetect;
239 #endif
240 
241 #if defined (_RTCC_CTRL_CNTMODE_MASK)
242   /** Select operational mode of the counter. */
243   RTCC_CntMode_TypeDef   cntMode;
244 #endif
245 
246 #if defined (_RTCC_CTRL_LYEARCORRDIS_MASK)
247   /** Disable leap year correction for calendar mode. When this parameter is
248    *  set to false, February has 29 days if (year % 4 == 0). If set to true,
249    *  February always has 28 days. */
250   bool                   disLeapYearCorr;
251 #endif
252 } RTCC_Init_TypeDef;
253 
254 /** RTCC capture/compare channel configuration structure. */
255 typedef struct {
256   /** Select mode of Capture/Compare channel. */
257   RTCC_CapComChMode_TypeDef        chMode;
258 
259   /** Compare mode channel match output action. */
260   RTCC_CompMatchOutAction_TypeDef  compMatchOutAction;
261 
262   /** Capture mode channel PRS input channel selection. */
263   RTCC_PRSSel_TypeDef              prsSel;
264 
265   /** Capture mode channel input edge selection. */
266   RTCC_InEdgeSel_TypeDef           inputEdgeSel;
267 
268   /** Comparison base of channel in compare mode. */
269   RTCC_CompBase_TypeDef            compBase;
270 
271 #if defined (_RTCC_CC_CTRL_COMPMASK_MASK)
272   /** The COMPMASK (5 bit) most significant bits of compare value will not
273    *  be subject to comparison.  */
274   uint8_t                          compMask;
275 #endif
276 
277 #if defined (_RTCC_CC_CTRL_DAYCC_MASK)
278   /** Day compare mode. */
279   RTCC_DayCompareMode_TypeDef      dayCompMode;
280 #endif
281 } RTCC_CCChConf_TypeDef;
282 
283 /*******************************************************************************
284  *******************************   DEFINES   ***********************************
285  ******************************************************************************/
286 
287 /** Default RTCC initialization structure. */
288 #if defined(_SILICON_LABS_32B_SERIES_2)
289 #define RTCC_INIT_DEFAULT                                                   \
290   {                                                                         \
291     true,   /* Start counting when init done.                            */ \
292     false,  /* Disable RTCC during debug halt.                           */ \
293     false,  /* Disable precounter wrap on ch. 0 CCV value.               */ \
294     false,  /* Disable counter wrap on ch. 1 CCV value.                  */ \
295     rtccCntPresc_32, /* 977 us per tick.                                 */ \
296     rtccCntTickPresc, /* Counter increments according to prescaler value.*/ \
297   }
298 
299 #elif defined(_RTCC_CTRL_BUMODETSEN_MASK)
300 #define RTCC_INIT_DEFAULT                                                   \
301   {                                                                         \
302     true,   /* Start counting when initialization is done.               */ \
303     false,  /* Disable RTCC during debug halt.                           */ \
304     false,  /* Disable pre-counter wrap on ch. 0 CCV value.              */ \
305     false,  /* Disable counter wrap on ch. 1 CCV value.                  */ \
306     rtccCntPresc_32, /* 977 us per tick.                                 */ \
307     rtccCntTickPresc, /* Counter increments according to prescaler value.*/ \
308     false,  /* No RTCC storage on backup mode entry.                     */ \
309     false,  /* No RTCC oscillator failure detection.                     */ \
310     rtccCntModeNormal, /* Normal RTCC mode.                              */ \
311     false,  /* No leap year correction.                                  */ \
312   }
313 
314 #else
315 #define RTCC_INIT_DEFAULT                                                   \
316   {                                                                         \
317     true,   /* Start counting when initialization is done.               */ \
318     false,  /* Disable RTCC during debug halt.                           */ \
319     false,  /* Disable pre-counter wrap on ch. 0 CCV value.              */ \
320     false,  /* Disable counter wrap on ch. 1 CCV value.                  */ \
321     rtccCntPresc_32, /* 977 us per tick.                                 */ \
322     rtccCntTickPresc, /* Counter increments according to prescaler value.*/ \
323     false,  /* No RTCC oscillator failure detection.                     */ \
324     rtccCntModeNormal, /* Normal RTCC mode.                              */ \
325     false,  /* No leap year correction.                                  */ \
326   }
327 #endif
328 
329 #if defined(_SILICON_LABS_32B_SERIES_2)
330 
331 /** Default RTCC channel output compare initialization structure. */
332 #define RTCC_CH_INIT_COMPARE_DEFAULT                                  \
333   {                                                                   \
334     rtccCapComChModeCompare,     /* Select output compare mode.    */ \
335     rtccCompMatchOutActionPulse, /* Create pulse on compare match. */ \
336     0,                           /* Don't care.                    */ \
337     rtccInEdgeNone,              /* Don't care.                    */ \
338     rtccCompBaseCnt,             /* Use CNT for comparison.        */ \
339   }
340 
341 /** Default RTCC channel input capture initialization structure. */
342 #define RTCC_CH_INIT_CAPTURE_DEFAULT                                 \
343   {                                                                  \
344     rtccCapComChModeCapture,     /* Select input capture mode.    */ \
345     rtccCompMatchOutActionPulse, /* Don't care.                   */ \
346     0,                           /* Use PRS channel 0 as trigger. */ \
347     rtccInEdgeRising,            /* Capture on rising edge.       */ \
348     rtccCompBaseCnt,             /* Don't care.                   */ \
349   }
350 
351 #else // Series 1 devices
352 
353 /** Default RTCC channel output compare initialization structure. */
354 #define RTCC_CH_INIT_COMPARE_DEFAULT                                 \
355   {                                                                  \
356     rtccCapComChModeCompare,   /* Select output compare mode.     */ \
357     rtccCompMatchOutActionPulse, /* Create pulse on compare match.*/ \
358     0,                         /* PRS channel 0 (not used).       */ \
359     rtccInEdgeNone,            /* No edge detection.              */ \
360     rtccCompBaseCnt,           /* Counter comparison base.        */ \
361     0,                         /* No compare mask bits set.       */ \
362     rtccDayCompareModeMonth    /* Don't care */                      \
363   }
364 
365 /** Default RTCC channel input capture initialization structure. */
366 #define RTCC_CH_INIT_CAPTURE_DEFAULT                                 \
367   {                                                                  \
368     rtccCapComChModeCapture,   /* Select input capture mode.      */ \
369     rtccCompMatchOutActionPulse, /* Create pulse on capture.      */ \
370     0,                         /* PRS channel 0.                  */ \
371     rtccInEdgeRising,          /* Rising edge detection.          */ \
372     rtccCompBaseCnt,           /* Don't care.                     */ \
373     0,                         /* Don't care.                     */ \
374     rtccDayCompareModeMonth    /* Don't care                      */ \
375   }
376 
377 #endif
378 
379 /** Number of RTCC capture/compare channels */
380 #if !defined(RTCC_CC_NUM)
381 #define RTCC_CC_NUM   3UL
382 #endif
383 
384 /** Validation of valid RTCC channel for assert statements. */
385 #define RTCC_CH_VALID(ch)    ((unsigned)(ch) < RTCC_CC_NUM)
386 
387 /*******************************************************************************
388  *****************************   PROTOTYPES   **********************************
389  ******************************************************************************/
390 
391 /***************************************************************************//**
392  * @brief
393  *   Get RTCC compare register value for selected channel.
394  *
395  * @param[in] ch
396  *   Channel selector.
397  *
398  * @return
399  *   Compare register value.
400  ******************************************************************************/
RTCC_ChannelCompareValueGet(int ch)401 __STATIC_INLINE uint32_t RTCC_ChannelCompareValueGet(int ch)
402 {
403   EFM_ASSERT(RTCC_CH_VALID(ch) );
404 #if defined (_RTCC_CC_CCV_MASK)
405   return RTCC->CC[ch].CCV;
406 #elif defined (_RTCC_CC_OCVALUE_MASK)
407   return RTCC->CC[ch].OCVALUE;
408 #endif
409 }
410 
411 /***************************************************************************//**
412  * @brief
413  *   Set RTCC compare register value for selected channel.
414  *
415  * @param[in] ch
416  *   Channel selector.
417  *
418  * @param[in] value
419  *   Compare register value
420  ******************************************************************************/
RTCC_ChannelCompareValueSet(int ch,uint32_t value)421 __STATIC_INLINE void RTCC_ChannelCompareValueSet(int ch, uint32_t value)
422 {
423   EFM_ASSERT(RTCC_CH_VALID(ch) );
424 #if defined (_RTCC_CC_CCV_MASK)
425   RTCC->CC[ch].CCV = value;
426 #elif defined (_RTCC_CC_OCVALUE_MASK)
427   RTCC->CC[ch].OCVALUE = value;
428 #endif
429 }
430 
431 /***************************************************************************//**
432  * @brief
433  *   Get RTCC input capture register value for selected channel.
434  *
435  * @param[in] ch
436  *   Channel selector.
437  *
438  * @return
439  *   Capture register value.
440  ******************************************************************************/
RTCC_ChannelCaptureValueGet(int ch)441 __STATIC_INLINE uint32_t RTCC_ChannelCaptureValueGet(int ch)
442 {
443   EFM_ASSERT(RTCC_CH_VALID(ch) );
444 #if defined (_RTCC_CC_CCV_MASK)
445   return RTCC->CC[ch].CCV;
446 #elif defined (_RTCC_CC_ICVALUE_MASK)
447   return RTCC->CC[ch].ICVALUE;
448 #endif
449 }
450 
451 /***************************************************************************//**
452  * @brief
453  *   Get RTCC capture/compare register value for selected channel.
454  *   For parts with separate capture compare value registers, this function
455  *   returns the compare value.
456  *
457  * @param[in] ch
458  *   Channel selector.
459  *
460  * @return
461  *   Capture/compare register value.
462  ******************************************************************************/
RTCC_ChannelCCVGet(int ch)463 __STATIC_INLINE uint32_t RTCC_ChannelCCVGet(int ch)
464 {
465   return RTCC_ChannelCompareValueGet(ch);
466 }
467 
468 /***************************************************************************//**
469  * @brief
470  *   Set RTCC capture/compare register value for selected channel.
471  *   For parts with separate capture compare value registers, this function
472  *   sets the compare value.
473  *
474  * @param[in] ch
475  *   Channel selector.
476  *
477  * @param[in] value
478  *   Capture/compare register value
479  ******************************************************************************/
RTCC_ChannelCCVSet(int ch,uint32_t value)480 __STATIC_INLINE void RTCC_ChannelCCVSet(int ch, uint32_t value)
481 {
482   RTCC_ChannelCompareValueSet(ch, value);
483 }
484 
485 #if defined (_RTCC_CC_DATE_MASK)
486 /***************************************************************************//**
487  * @brief
488  *   Get the calendar DATE register content for selected channel.
489  *
490  * @param[in] ch
491  *   Channel selector.
492  *
493  * @return
494  *   DATE register value.
495  ******************************************************************************/
RTCC_ChannelDateGet(int ch)496 __STATIC_INLINE uint32_t RTCC_ChannelDateGet(int ch)
497 {
498   EFM_ASSERT(RTCC_CH_VALID(ch) );
499   return RTCC->CC[ch].DATE;
500 }
501 
502 /***************************************************************************//**
503  * @brief
504  *   Set calendar DATE register for selected channel.
505  *
506  * @param[in] ch
507  *   Channel selector.
508  *
509  * @param[in] date
510  *   DATE value.
511  ******************************************************************************/
RTCC_ChannelDateSet(int ch,uint32_t date)512 __STATIC_INLINE void RTCC_ChannelDateSet(int ch, uint32_t date)
513 {
514   EFM_ASSERT(RTCC_CH_VALID(ch) );
515   RTCC->CC[ch].DATE = date;
516 }
517 
518 /***************************************************************************//**
519  * @brief
520  *   Get calendar TIME register content for selected channel.
521  *
522  * @param[in] ch
523  *   Channel selector.
524  *
525  * @return
526  *   TIME register value.
527  ******************************************************************************/
RTCC_ChannelTimeGet(int ch)528 __STATIC_INLINE uint32_t RTCC_ChannelTimeGet(int ch)
529 {
530   EFM_ASSERT(RTCC_CH_VALID(ch) );
531   return RTCC->CC[ch].TIME;
532 }
533 
534 /***************************************************************************//**
535  * @brief
536  *   Set calendar TIME register for selected channel.
537  *
538  * @param[in] ch
539  *   Channel selector.
540  *
541  * @param[in] time
542  *   TIME value.
543  ******************************************************************************/
RTCC_ChannelTimeSet(int ch,uint32_t time)544 __STATIC_INLINE void RTCC_ChannelTimeSet(int ch, uint32_t time)
545 {
546   EFM_ASSERT(RTCC_CH_VALID(ch) );
547   RTCC->CC[ch].TIME = time;
548 }
549 #endif /* defined (_RTCC_CC_DATE_MASK) */
550 
551 /***************************************************************************//**
552  * @brief
553  *   Get combined CNT/PRECNT register content.
554  *
555  * @return
556  *   CNT/PRECNT register value.
557  ******************************************************************************/
RTCC_CombinedCounterGet(void)558 __STATIC_INLINE uint32_t RTCC_CombinedCounterGet(void)
559 {
560 #if defined (RTCC_SYNCBUSY_CNT) || defined (RTCC_SYNCBUSY_CNT)
561   while ((RTCC->SYNCBUSY & (RTCC_SYNCBUSY_CNT | RTCC_SYNCBUSY_PRECNT)) != 0U) {
562     /* Wait for CNT and PRECNT to synchronize */
563   }
564 #endif
565   return RTCC->COMBCNT;
566 }
567 
568 /***************************************************************************//**
569  * @brief
570  *   Get RTCC counter value.
571  *
572  * @return
573  *   Current RTCC counter value.
574  ******************************************************************************/
RTCC_CounterGet(void)575 __STATIC_INLINE uint32_t RTCC_CounterGet(void)
576 {
577 #if defined (RTCC_SYNCBUSY_CNT)
578   while ((RTCC->SYNCBUSY & RTCC_SYNCBUSY_CNT) != 0U) {
579     /* Wait for CNT to synchronize before getting value */
580   }
581 #endif
582   return RTCC->CNT;
583 }
584 
585 /***************************************************************************//**
586  * @brief
587  *   Set RTCC CNT counter.
588  *
589  * @param[in] value
590  *   CNT value.
591  ******************************************************************************/
RTCC_CounterSet(uint32_t value)592 __STATIC_INLINE void RTCC_CounterSet(uint32_t value)
593 {
594 #if defined (RTCC_SYNCBUSY_CNT)
595   while ((RTCC->SYNCBUSY & RTCC_SYNCBUSY_CNT) != 0U) {
596     /* Wait for CNT to synchronize before setting new value */
597   }
598 #endif
599 
600   RTCC->CNT = value;
601 }
602 
603 #if defined (_RTCC_CC_DATE_MASK)
604 /***************************************************************************//**
605  * @brief
606  *   Get DATE register value.
607  *
608  * @return
609  *   Current DATE register value.
610  ******************************************************************************/
RTCC_DateGet(void)611 __STATIC_INLINE uint32_t RTCC_DateGet(void)
612 {
613   return RTCC->DATE;
614 }
615 
616 /***************************************************************************//**
617  * @brief
618  *   Set RTCC DATE register.
619  *
620  * @param[in] date
621  *   DATE value.
622  ******************************************************************************/
RTCC_DateSet(uint32_t date)623 __STATIC_INLINE void RTCC_DateSet(uint32_t date)
624 {
625   RTCC->DATE = date;
626 }
627 #endif /* defined (_RTCC_CC_DATE_MASK) */
628 
629 #if defined (RTCC_EM4WUEN_EM4WU)
630 /***************************************************************************//**
631  * @brief
632  *   Enable/disable EM4 wakeup capability.
633  *
634  * @param[in] enable
635  *   Set to true to enable EM4 wakeup, set to false otherwise.
636  ******************************************************************************/
RTCC_EM4WakeupEnable(bool enable)637 __STATIC_INLINE void RTCC_EM4WakeupEnable(bool enable)
638 {
639   if ( enable ) {
640     RTCC->EM4WUEN = RTCC_EM4WUEN_EM4WU;
641   } else {
642     RTCC->EM4WUEN = 0;
643   }
644 }
645 #endif
646 
647 void RTCC_Enable(bool enable);
648 
649 void RTCC_Init(const RTCC_Init_TypeDef *init);
650 
651 void RTCC_ChannelInit(int ch, RTCC_CCChConf_TypeDef const *confPtr);
652 
653 /***************************************************************************//**
654  * @brief
655  *   Clear one or more pending RTCC interrupts.
656  *
657  * @param[in] flags
658  *   RTCC interrupt sources to clear. Use a set of interrupt flags OR-ed
659  *   together to clear multiple interrupt sources.
660  ******************************************************************************/
RTCC_IntClear(uint32_t flags)661 __STATIC_INLINE void RTCC_IntClear(uint32_t flags)
662 {
663 #if defined (RTCC_HAS_SET_CLEAR)
664   RTCC->IF_CLR = flags;
665 #else
666   RTCC->IFC = flags;
667 #endif
668 }
669 
670 /***************************************************************************//**
671  * @brief
672  *   Disable one or more RTCC interrupts.
673  *
674  * @param[in] flags
675  *   RTCC interrupt sources to disable. Use a set of interrupt flags OR-ed
676  *   together to disable multiple interrupt.
677  ******************************************************************************/
RTCC_IntDisable(uint32_t flags)678 __STATIC_INLINE void RTCC_IntDisable(uint32_t flags)
679 {
680   RTCC->IEN &= ~flags;
681 }
682 
683 /***************************************************************************//**
684  * @brief
685  *   Enable one or more RTCC interrupts.
686  *
687  * @note
688  *   Depending on the use, a pending interrupt may already be set prior to
689  *   enabling the interrupt. To ignore a pending interrupt, consider using
690  *   RTCC_IntClear() prior to enabling the interrupt.
691  *
692  * @param[in] flags
693  *   RTCC interrupt sources to enable. Use a set of interrupt flags OR-ed
694  *   together to set multiple interrupt.
695  ******************************************************************************/
RTCC_IntEnable(uint32_t flags)696 __STATIC_INLINE void RTCC_IntEnable(uint32_t flags)
697 {
698   RTCC->IEN |= flags;
699 }
700 
701 /***************************************************************************//**
702  * @brief
703  *   Get pending RTCC interrupt flags.
704  *
705  * @note
706  *   Event bits are not cleared by using this function.
707  *
708  * @return
709  *   Pending RTCC interrupt sources. Returns a set of interrupt flags OR-ed
710  *   together for the interrupt sources set.
711  ******************************************************************************/
RTCC_IntGet(void)712 __STATIC_INLINE uint32_t RTCC_IntGet(void)
713 {
714   return RTCC->IF;
715 }
716 
717 /***************************************************************************//**
718  * @brief
719  *   Get enabled and pending RTCC interrupt flags.
720  *
721  * @details
722  *   Useful for handling more interrupt sources in the same interrupt handler.
723  *
724  * @return
725  *   Pending and enabled RTCC interrupt sources. Returns a set of interrupt
726  *   flags OR-ed together for the interrupt sources set.
727  ******************************************************************************/
RTCC_IntGetEnabled(void)728 __STATIC_INLINE uint32_t RTCC_IntGetEnabled(void)
729 {
730   uint32_t tmp;
731 
732   tmp = RTCC->IEN;
733 
734   /* Bitwise AND of pending and enabled interrupt flags. */
735   return RTCC->IF & tmp;
736 }
737 
738 /***************************************************************************//**
739  * @brief
740  *   Set one or more pending RTCC interrupts from SW.
741  *
742  * @param[in] flags
743  *   RTCC interrupt sources to set to pending. Use a set of interrupt flags
744  *   (RTCC_IFS_nnn).
745  ******************************************************************************/
RTCC_IntSet(uint32_t flags)746 __STATIC_INLINE void RTCC_IntSet(uint32_t flags)
747 {
748 #if defined (RTCC_HAS_SET_CLEAR)
749   RTCC->IF_SET = flags;
750 #else
751   RTCC->IFS = flags;
752 #endif
753 }
754 
755 /***************************************************************************//**
756  * @brief
757  *   Lock RTCC registers.
758  *
759  * @note
760  *   When RTCC registers are locked, RTCC_CTRL, RTCC_PRECNT, RTCC_CNT,
761  *   RTCC_TIME, RTCC_DATE, RTCC_IEN, RTCC_POWERDOWN and RTCC_CCx_XXX registers
762  *   cannot be written to.
763  ******************************************************************************/
RTCC_Lock(void)764 __STATIC_INLINE void RTCC_Lock(void)
765 {
766 #if defined(ERRATA_FIX_RTCC_E203)
767   /* RTCC_E203 - Potential Stability Issue with RTCC Registers.
768    * RTCC_LOCK register must be modified while RTCC clock is disabled. */
769   uint32_t lfeReg = CMU->LFECLKEN0;
770   bool cmuLocked = (CMU->LOCK == CMU_LOCK_LOCKKEY_LOCKED);
771   if (cmuLocked) {
772     CMU->LOCK = CMU_LOCK_LOCKKEY_UNLOCK;
773   }
774   CMU->LFECLKEN0 = 0x0;
775 #endif
776   RTCC->LOCK = ~RTCC_LOCK_LOCKKEY_UNLOCK;
777 #if defined(ERRATA_FIX_RTCC_E203)
778   /* Restore clock state after RTCC_E203 fix. */
779   CMU->LFECLKEN0 = lfeReg;
780   if (cmuLocked) {
781     CMU->LOCK = CMU_LOCK_LOCKKEY_LOCK;
782   }
783 #endif
784 }
785 
786 /***************************************************************************//**
787  * @brief
788  *   Get RTCC pre-counter value.
789  *
790  * @return
791  *   Current RTCC pre-counter value.
792  ******************************************************************************/
RTCC_PreCounterGet(void)793 __STATIC_INLINE uint32_t RTCC_PreCounterGet(void)
794 {
795 #if defined (RTCC_SYNCBUSY_PRECNT)
796   while ((RTCC->SYNCBUSY & RTCC_SYNCBUSY_PRECNT) != 0U) {
797     /* Wait for PRECNT to synchronize */
798   }
799 #endif
800   return RTCC->PRECNT;
801 }
802 
803 /***************************************************************************//**
804  * @brief
805  *   Set RTCC pre-counter value.
806  *
807  * @param[in] preCntVal
808  *   RTCC pre-counter value to be set.
809  ******************************************************************************/
RTCC_PreCounterSet(uint32_t preCntVal)810 __STATIC_INLINE void RTCC_PreCounterSet(uint32_t preCntVal)
811 {
812 #if defined (RTCC_SYNCBUSY_PRECNT)
813   while ((RTCC->SYNCBUSY & RTCC_SYNCBUSY_PRECNT) != 0U) {
814     /* Wait for PRECNT to synchronize */
815   }
816 #endif
817 
818   RTCC->PRECNT = preCntVal;
819 }
820 
821 void RTCC_Reset(void);
822 
823 #if defined (_RTCC_POWERDOWN_MASK)
824 /***************************************************************************//**
825  * @brief
826  *   Power down retention RAM.
827  *
828  * @note
829  *   Once retention RAM is powered down, it cannot be powered up again.
830  ******************************************************************************/
RTCC_RetentionRamPowerDown(void)831 __STATIC_INLINE void RTCC_RetentionRamPowerDown(void)
832 {
833 #if !defined(ERRATA_FIX_RTCC_E204)
834   /* Devices that are affected by RTCC_E204 should always keep RTCC
835    * backup RAM retained. */
836   RTCC->POWERDOWN = RTCC_POWERDOWN_RAM;
837 #endif
838 }
839 #endif
840 
841 void RTCC_StatusClear(void);
842 
843 /***************************************************************************//**
844  * @brief
845  *   Get STATUS register value.
846  *
847  * @return
848  *   Current STATUS register value.
849  ******************************************************************************/
RTCC_StatusGet(void)850 __STATIC_INLINE uint32_t RTCC_StatusGet(void)
851 {
852 #if defined (RTCC_SYNCBUSY_CMD)
853   while ((RTCC->SYNCBUSY & RTCC_SYNCBUSY_CMD) != 0U) {
854     // Wait for synchronization.
855   }
856 #elif defined (RTCC_SYNCBUSY_START)
857   while ((RTCC->SYNCBUSY & (RTCC_SYNCBUSY_START | RTCC_SYNCBUSY_STOP)) != 0U) {
858     /* Wait for synchronization. */
859   }
860 #endif
861   return RTCC->STATUS;
862 }
863 
864 #if defined(_SILICON_LABS_32B_SERIES_2)
865 /***************************************************************************//**
866  * @brief
867  *   Wait for the RTCC to complete all synchronization of register changes
868  *   and commands.
869  ******************************************************************************/
RTCC_SyncWait(void)870 __STATIC_INLINE void RTCC_SyncWait(void)
871 {
872   while ((RTCC->EN != 0U) && (RTCC->SYNCBUSY != 0U)) {
873     /* Wait for synchronization to finish */
874   }
875 }
876 
877 /***************************************************************************//**
878  * @brief
879  *   Start RTCC counter.
880  *
881  * @details
882  *   This function will send a start command to the RTCC peripheral. The RTCC
883  *   peripheral will use some LF clock ticks before the command is executed.
884  *   The @ref RTCC_SyncWait() function can be used to wait for the start command
885  *   to be executed.
886  *
887  * @note
888  *   This function requires the RTCC to be enabled.
889  ******************************************************************************/
RTCC_Start(void)890 __STATIC_INLINE void RTCC_Start(void)
891 {
892   RTCC_SyncWait();
893   RTCC->CMD = RTCC_CMD_START;
894 }
895 
896 /***************************************************************************//**
897  * @brief
898  *   Stop the RTCC counter.
899  *
900  * @details
901  *   This function will send a stop command to the RTCC peripheral. The RTCC
902  *   peripheral will use some LF clock ticks before the command is executed.
903  *   The @ref RTCC_SyncWait() function can be used to wait for the stop command
904  *   to be executed.
905  *
906  * @note
907  *   This function requires the RTCC to be enabled.
908  ******************************************************************************/
RTCC_Stop(void)909 __STATIC_INLINE void RTCC_Stop(void)
910 {
911   RTCC_SyncWait();
912   RTCC->CMD = RTCC_CMD_STOP;
913 }
914 #endif
915 
916 #if defined (_RTCC_TIME_MASK)
917 /***************************************************************************//**
918  * @brief
919  *   Get TIME register value.
920  *
921  * @return
922  *   Current TIME register value.
923  ******************************************************************************/
RTCC_TimeGet(void)924 __STATIC_INLINE uint32_t RTCC_TimeGet(void)
925 {
926   return RTCC->TIME;
927 }
928 
929 /***************************************************************************//**
930  * @brief
931  *   Set RTCC TIME register.
932  *
933  * @param[in] time
934  *   TIME value.
935  ******************************************************************************/
RTCC_TimeSet(uint32_t time)936 __STATIC_INLINE void RTCC_TimeSet(uint32_t time)
937 {
938   RTCC->TIME = time;
939 }
940 #endif
941 
942 /***************************************************************************//**
943  * @brief
944  *   Unlock RTCC registers.
945  *
946  * @note
947  *   When RTCC registers are locked, RTCC_CTRL, RTCC_PRECNT, RTCC_CNT,
948  *   RTCC_TIME, RTCC_DATE, RTCC_IEN, RTCC_POWERDOWN and RTCC_CCx_XXX registers
949  *   cannot be written to.
950  ******************************************************************************/
RTCC_Unlock(void)951 __STATIC_INLINE void RTCC_Unlock(void)
952 {
953 #if defined(ERRATA_FIX_RTCC_E203)
954   /* RTCC_E203 - Potential Stability Issue with RTCC Registers.
955    * RTCC_LOCK register must be modified while RTCC clock is disabled. */
956   uint32_t lfeReg = CMU->LFECLKEN0;
957   bool cmuLocked = (CMU->LOCK == CMU_LOCK_LOCKKEY_LOCKED);
958   if (cmuLocked) {
959     CMU->LOCK = CMU_LOCK_LOCKKEY_UNLOCK;
960   }
961   CMU->LFECLKEN0 = 0x0;
962 #endif
963   RTCC->LOCK = RTCC_LOCK_LOCKKEY_UNLOCK;
964 #if defined(ERRATA_FIX_RTCC_E203)
965   /* Restore clock state after RTCC_E203 fix. */
966   CMU->LFECLKEN0 = lfeReg;
967   if (cmuLocked) {
968     CMU->LOCK = CMU_LOCK_LOCKKEY_LOCK;
969   }
970 #endif
971 }
972 
973 /** @} (end addtogroup rtcc) */
974 
975 #ifdef __cplusplus
976 }
977 #endif
978 
979 #endif /* defined( RTCC_COUNT ) && ( RTC_COUNT == 1 ) */
980 #endif /* EM_RTCC_H */
981