/***************************************************************************//** * @file * @brief Real Time Counter (RTCC) peripheral API. ******************************************************************************* * # License * Copyright 2018 Silicon Laboratories Inc. www.silabs.com ******************************************************************************* * * SPDX-License-Identifier: Zlib * * The licensor of this software is Silicon Laboratories Inc. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * ******************************************************************************/ #ifndef EM_RTCC_H #define EM_RTCC_H #include "em_device.h" #if defined(RTCC_COUNT) && (RTCC_COUNT == 1) #include #include "sl_assert.h" #ifdef __cplusplus extern "C" { #endif /***************************************************************************//** * @addtogroup rtcc * @{ ******************************************************************************/ /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ #if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_84) \ || defined(_SILICON_LABS_GECKO_INTERNAL_SDID_89) /* Enable fix for errata "RTCC_E203 - Potential Stability Issue with RTCC * Registers". */ #define ERRATA_FIX_RTCC_E203 #endif #if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_84) /* Enable fix for errata "RTCC_E204 - Disabling the RTCC Backup RAM may consume extra * current". */ #define ERRATA_FIX_RTCC_E204 #endif /** @endcond */ /******************************************************************************* ********************************* ENUM ************************************ ******************************************************************************/ #if defined (_RTCC_CTRL_CNTMODE_MASK) /** Operational mode of the counter. */ typedef enum { /** Normal counter mode. The counter is incremented by 1 for each tick. */ rtccCntModeNormal = _RTCC_CTRL_CNTMODE_NORMAL, /** Calendar mode. Refer to the RTCC chapter of the Reference Manual for more * details on the calendar mode. */ rtccCntModeCalendar = _RTCC_CTRL_CNTMODE_CALENDAR } RTCC_CntMode_TypeDef; #endif /** Counter prescaler selection. */ #if defined (_RTCC_CTRL_CNTPRESC_DIV1) typedef enum { rtccCntPresc_1 = _RTCC_CTRL_CNTPRESC_DIV1, /**< Divide clock by 1. */ rtccCntPresc_2 = _RTCC_CTRL_CNTPRESC_DIV2, /**< Divide clock by 2. */ rtccCntPresc_4 = _RTCC_CTRL_CNTPRESC_DIV4, /**< Divide clock by 4. */ rtccCntPresc_8 = _RTCC_CTRL_CNTPRESC_DIV8, /**< Divide clock by 8. */ rtccCntPresc_16 = _RTCC_CTRL_CNTPRESC_DIV16, /**< Divide clock by 16. */ rtccCntPresc_32 = _RTCC_CTRL_CNTPRESC_DIV32, /**< Divide clock by 32. */ rtccCntPresc_64 = _RTCC_CTRL_CNTPRESC_DIV64, /**< Divide clock by 64. */ rtccCntPresc_128 = _RTCC_CTRL_CNTPRESC_DIV128, /**< Divide clock by 128. */ rtccCntPresc_256 = _RTCC_CTRL_CNTPRESC_DIV256, /**< Divide clock by 256. */ rtccCntPresc_512 = _RTCC_CTRL_CNTPRESC_DIV512, /**< Divide clock by 512. */ rtccCntPresc_1024 = _RTCC_CTRL_CNTPRESC_DIV1024, /**< Divide clock by 1024. */ rtccCntPresc_2048 = _RTCC_CTRL_CNTPRESC_DIV2048, /**< Divide clock by 2048. */ rtccCntPresc_4096 = _RTCC_CTRL_CNTPRESC_DIV4096, /**< Divide clock by 4096. */ rtccCntPresc_8192 = _RTCC_CTRL_CNTPRESC_DIV8192, /**< Divide clock by 8192. */ rtccCntPresc_16384 = _RTCC_CTRL_CNTPRESC_DIV16384, /**< Divide clock by 16384. */ rtccCntPresc_32768 = _RTCC_CTRL_CNTPRESC_DIV32768 /**< Divide clock by 32768. */ } RTCC_CntPresc_TypeDef; #elif defined (_RTCC_CFG_CNTPRESC_DIV1) typedef enum { rtccCntPresc_1 = _RTCC_CFG_CNTPRESC_DIV1, /**< Divide clock by 1. */ rtccCntPresc_2 = _RTCC_CFG_CNTPRESC_DIV2, /**< Divide clock by 2. */ rtccCntPresc_4 = _RTCC_CFG_CNTPRESC_DIV4, /**< Divide clock by 4. */ rtccCntPresc_8 = _RTCC_CFG_CNTPRESC_DIV8, /**< Divide clock by 8. */ rtccCntPresc_16 = _RTCC_CFG_CNTPRESC_DIV16, /**< Divide clock by 16. */ rtccCntPresc_32 = _RTCC_CFG_CNTPRESC_DIV32, /**< Divide clock by 32. */ rtccCntPresc_64 = _RTCC_CFG_CNTPRESC_DIV64, /**< Divide clock by 64. */ rtccCntPresc_128 = _RTCC_CFG_CNTPRESC_DIV128, /**< Divide clock by 128. */ rtccCntPresc_256 = _RTCC_CFG_CNTPRESC_DIV256, /**< Divide clock by 256. */ rtccCntPresc_512 = _RTCC_CFG_CNTPRESC_DIV512, /**< Divide clock by 512. */ rtccCntPresc_1024 = _RTCC_CFG_CNTPRESC_DIV1024, /**< Divide clock by 1024. */ rtccCntPresc_2048 = _RTCC_CFG_CNTPRESC_DIV2048, /**< Divide clock by 2048. */ rtccCntPresc_4096 = _RTCC_CFG_CNTPRESC_DIV4096, /**< Divide clock by 4096. */ rtccCntPresc_8192 = _RTCC_CFG_CNTPRESC_DIV8192, /**< Divide clock by 8192. */ rtccCntPresc_16384 = _RTCC_CFG_CNTPRESC_DIV16384, /**< Divide clock by 16384. */ rtccCntPresc_32768 = _RTCC_CFG_CNTPRESC_DIV32768 /**< Divide clock by 32768. */ } RTCC_CntPresc_TypeDef; #endif /** Prescaler mode of the RTCC counter. */ #if defined (_RTCC_CTRL_CNTTICK_MASK) typedef enum { /** CNT register ticks according to prescaler value. */ rtccCntTickPresc = _RTCC_CTRL_CNTTICK_PRESC, /** CNT register ticks when PRECNT matches the 15 least significant bits of * ch. 0 CCV register. */ rtccCntTickCCV0Match = _RTCC_CTRL_CNTTICK_CCV0MATCH } RTCC_PrescMode_TypeDef; #elif defined (_RTCC_CFG_CNTTICK_MASK) typedef enum { /** CNT register ticks according to the prescaler value. */ rtccCntTickPresc = _RTCC_CFG_CNTTICK_PRESC, /** CNT register ticks when PRECNT matches the 15 least significant bits of * ch. 0 CCV register. */ rtccCntTickCCV0Match = _RTCC_CFG_CNTTICK_CCV0MATCH } RTCC_PrescMode_TypeDef; #endif /** Capture/Compare channel mode. */ typedef enum { rtccCapComChModeOff = _RTCC_CC_CTRL_MODE_OFF, /**< Capture/Compare channel turned off. */ rtccCapComChModeCapture = _RTCC_CC_CTRL_MODE_INPUTCAPTURE, /**< Capture mode. */ rtccCapComChModeCompare = _RTCC_CC_CTRL_MODE_OUTPUTCOMPARE, /**< Compare mode. */ } RTCC_CapComChMode_TypeDef; /** Compare match output action mode. */ typedef enum { rtccCompMatchOutActionPulse = _RTCC_CC_CTRL_CMOA_PULSE, /**< Generate a pulse. */ rtccCompMatchOutActionToggle = _RTCC_CC_CTRL_CMOA_TOGGLE, /**< Toggle output. */ rtccCompMatchOutActionClear = _RTCC_CC_CTRL_CMOA_CLEAR, /**< Clear output. */ rtccCompMatchOutActionSet = _RTCC_CC_CTRL_CMOA_SET /**< Set output. */ } RTCC_CompMatchOutAction_TypeDef; /** PRS channel number. This type is used when configuring input capture mode on * a RTCC channel. */ typedef uint8_t RTCC_PRSSel_TypeDef; /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ /** Deprecated PRS channel values. New code should use an integer instead of * using these deprecated enum values. */ #define rtccPRSCh0 0U #define rtccPRSCh1 1U #define rtccPRSCh2 2U #define rtccPRSCh3 3U #define rtccPRSCh4 4U #define rtccPRSCh5 5U #define rtccPRSCh6 6U #define rtccPRSCh7 7U #define rtccPRSCh8 8U #define rtccPRSCh9 9U #define rtccPRSCh10 10U #define rtccPRSCh11 11U /** @endcond */ /** Input edge select. */ typedef enum { rtccInEdgeRising = _RTCC_CC_CTRL_ICEDGE_RISING, /**< Rising edges detected. */ rtccInEdgeFalling = _RTCC_CC_CTRL_ICEDGE_FALLING, /**< Falling edges detected. */ rtccInEdgeBoth = _RTCC_CC_CTRL_ICEDGE_BOTH, /**< Both edges detected. */ rtccInEdgeNone = _RTCC_CC_CTRL_ICEDGE_NONE /**< No edge detection, signal is left as is. */ } RTCC_InEdgeSel_TypeDef; /** Capture/Compare channel compare mode. */ typedef enum { /** CCVx is compared with the CNT register. */ rtccCompBaseCnt = _RTCC_CC_CTRL_COMPBASE_CNT, /** CCVx is compared with a CNT[16:0] and PRECNT[14:0]. */ rtccCompBasePreCnt = _RTCC_CC_CTRL_COMPBASE_PRECNT } RTCC_CompBase_TypeDef; #if defined (_RTCC_CC_CTRL_DAYCC_MASK) /** Day compare mode. */ typedef enum { rtccDayCompareModeMonth = _RTCC_CC_CTRL_DAYCC_MONTH, /**< Day of month is selected for Capture/Compare. */ rtccDayCompareModeWeek = _RTCC_CC_CTRL_DAYCC_WEEK /**< Day of week is selected for Capture/Compare. */ } RTCC_DayCompareMode_TypeDef; #endif /******************************************************************************* ******************************* STRUCTS *********************************** ******************************************************************************/ /** RTCC initialization structure. */ typedef struct { /** Enable/disable counting when initialization is completed. */ bool enable; /** Enable/disable timer counting during debug halt. */ bool debugRun; /** Enable/disable pre-counter wrap on ch. 0 CCV value. */ bool precntWrapOnCCV0; /** Enable/disable counter wrap on ch. 1 CCV value. */ bool cntWrapOnCCV1; /** Counter prescaler. */ RTCC_CntPresc_TypeDef presc; /** Prescaler mode. */ RTCC_PrescMode_TypeDef prescMode; #if defined(_RTCC_CTRL_BUMODETSEN_MASK) /** Enable/disable storing RTCC counter value in RTCC_CCV2 upon backup mode * entry. */ bool enaBackupModeSet; #endif #if defined(_RTCC_CTRL_OSCFDETEN_MASK) /** Enable/disable the check that sets OSCFFAIL interrupt flag if no * LFCLK-RTCC ticks are detected within one ULFRCO cycles. */ bool enaOSCFailDetect; #endif #if defined (_RTCC_CTRL_CNTMODE_MASK) /** Select operational mode of the counter. */ RTCC_CntMode_TypeDef cntMode; #endif #if defined (_RTCC_CTRL_LYEARCORRDIS_MASK) /** Disable leap year correction for calendar mode. When this parameter is * set to false, February has 29 days if (year % 4 == 0). If set to true, * February always has 28 days. */ bool disLeapYearCorr; #endif } RTCC_Init_TypeDef; /** RTCC capture/compare channel configuration structure. */ typedef struct { /** Select mode of Capture/Compare channel. */ RTCC_CapComChMode_TypeDef chMode; /** Compare mode channel match output action. */ RTCC_CompMatchOutAction_TypeDef compMatchOutAction; /** Capture mode channel PRS input channel selection. */ RTCC_PRSSel_TypeDef prsSel; /** Capture mode channel input edge selection. */ RTCC_InEdgeSel_TypeDef inputEdgeSel; /** Comparison base of channel in compare mode. */ RTCC_CompBase_TypeDef compBase; #if defined (_RTCC_CC_CTRL_COMPMASK_MASK) /** The COMPMASK (5 bit) most significant bits of compare value will not * be subject to comparison. */ uint8_t compMask; #endif #if defined (_RTCC_CC_CTRL_DAYCC_MASK) /** Day compare mode. */ RTCC_DayCompareMode_TypeDef dayCompMode; #endif } RTCC_CCChConf_TypeDef; /******************************************************************************* ******************************* DEFINES *********************************** ******************************************************************************/ /** Default RTCC initialization structure. */ #if defined(_SILICON_LABS_32B_SERIES_2) #define RTCC_INIT_DEFAULT \ { \ true, /* Start counting when init done. */ \ false, /* Disable RTCC during debug halt. */ \ false, /* Disable precounter wrap on ch. 0 CCV value. */ \ false, /* Disable counter wrap on ch. 1 CCV value. */ \ rtccCntPresc_32, /* 977 us per tick. */ \ rtccCntTickPresc, /* Counter increments according to prescaler value.*/ \ } #elif defined(_RTCC_CTRL_BUMODETSEN_MASK) #define RTCC_INIT_DEFAULT \ { \ true, /* Start counting when initialization is done. */ \ false, /* Disable RTCC during debug halt. */ \ false, /* Disable pre-counter wrap on ch. 0 CCV value. */ \ false, /* Disable counter wrap on ch. 1 CCV value. */ \ rtccCntPresc_32, /* 977 us per tick. */ \ rtccCntTickPresc, /* Counter increments according to prescaler value.*/ \ false, /* No RTCC storage on backup mode entry. */ \ false, /* No RTCC oscillator failure detection. */ \ rtccCntModeNormal, /* Normal RTCC mode. */ \ false, /* No leap year correction. */ \ } #else #define RTCC_INIT_DEFAULT \ { \ true, /* Start counting when initialization is done. */ \ false, /* Disable RTCC during debug halt. */ \ false, /* Disable pre-counter wrap on ch. 0 CCV value. */ \ false, /* Disable counter wrap on ch. 1 CCV value. */ \ rtccCntPresc_32, /* 977 us per tick. */ \ rtccCntTickPresc, /* Counter increments according to prescaler value.*/ \ false, /* No RTCC oscillator failure detection. */ \ rtccCntModeNormal, /* Normal RTCC mode. */ \ false, /* No leap year correction. */ \ } #endif #if defined(_SILICON_LABS_32B_SERIES_2) /** Default RTCC channel output compare initialization structure. */ #define RTCC_CH_INIT_COMPARE_DEFAULT \ { \ rtccCapComChModeCompare, /* Select output compare mode. */ \ rtccCompMatchOutActionPulse, /* Create pulse on compare match. */ \ 0, /* Don't care. */ \ rtccInEdgeNone, /* Don't care. */ \ rtccCompBaseCnt, /* Use CNT for comparison. */ \ } /** Default RTCC channel input capture initialization structure. */ #define RTCC_CH_INIT_CAPTURE_DEFAULT \ { \ rtccCapComChModeCapture, /* Select input capture mode. */ \ rtccCompMatchOutActionPulse, /* Don't care. */ \ 0, /* Use PRS channel 0 as trigger. */ \ rtccInEdgeRising, /* Capture on rising edge. */ \ rtccCompBaseCnt, /* Don't care. */ \ } #else // Series 1 devices /** Default RTCC channel output compare initialization structure. */ #define RTCC_CH_INIT_COMPARE_DEFAULT \ { \ rtccCapComChModeCompare, /* Select output compare mode. */ \ rtccCompMatchOutActionPulse, /* Create pulse on compare match.*/ \ 0, /* PRS channel 0 (not used). */ \ rtccInEdgeNone, /* No edge detection. */ \ rtccCompBaseCnt, /* Counter comparison base. */ \ 0, /* No compare mask bits set. */ \ rtccDayCompareModeMonth /* Don't care */ \ } /** Default RTCC channel input capture initialization structure. */ #define RTCC_CH_INIT_CAPTURE_DEFAULT \ { \ rtccCapComChModeCapture, /* Select input capture mode. */ \ rtccCompMatchOutActionPulse, /* Create pulse on capture. */ \ 0, /* PRS channel 0. */ \ rtccInEdgeRising, /* Rising edge detection. */ \ rtccCompBaseCnt, /* Don't care. */ \ 0, /* Don't care. */ \ rtccDayCompareModeMonth /* Don't care */ \ } #endif /** Number of RTCC capture/compare channels */ #if !defined(RTCC_CC_NUM) #define RTCC_CC_NUM 3UL #endif /** Validation of valid RTCC channel for assert statements. */ #define RTCC_CH_VALID(ch) ((unsigned)(ch) < RTCC_CC_NUM) /******************************************************************************* ***************************** PROTOTYPES ********************************** ******************************************************************************/ /***************************************************************************//** * @brief * Get the RTCC compare register value for a selected channel. * * @param[in] ch * Channel selector. * * @return * Compare register value. ******************************************************************************/ __STATIC_INLINE uint32_t RTCC_ChannelCompareValueGet(int ch) { EFM_ASSERT(RTCC_CH_VALID(ch) ); #if defined (_RTCC_CC_CCV_MASK) return RTCC->CC[ch].CCV; #elif defined (_RTCC_CC_OCVALUE_MASK) return RTCC->CC[ch].OCVALUE; #endif } /***************************************************************************//** * @brief * Set the RTCC compare register value for a selected channel. * * @param[in] ch * Channel selector. * * @param[in] value * Compare register value ******************************************************************************/ __STATIC_INLINE void RTCC_ChannelCompareValueSet(int ch, uint32_t value) { EFM_ASSERT(RTCC_CH_VALID(ch) ); #if defined (_RTCC_CC_CCV_MASK) RTCC->CC[ch].CCV = value; #elif defined (_RTCC_CC_OCVALUE_MASK) RTCC->CC[ch].OCVALUE = value; #endif } /***************************************************************************//** * @brief * Get the RTCC input capture register value for a selected channel. * * @param[in] ch * Channel selector. * * @return * Capture register value. ******************************************************************************/ __STATIC_INLINE uint32_t RTCC_ChannelCaptureValueGet(int ch) { EFM_ASSERT(RTCC_CH_VALID(ch) ); #if defined (_RTCC_CC_CCV_MASK) return RTCC->CC[ch].CCV; #elif defined (_RTCC_CC_ICVALUE_MASK) return RTCC->CC[ch].ICVALUE; #endif } /***************************************************************************//** * @brief * Get the RTCC capture/compare register value for a selected channel. * For parts with separate capture compare value registers, this function * returns the compare value. * * @param[in] ch * Channel selector. * * @return * Capture/compare register value. ******************************************************************************/ __STATIC_INLINE uint32_t RTCC_ChannelCCVGet(int ch) { return RTCC_ChannelCompareValueGet(ch); } /***************************************************************************//** * @brief * Set RTCC capture/compare register value for a selected channel. * For parts with separate capture compare value registers, this function * sets the compare value. * * @param[in] ch * Channel selector. * * @param[in] value * Capture/compare register value ******************************************************************************/ __STATIC_INLINE void RTCC_ChannelCCVSet(int ch, uint32_t value) { RTCC_ChannelCompareValueSet(ch, value); } #if defined (_RTCC_CC_DATE_MASK) /***************************************************************************//** * @brief * Get the calendar DATE register content for a selected channel. * * @param[in] ch * Channel selector. * * @return * DATE register value. ******************************************************************************/ __STATIC_INLINE uint32_t RTCC_ChannelDateGet(int ch) { EFM_ASSERT(RTCC_CH_VALID(ch) ); return RTCC->CC[ch].DATE; } /***************************************************************************//** * @brief * Set the calendar DATE register for a selected channel. * * @param[in] ch * Channel selector. * * @param[in] date * DATE value. ******************************************************************************/ __STATIC_INLINE void RTCC_ChannelDateSet(int ch, uint32_t date) { EFM_ASSERT(RTCC_CH_VALID(ch) ); RTCC->CC[ch].DATE = date; } /***************************************************************************//** * @brief * Get the calendar TIME register content for a selected channel. * * @param[in] ch * Channel selector. * * @return * TIME register value. ******************************************************************************/ __STATIC_INLINE uint32_t RTCC_ChannelTimeGet(int ch) { EFM_ASSERT(RTCC_CH_VALID(ch) ); return RTCC->CC[ch].TIME; } /***************************************************************************//** * @brief * Set the calendar TIME register for a selected channel. * * @param[in] ch * Channel selector. * * @param[in] time * TIME value. ******************************************************************************/ __STATIC_INLINE void RTCC_ChannelTimeSet(int ch, uint32_t time) { EFM_ASSERT(RTCC_CH_VALID(ch) ); RTCC->CC[ch].TIME = time; } #endif /* defined (_RTCC_CC_DATE_MASK) */ /***************************************************************************//** * @brief * Get the combined CNT/PRECNT register content. * * @return * CNT/PRECNT register value. ******************************************************************************/ __STATIC_INLINE uint32_t RTCC_CombinedCounterGet(void) { #if defined (RTCC_SYNCBUSY_CNT) || defined (RTCC_SYNCBUSY_CNT) while ((RTCC->SYNCBUSY & (RTCC_SYNCBUSY_CNT | RTCC_SYNCBUSY_PRECNT)) != 0U) { /* Wait for CNT and PRECNT to synchronize */ } #endif return RTCC->COMBCNT; } /***************************************************************************//** * @brief * Get the RTCC counter value. * * @return * Current RTCC counter value. ******************************************************************************/ __STATIC_INLINE uint32_t RTCC_CounterGet(void) { #if defined (RTCC_SYNCBUSY_CNT) while ((RTCC->SYNCBUSY & RTCC_SYNCBUSY_CNT) != 0U) { /* Wait for CNT to synchronize before getting value */ } #endif return RTCC->CNT; } /***************************************************************************//** * @brief * Set the RTCC CNT counter. * * @param[in] value * CNT value. ******************************************************************************/ __STATIC_INLINE void RTCC_CounterSet(uint32_t value) { #if defined (RTCC_SYNCBUSY_CNT) while ((RTCC->SYNCBUSY & RTCC_SYNCBUSY_CNT) != 0U) { /* Wait for CNT to synchronize before setting new value */ } #endif RTCC->CNT = value; } #if defined (_RTCC_CC_DATE_MASK) /***************************************************************************//** * @brief * Get the DATE register value. * * @return * Current DATE register value. ******************************************************************************/ __STATIC_INLINE uint32_t RTCC_DateGet(void) { return RTCC->DATE; } /***************************************************************************//** * @brief * Set the RTCC DATE register. * * @param[in] date * DATE value. ******************************************************************************/ __STATIC_INLINE void RTCC_DateSet(uint32_t date) { RTCC->DATE = date; } #endif /* defined (_RTCC_CC_DATE_MASK) */ #if defined (RTCC_EM4WUEN_EM4WU) /***************************************************************************//** * @brief * Enable/disable EM4 wakeup capability. * * @param[in] enable * Set to true to enable EM4 wakeup, set to false otherwise. ******************************************************************************/ __STATIC_INLINE void RTCC_EM4WakeupEnable(bool enable) { if ( enable ) { RTCC->EM4WUEN = RTCC_EM4WUEN_EM4WU; } else { RTCC->EM4WUEN = 0; } } #endif void RTCC_Enable(bool enable); void RTCC_Init(const RTCC_Init_TypeDef *init); void RTCC_ChannelInit(int ch, RTCC_CCChConf_TypeDef const *confPtr); /***************************************************************************//** * @brief * Clear one or more pending RTCC interrupts. * * @param[in] flags * RTCC interrupt sources to clear. Use a set of interrupt flags OR-ed * together to clear multiple interrupt sources. ******************************************************************************/ __STATIC_INLINE void RTCC_IntClear(uint32_t flags) { #if defined (RTCC_HAS_SET_CLEAR) RTCC->IF_CLR = flags; #else RTCC->IFC = flags; #endif } /***************************************************************************//** * @brief * Disable one or more RTCC interrupts. * * @param[in] flags * RTCC interrupt sources to disable. Use a set of interrupt flags OR-ed * together to disable multiple interrupt. ******************************************************************************/ __STATIC_INLINE void RTCC_IntDisable(uint32_t flags) { RTCC->IEN &= ~flags; } /***************************************************************************//** * @brief * Enable one or more RTCC interrupts. * * @note * Depending on the use, a pending interrupt may already be set prior to * enabling the interrupt. To ignore a pending interrupt, consider using * RTCC_IntClear() prior to enabling the interrupt. * * @param[in] flags * RTCC interrupt sources to enable. Use a set of interrupt flags OR-ed * together to set multiple interrupt. ******************************************************************************/ __STATIC_INLINE void RTCC_IntEnable(uint32_t flags) { RTCC->IEN |= flags; } /***************************************************************************//** * @brief * Get pending RTCC interrupt flags. * * @note * Event bits are not cleared by using this function. * * @return * Pending RTCC interrupt sources. Returns a set of interrupt flags OR-ed * together for the interrupt sources set. ******************************************************************************/ __STATIC_INLINE uint32_t RTCC_IntGet(void) { return RTCC->IF; } /***************************************************************************//** * @brief * Get enabled and pending RTCC interrupt flags. * * @details * Useful for handling more interrupt sources in the same interrupt handler. * * @return * Pending and enabled RTCC interrupt sources. Returns a set of interrupt * flags OR-ed together for the interrupt sources set. ******************************************************************************/ __STATIC_INLINE uint32_t RTCC_IntGetEnabled(void) { uint32_t tmp; tmp = RTCC->IEN; /* Bitwise AND of pending and enabled interrupt flags. */ return RTCC->IF & tmp; } /***************************************************************************//** * @brief * Set one or more pending RTCC interrupts from SW. * * @param[in] flags * RTCC interrupt sources to set to pending. Use a set of interrupt flags * (RTCC_IFS_nnn). ******************************************************************************/ __STATIC_INLINE void RTCC_IntSet(uint32_t flags) { #if defined (RTCC_HAS_SET_CLEAR) RTCC->IF_SET = flags; #else RTCC->IFS = flags; #endif } /***************************************************************************//** * @brief * Lock RTCC registers. * * @note * When RTCC registers are locked, RTCC_CTRL, RTCC_PRECNT, RTCC_CNT, * RTCC_TIME, RTCC_DATE, RTCC_IEN, RTCC_POWERDOWN and RTCC_CCx_XXX registers * cannot be written to. ******************************************************************************/ __STATIC_INLINE void RTCC_Lock(void) { #if defined(ERRATA_FIX_RTCC_E203) /* RTCC_E203 - Potential Stability Issue with RTCC Registers. * RTCC_LOCK register must be modified while RTCC clock is disabled. */ uint32_t lfeReg = CMU->LFECLKEN0; bool cmuLocked = (CMU->LOCK == CMU_LOCK_LOCKKEY_LOCKED); if (cmuLocked) { CMU->LOCK = CMU_LOCK_LOCKKEY_UNLOCK; } CMU->LFECLKEN0 = 0x0; #endif RTCC->LOCK = ~RTCC_LOCK_LOCKKEY_UNLOCK; #if defined(ERRATA_FIX_RTCC_E203) /* Restore clock state after RTCC_E203 fix. */ CMU->LFECLKEN0 = lfeReg; if (cmuLocked) { CMU->LOCK = CMU_LOCK_LOCKKEY_LOCK; } #endif } /***************************************************************************//** * @brief * Get the RTCC pre-counter value. * * @return * Current RTCC pre-counter value. ******************************************************************************/ __STATIC_INLINE uint32_t RTCC_PreCounterGet(void) { #if defined (RTCC_SYNCBUSY_PRECNT) while ((RTCC->SYNCBUSY & RTCC_SYNCBUSY_PRECNT) != 0U) { /* Wait for PRECNT to synchronize */ } #endif return RTCC->PRECNT; } /***************************************************************************//** * @brief * Set the RTCC pre-counter value. * * @param[in] preCntVal * RTCC pre-counter value to be set. ******************************************************************************/ __STATIC_INLINE void RTCC_PreCounterSet(uint32_t preCntVal) { #if defined (RTCC_SYNCBUSY_PRECNT) while ((RTCC->SYNCBUSY & RTCC_SYNCBUSY_PRECNT) != 0U) { /* Wait for PRECNT to synchronize */ } #endif RTCC->PRECNT = preCntVal; } void RTCC_Reset(void); #if defined (_RTCC_POWERDOWN_MASK) /***************************************************************************//** * @brief * Power down retention RAM. * * @note * Once retention RAM is powered down, it cannot be powered up again. ******************************************************************************/ __STATIC_INLINE void RTCC_RetentionRamPowerDown(void) { #if !defined(ERRATA_FIX_RTCC_E204) /* Devices that are affected by RTCC_E204 should always keep RTCC * backup RAM retained. */ RTCC->POWERDOWN = RTCC_POWERDOWN_RAM; #endif } #endif void RTCC_StatusClear(void); /***************************************************************************//** * @brief * Get the STATUS register value. * * @return * Current STATUS register value. ******************************************************************************/ __STATIC_INLINE uint32_t RTCC_StatusGet(void) { #if defined (RTCC_SYNCBUSY_CMD) while ((RTCC->SYNCBUSY & RTCC_SYNCBUSY_CMD) != 0U) { // Wait for synchronization. } #elif defined (RTCC_SYNCBUSY_START) while ((RTCC->SYNCBUSY & (RTCC_SYNCBUSY_START | RTCC_SYNCBUSY_STOP)) != 0U) { /* Wait for synchronization. */ } #endif return RTCC->STATUS; } #if defined(_SILICON_LABS_32B_SERIES_2) /***************************************************************************//** * @brief * Wait for the RTCC to complete all synchronization of register changes * and commands. ******************************************************************************/ __STATIC_INLINE void RTCC_SyncWait(void) { while ((RTCC->EN != 0U) && (RTCC->SYNCBUSY != 0U)) { /* Wait for synchronization to finish */ } } /***************************************************************************//** * @brief * Start the RTCC counter. * * @details * This function will send a start command to the RTCC peripheral. The RTCC * peripheral will use some LF clock ticks before the command is executed. * The @ref RTCC_SyncWait() function can be used to wait for the start command * to be executed. * * @note * This function requires the RTCC to be enabled. ******************************************************************************/ __STATIC_INLINE void RTCC_Start(void) { RTCC_SyncWait(); RTCC->CMD = RTCC_CMD_START; } /***************************************************************************//** * @brief * Stop the RTCC counter. * * @details * This function will send a stop command to the RTCC peripheral. The RTCC * peripheral will use some LF clock ticks before the command is executed. * The @ref RTCC_SyncWait() function can be used to wait for the stop command * to be executed. * * @note * This function requires the RTCC to be enabled. ******************************************************************************/ __STATIC_INLINE void RTCC_Stop(void) { RTCC_SyncWait(); RTCC->CMD = RTCC_CMD_STOP; } #endif #if defined (_RTCC_TIME_MASK) /***************************************************************************//** * @brief * Get the TIME register value. * * @return * Current TIME register value. ******************************************************************************/ __STATIC_INLINE uint32_t RTCC_TimeGet(void) { return RTCC->TIME; } /***************************************************************************//** * @brief * Set the RTCC TIME register. * * @param[in] time * TIME value. ******************************************************************************/ __STATIC_INLINE void RTCC_TimeSet(uint32_t time) { RTCC->TIME = time; } #endif /***************************************************************************//** * @brief * Unlock RTCC registers. * * @note * When RTCC registers are locked, RTCC_CTRL, RTCC_PRECNT, RTCC_CNT, * RTCC_TIME, RTCC_DATE, RTCC_IEN, RTCC_POWERDOWN and RTCC_CCx_XXX registers * cannot be written to. ******************************************************************************/ __STATIC_INLINE void RTCC_Unlock(void) { #if defined(ERRATA_FIX_RTCC_E203) /* RTCC_E203 - Potential Stability Issue with RTCC Registers. * RTCC_LOCK register must be modified while RTCC clock is disabled. */ uint32_t lfeReg = CMU->LFECLKEN0; bool cmuLocked = (CMU->LOCK == CMU_LOCK_LOCKKEY_LOCKED); if (cmuLocked) { CMU->LOCK = CMU_LOCK_LOCKKEY_UNLOCK; } CMU->LFECLKEN0 = 0x0; #endif RTCC->LOCK = RTCC_LOCK_LOCKKEY_UNLOCK; #if defined(ERRATA_FIX_RTCC_E203) /* Restore clock state after RTCC_E203 fix. */ CMU->LFECLKEN0 = lfeReg; if (cmuLocked) { CMU->LOCK = CMU_LOCK_LOCKKEY_LOCK; } #endif } /** @} (end addtogroup rtcc) */ #ifdef __cplusplus } #endif #endif /* defined( RTCC_COUNT ) && ( RTC_COUNT == 1 ) */ #endif /* EM_RTCC_H */