| /***************************************************************************//** |
| * @file em_cryotimer.h |
| * @brief Ultra Low Energy Timer/Counter (CRYOTIMER) peripheral API |
| * @version 5.6.0 |
| ******************************************************************************* |
| * # License |
| * <b>Copyright 2016 Silicon Laboratories, Inc. www.silabs.com</b> |
| ******************************************************************************* |
| * |
| * 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.@n |
| * 2. Altered source versions must be plainly marked as such, and must not be |
| * misrepresented as being the original software.@n |
| * 3. This notice may not be removed or altered from any source distribution. |
| * |
| * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no |
| * obligation to support this Software. Silicon Labs is providing the |
| * Software "AS IS", with no express or implied warranties of any kind, |
| * including, but not limited to, any implied warranties of merchantability |
| * or fitness for any particular purpose or warranties against infringement |
| * of any proprietary rights of a third party. |
| * |
| * Silicon Labs will not be liable for any consequential, incidental, or |
| * special damages, or any other relief, or for any claim by any third party, |
| * arising from your use of this Software. |
| * |
| ******************************************************************************/ |
| |
| #ifndef EM_CRYOTIMER_H |
| #define EM_CRYOTIMER_H |
| |
| #include <stdbool.h> |
| #include "em_device.h" |
| #include "em_bus.h" |
| |
| #if defined(CRYOTIMER_PRESENT) && (CRYOTIMER_COUNT == 1) |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /***************************************************************************//** |
| * @addtogroup emlib |
| * @{ |
| ******************************************************************************/ |
| |
| /***************************************************************************//** |
| * @addtogroup CRYOTIMER |
| * @brief Ultra Low Energy Timer/Counter (CRYOTIMER) Peripheral API |
| * |
| * @details |
| * The CRYOTIMER is a 32 bit counter which operates on a low-frequency |
| * oscillator and is capable of running in all Energy Modes. It can provide |
| * periodic wakeup events and PRS signals which can be used to wake up |
| * peripherals from any energy mode. The CRYOTIMER provides a very wide range |
| * of periods for the interrupts facilitating flexible ultra-low energy |
| * operation. Because of its simplicity, the CRYOTIMER is a lower energy |
| * solution for periodically waking up the MCU compared to the RTCC. |
| * |
| * To configure the CRYOTIMER, call the @ref CRYOTIMER_Init function. |
| * This function will configure the CRYOTIMER peripheral according to the |
| * user configuration. |
| * |
| * @details |
| * When using the CRYOTIMER, choose which oscillator to use |
| * as the CRYOTIMER clock. The CRYOTIMER supports 3 low-frequency clocks |
| * LFXO, LFRCO, and ULFRCO. The oscillator that is chosen must be |
| * enabled and ready before calling this @ref CRYOTIMER_Init function. |
| * See @ref CMU_OscillatorEnable for details of how to enable and wait for an |
| * oscillator to become ready. Note that ULFRCO is always ready while LFRCO |
| * @ref cmuOsc_LFRCO and LFXO @ref cmuOsc_LFXO must be enabled by the user. |
| * |
| * @details |
| * Note that the only oscillator which is running in EM3 is ULFRCO. Keep this |
| * in mind when choosing which oscillator to use for the CRYOTIMER. |
| * |
| * This example shows how to use the CRYOTIMER to generate an interrupt |
| * at a configurable period. |
| * |
| * @include em_cryotimer_period.c |
| * |
| * @details |
| * To use the CRYOTIMER in EM4, enable EM4 wakeup in the |
| * CRYOTIMER. This can be done either in the @ref CRYOTIMER_Init_TypeDef |
| * structure when initializing the CRYOTIMER or at a later time by using |
| * @ref CRYOTIMER_EM4WakeupEnable. |
| * |
| * Note that when using the CRYOTIMER to wake up from EM4, the application has |
| * the responsibility to clear the wakeup event. This is done by calling |
| * @ref CRYOTIMER_IntClear. If the user does not clear the wakeup event, |
| * the wakeup event will stay pending and will cause an immediate wakeup the |
| * next time the application attempts to enter EM4. |
| * |
| * This example shows how to use the CRYOTIMER to wake up from EM4 after |
| * a configurable amount of time. |
| * |
| * @include em_cryotimer_em4.c |
| * |
| * @details |
| * All the low frequency oscillators can be used in EM4, however, the |
| * oscillator that is used must be be configured to be retained when going |
| * into EM4. This can be configured by using functions in the @ref EMU module. |
| * See @ref EMU_EM4Init and @ref EMU_EM4Init_TypeDef. If an oscillator is |
| * retained in EM4, the user is also responsible for unlatching the retained |
| * configuration on a wakeup from EM4. |
| * |
| * @{ |
| ******************************************************************************/ |
| |
| /******************************************************************************* |
| ********************************* ENUM ************************************ |
| ******************************************************************************/ |
| |
| /** Prescaler selection. */ |
| typedef enum { |
| cryotimerPresc_1 = _CRYOTIMER_CTRL_PRESC_DIV1, /**< Divide clock by 1. */ |
| cryotimerPresc_2 = _CRYOTIMER_CTRL_PRESC_DIV2, /**< Divide clock by 2. */ |
| cryotimerPresc_4 = _CRYOTIMER_CTRL_PRESC_DIV4, /**< Divide clock by 4. */ |
| cryotimerPresc_8 = _CRYOTIMER_CTRL_PRESC_DIV8, /**< Divide clock by 8. */ |
| cryotimerPresc_16 = _CRYOTIMER_CTRL_PRESC_DIV16, /**< Divide clock by 16. */ |
| cryotimerPresc_32 = _CRYOTIMER_CTRL_PRESC_DIV32, /**< Divide clock by 32. */ |
| cryotimerPresc_64 = _CRYOTIMER_CTRL_PRESC_DIV64, /**< Divide clock by 64. */ |
| cryotimerPresc_128 = _CRYOTIMER_CTRL_PRESC_DIV128, /**< Divide clock by 128. */ |
| } CRYOTIMER_Presc_TypeDef; |
| |
| /** Low frequency oscillator selection. */ |
| typedef enum { |
| cryotimerOscLFRCO = _CRYOTIMER_CTRL_OSCSEL_LFRCO, /**< Select Low-frequency RC Oscillator. */ |
| cryotimerOscLFXO = _CRYOTIMER_CTRL_OSCSEL_LFXO, /**< Select Low-frequency Crystal Oscillator. */ |
| cryotimerOscULFRCO = _CRYOTIMER_CTRL_OSCSEL_ULFRCO, /**< Select Ultra Low Frequency RC Oscillator. */ |
| } CRYOTIMER_Osc_TypeDef; |
| |
| /** Period selection value */ |
| typedef enum { |
| cryotimerPeriod_1 = 0, /**< Wakeup event after every Pre-scaled clock cycle. */ |
| cryotimerPeriod_2 = 1, /**< Wakeup event after 2 Pre-scaled clock cycles. */ |
| cryotimerPeriod_4 = 2, /**< Wakeup event after 4 Pre-scaled clock cycles. */ |
| cryotimerPeriod_8 = 3, /**< Wakeup event after 8 Pre-scaled clock cycles. */ |
| cryotimerPeriod_16 = 4, /**< Wakeup event after 16 Pre-scaled clock cycles. */ |
| cryotimerPeriod_32 = 5, /**< Wakeup event after 32 Pre-scaled clock cycles. */ |
| cryotimerPeriod_64 = 6, /**< Wakeup event after 64 Pre-scaled clock cycles. */ |
| cryotimerPeriod_128 = 7, /**< Wakeup event after 128 Pre-scaled clock cycles. */ |
| cryotimerPeriod_256 = 8, /**< Wakeup event after 256 Pre-scaled clock cycles. */ |
| cryotimerPeriod_512 = 9, /**< Wakeup event after 512 Pre-scaled clock cycles. */ |
| cryotimerPeriod_1k = 10, /**< Wakeup event after 1k Pre-scaled clock cycles. */ |
| cryotimerPeriod_2k = 11, /**< Wakeup event after 2k Pre-scaled clock cycles. */ |
| cryotimerPeriod_4k = 12, /**< Wakeup event after 4k Pre-scaled clock cycles. */ |
| cryotimerPeriod_8k = 13, /**< Wakeup event after 8k Pre-scaled clock cycles. */ |
| cryotimerPeriod_16k = 14, /**< Wakeup event after 16k Pre-scaled clock cycles. */ |
| cryotimerPeriod_32k = 15, /**< Wakeup event after 32k Pre-scaled clock cycles. */ |
| cryotimerPeriod_64k = 16, /**< Wakeup event after 64k Pre-scaled clock cycles. */ |
| cryotimerPeriod_128k = 17, /**< Wakeup event after 128k Pre-scaled clock cycles. */ |
| cryotimerPeriod_256k = 18, /**< Wakeup event after 256k Pre-scaled clock cycles. */ |
| cryotimerPeriod_512k = 19, /**< Wakeup event after 512k Pre-scaled clock cycles. */ |
| cryotimerPeriod_1m = 20, /**< Wakeup event after 1m Pre-scaled clock cycles. */ |
| cryotimerPeriod_2m = 21, /**< Wakeup event after 2m Pre-scaled clock cycles. */ |
| cryotimerPeriod_4m = 22, /**< Wakeup event after 4m Pre-scaled clock cycles. */ |
| cryotimerPeriod_8m = 23, /**< Wakeup event after 8m Pre-scaled clock cycles. */ |
| cryotimerPeriod_16m = 24, /**< Wakeup event after 16m Pre-scaled clock cycles. */ |
| cryotimerPeriod_32m = 25, /**< Wakeup event after 32m Pre-scaled clock cycles. */ |
| cryotimerPeriod_64m = 26, /**< Wakeup event after 64m Pre-scaled clock cycles. */ |
| cryotimerPeriod_128m = 27, /**< Wakeup event after 128m Pre-scaled clock cycles. */ |
| cryotimerPeriod_256m = 28, /**< Wakeup event after 256m Pre-scaled clock cycles. */ |
| cryotimerPeriod_512m = 29, /**< Wakeup event after 512m Pre-scaled clock cycles. */ |
| cryotimerPeriod_1024m = 30, /**< Wakeup event after 1024m Pre-scaled clock cycles. */ |
| cryotimerPeriod_2048m = 31, /**< Wakeup event after 2048m Pre-scaled clock cycles. */ |
| cryotimerPeriod_4096m = 32, /**< Wakeup event after 4096m Pre-scaled clock cycles. */ |
| } CRYOTIMER_Period_TypeDef; |
| |
| /******************************************************************************* |
| ******************************* STRUCTURES *********************************** |
| ******************************************************************************/ |
| |
| /** CRYOTIMER initialization structure. */ |
| typedef struct { |
| /** Enable/disable counting when initialization is complete. */ |
| bool enable; |
| |
| /** Enable/disable timer counting during debug halt. */ |
| bool debugRun; |
| |
| /** Enable/disable EM4 Wakeup. */ |
| bool em4Wakeup; |
| |
| /** Select the oscillator for the CRYOTIMER. */ |
| CRYOTIMER_Osc_TypeDef osc; |
| |
| /** Prescaler. */ |
| CRYOTIMER_Presc_TypeDef presc; |
| |
| /** A period between a wakeup event/interrupt. */ |
| CRYOTIMER_Period_TypeDef period; |
| } CRYOTIMER_Init_TypeDef; |
| |
| /******************************************************************************* |
| ******************************* DEFINES *********************************** |
| ******************************************************************************/ |
| |
| /** Default CRYOTIMER init structure. */ |
| #define CRYOTIMER_INIT_DEFAULT \ |
| { \ |
| true, /* Start counting when the initialization is done. */ \ |
| false, /* Disable CRYOTIMER during debug halt. */ \ |
| false, /* Disable EM4 wakeup. */ \ |
| cryotimerOscLFRCO, /* Select Low Frequency RC Oscillator. */ \ |
| cryotimerPresc_1, /* LF Oscillator frequency undivided. */ \ |
| cryotimerPeriod_4096m, /* Wakeup event after 4096 M pre-scaled clock cycles. */ \ |
| } |
| |
| /******************************************************************************* |
| ***************************** PROTOTYPES ********************************** |
| ******************************************************************************/ |
| |
| /***************************************************************************//** |
| * @brief |
| * Clear the CRYOTIMER period interrupt. |
| * |
| * @param[in] flags |
| * CRYOTIMER interrupt sources to clear. Use @ref CRYOTIMER_IFC_PERIOD. |
| ******************************************************************************/ |
| __STATIC_INLINE void CRYOTIMER_IntClear(uint32_t flags) |
| { |
| CRYOTIMER->IFC = flags & _CRYOTIMER_IFC_MASK; |
| } |
| |
| /***************************************************************************//** |
| * @brief |
| * Get the CRYOTIMER interrupt flag. |
| * |
| * @note |
| * This function does not clear event bits. |
| * |
| * @return |
| * Pending CRYOTIMER interrupt sources. The only interrupt source available |
| * for the CRYOTIMER is @ref CRYOTIMER_IF_PERIOD. |
| ******************************************************************************/ |
| __STATIC_INLINE uint32_t CRYOTIMER_IntGet(void) |
| { |
| return CRYOTIMER->IF; |
| } |
| |
| /***************************************************************************//** |
| * @brief |
| * Get enabled and pending CRYOTIMER interrupt flags. |
| * Useful for handling more interrupt sources in the same interrupt handler. |
| * |
| * @note |
| * This function does not clear interrupt flags. |
| * |
| * @return |
| * Pending and enabled CRYOTIMER interrupt sources. |
| * The return value is the bitwise AND of |
| * - the enabled interrupt sources in CRYOTIMER_IEN and |
| * - the pending interrupt flags CRYOTIMER_IF |
| ******************************************************************************/ |
| __STATIC_INLINE uint32_t CRYOTIMER_IntGetEnabled(void) |
| { |
| uint32_t ien; |
| |
| ien = CRYOTIMER->IEN & _CRYOTIMER_IEN_MASK; |
| return CRYOTIMER->IF & ien; |
| } |
| |
| /***************************************************************************//** |
| * @brief |
| * Enable one or more CRYOTIMER interrupts. |
| * |
| * @param[in] flags |
| * CRYOTIMER interrupt sources to enable. Use @ref CRYOTIMER_IEN_PERIOD. |
| ******************************************************************************/ |
| __STATIC_INLINE void CRYOTIMER_IntEnable(uint32_t flags) |
| { |
| CRYOTIMER->IEN |= (flags & _CRYOTIMER_IEN_MASK); |
| } |
| |
| /***************************************************************************//** |
| * @brief |
| * Disable one or more CRYOTIMER interrupts. |
| * |
| * @param[in] flags |
| * CRYOTIMER interrupt sources to disable. Use @ref CRYOTIMER_IEN_PERIOD. |
| ******************************************************************************/ |
| __STATIC_INLINE void CRYOTIMER_IntDisable(uint32_t flags) |
| { |
| CRYOTIMER->IEN &= ~(flags & _CRYOTIMER_IEN_MASK); |
| } |
| |
| /***************************************************************************//** |
| * @brief |
| * Set the CRYOTIMER period interrupt flag. |
| * |
| * @note |
| * Writes 1 to the interrupt flag set register. |
| * |
| * @param[in] flags |
| * CRYOTIMER interrupt sources to set to pending. Use |
| * @ref CRYOTIMER_IFS_PERIOD. |
| ******************************************************************************/ |
| __STATIC_INLINE void CRYOTIMER_IntSet(uint32_t flags) |
| { |
| CRYOTIMER->IFS = flags & _CRYOTIMER_IFS_MASK; |
| } |
| |
| /***************************************************************************//** |
| * @brief |
| * Set the CRYOTIMER period select. |
| * |
| * @note |
| * Sets the duration between the interrupts/wakeup events based on |
| * the pre-scaled clock. |
| * |
| * @param[in] period |
| * 2^period is the number of clock cycles before a wakeup event or |
| * interrupt is triggered. The CRYOTIMER_Periodsel_TypeDef enumeration can |
| * be used a convenience type when calling this function. |
| ******************************************************************************/ |
| __STATIC_INLINE void CRYOTIMER_PeriodSet(uint32_t period) |
| { |
| CRYOTIMER->PERIODSEL = period & _CRYOTIMER_PERIODSEL_MASK; |
| } |
| |
| /***************************************************************************//** |
| * @brief |
| * Get the CRYOTIMER period select value. |
| * |
| * @note |
| * Gets the duration between the interrupts/wakeup events in the |
| * CRYOTIMER. |
| * |
| * @return |
| * Duration between the interrupts/wakeup events. Returns the value |
| * of the PERIODSEL register. The number of clock cycles can be calculated |
| * as the 2^n where n is the return value of this function. |
| ******************************************************************************/ |
| __STATIC_INLINE uint32_t CRYOTIMER_PeriodGet(void) |
| { |
| return CRYOTIMER->PERIODSEL; |
| } |
| |
| /***************************************************************************//** |
| * @brief |
| * Get the CRYOTIMER counter value. |
| * |
| * @return |
| * Returns the current CRYOTIMER counter value. |
| ******************************************************************************/ |
| __STATIC_INLINE uint32_t CRYOTIMER_CounterGet(void) |
| { |
| return CRYOTIMER->CNT; |
| } |
| |
| /***************************************************************************//** |
| * @brief |
| * Enable/disable EM4 wakeup capability. |
| * |
| * @param[in] enable |
| * True to enable EM4 wakeup, false to disable. |
| ******************************************************************************/ |
| __STATIC_INLINE void CRYOTIMER_EM4WakeupEnable(bool enable) |
| { |
| BUS_RegBitWrite((&CRYOTIMER->EM4WUEN), |
| _CRYOTIMER_EM4WUEN_EM4WU_SHIFT, |
| (uint32_t)enable); |
| } |
| |
| /***************************************************************************//** |
| * @brief |
| * Enable/disable the CRYOTIMER. |
| * |
| * @param[in] enable |
| * True to enable the CRYOTIMER, false to disable. |
| ******************************************************************************/ |
| __STATIC_INLINE void CRYOTIMER_Enable(bool enable) |
| { |
| BUS_RegBitWrite((&CRYOTIMER->CTRL), |
| _CRYOTIMER_CTRL_EN_SHIFT, |
| (uint32_t)enable); |
| } |
| |
| void CRYOTIMER_Init(const CRYOTIMER_Init_TypeDef *init); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| /** @} (end addtogroup CRYOTIMER) */ |
| /** @} (end addtogroup emlib) */ |
| |
| #endif /* defined(CRYOTIMER_PRESENT) && (CRYOTIMER_COUNT == 1) */ |
| #endif /* EM_CRYOTIMER_H */ |