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