t
Fork of mbed-dev by
Diff: targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/rtc_api.c
- Revision:
- 50:a417edff4437
- Parent:
- 0:9b334a45a8ff
- Child:
- 144:ef7eb2e8f9f7
diff -r 57ac6e3cdfd3 -r a417edff4437 targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/rtc_api.c --- a/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/rtc_api.c Wed Jan 13 12:45:11 2016 +0000 +++ b/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/rtc_api.c Fri Jan 15 07:45:16 2016 +0000 @@ -34,10 +34,17 @@ #include "rtc_api.h" #include "rtc_api_HAL.h" #include "em_cmu.h" -#include "em_rtc.h" #include "sleep_api.h" #include "sleepmodes.h" +#if (defined RTC_COUNT) && (RTC_COUNT > 0) +#include "em_rtc.h" +#endif + +#if (defined RTCC_COUNT) && (RTCC_COUNT > 0) +#include "em_rtcc.h" +#endif + static bool rtc_inited = false; static time_t time_base = 0; static uint32_t useflags = 0; @@ -45,6 +52,10 @@ static void (*comp0_handler)(void) = NULL; +#ifndef RTCC_COUNT + +/* Using RTC API */ + #define RTC_LEAST_ACTIVE_SLEEPMODE EM2 #define RTC_NUM_BITS (24) @@ -65,12 +76,12 @@ } } -uint32_t rtc_get_32bit(void) +uint32_t rtc_get_32bit(void) { return (RTC_CounterGet() + (time_extend << RTC_NUM_BITS)); } -uint64_t rtc_get_full(void) +uint64_t rtc_get_full(void) { uint64_t ticks = 0; ticks += time_extend; @@ -79,18 +90,6 @@ return ticks; } -void rtc_set_comp0_handler(uint32_t handler) -{ - comp0_handler = (void (*)(void)) handler; -} - -void rtc_init(void) -{ - /* Register that the RTC is used for timekeeping. */ - rtc_init_real(RTC_INIT_RTC); -} - - void rtc_init_real(uint32_t flags) { useflags |= flags; @@ -143,6 +142,113 @@ } } +#else + +/* Using RTCC API */ + +#define RTCC_LEAST_ACTIVE_SLEEPMODE EM2 +#define RTCC_NUM_BITS (32) + +void RTCC_IRQHandler(void) +{ + uint32_t flags; + flags = RTCC_IntGet(); + + if (flags & RTCC_IF_OF) { + RTCC_IntClear(RTCC_IF_OF); + /* RTC has overflowed (32 bits). Use time_extend as software counter for 32 more bits. */ + time_extend += 1; + } + + if (flags & RTCC_IF_CC0) { + RTCC_IntClear(RTCC_IF_CC0); + if (comp0_handler != NULL) { + comp0_handler(); + } + } +} + +uint32_t rtc_get_32bit(void) +{ + return RTCC_CounterGet(); +} + +uint64_t rtc_get_full(void) +{ + uint64_t ticks = 0; + ticks += time_extend; + ticks = ticks << RTCC_NUM_BITS; + ticks += RTCC_CounterGet(); + return ticks; +} + +void rtc_init_real(uint32_t flags) +{ + useflags |= flags; + + if (!rtc_inited) { + CMU_ClockEnable(cmuClock_RTCC, true); + + /* Enable clock to the interface of the low energy modules */ + CMU_ClockEnable(cmuClock_CORELE, true); + + /* Initialize RTC */ + RTCC_Init_TypeDef init = RTCC_INIT_DEFAULT; + init.enable = 1; + init.precntWrapOnCCV0 = false; + init.cntWrapOnCCV1 = false; +#if RTC_CLOCKDIV_INT == 8 + init.presc = rtccCntPresc_8; +#else +#error invalid prescaler value RTC_CLOCKDIV_INT +#endif + + /* Enable Interrupt from RTC */ + RTCC_IntEnable(RTCC_IEN_OF); + NVIC_EnableIRQ(RTCC_IRQn); + NVIC_SetVector(RTCC_IRQn, (uint32_t)RTCC_IRQHandler); + + /* Initialize */ + RTCC_Init(&init); + + blockSleepMode(RTCC_LEAST_ACTIVE_SLEEPMODE); + rtc_inited = true; + } +} + +void rtc_free(void) +{ + rtc_free_real(RTC_INIT_RTC); +} + +void rtc_free_real(uint32_t flags) +{ + /* Clear use flag */ + useflags &= ~flags; + + /* Disable the RTC if it was inited and is no longer in use by anyone. */ + if (rtc_inited && (useflags == 0)) { + NVIC_DisableIRQ(RTCC_IRQn); + RTCC_Reset(); + CMU_ClockEnable(cmuClock_RTCC, false); + unblockSleepMode(RTCC_LEAST_ACTIVE_SLEEPMODE); + rtc_inited = false; + } +} + +#endif /* RTCC_COUNT */ + +void rtc_set_comp0_handler(uint32_t handler) +{ + comp0_handler = (void (*)(void)) handler; +} + +void rtc_init(void) +{ + /* Register that the RTC is used for timekeeping. */ + rtc_init_real(RTC_INIT_RTC); +} + int rtc_isenabled(void) { return rtc_inited; @@ -153,7 +259,7 @@ return (time_t) (rtc_get_full() >> RTC_FREQ_SHIFT) + time_base; } -time_t rtc_read_uncompensated(void) +time_t rtc_read_uncompensated(void) { return (time_t) (rtc_get_full() >> RTC_FREQ_SHIFT); } @@ -166,7 +272,7 @@ do { time = rtc_read_uncompensated(); time_base = t - time; - } while (time != rtc_read_uncompensated()); + } while (time != (uint32_t)rtc_read_uncompensated()); } #endif