Modified for BG96
Fork of mbed-dev by
Diff: targets/TARGET_STM/rtc_api.c
- Revision:
- 180:96ed750bd169
- Parent:
- 176:447f873cad2f
- Child:
- 181:57724642e740
--- a/targets/TARGET_STM/rtc_api.c Thu Dec 07 14:01:42 2017 +0000 +++ b/targets/TARGET_STM/rtc_api.c Wed Jan 17 15:23:54 2018 +0000 @@ -1,6 +1,6 @@ /* mbed Microcontroller Library ******************************************************************************* - * Copyright (c) 2016, STMicroelectronics + * Copyright (c) 2017, STMicroelectronics * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,29 +27,15 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************* */ + #if DEVICE_RTC -#include "rtc_api.h" #include "rtc_api_hal.h" #include "mbed_error.h" #include "mbed_mktime.h" static RTC_HandleTypeDef RtcHandle; -#if RTC_LSI -#define RTC_CLOCK LSI_VALUE -#else -#define RTC_CLOCK LSE_VALUE -#endif - -#if DEVICE_LOWPOWERTIMER -#define RTC_ASYNCH_PREDIV ((RTC_CLOCK - 1) / 0x8000) -#define RTC_SYNCH_PREDIV (RTC_CLOCK / (RTC_ASYNCH_PREDIV + 1) - 1) -#else -#define RTC_ASYNCH_PREDIV (0x007F) -#define RTC_SYNCH_PREDIV (RTC_CLOCK / (RTC_ASYNCH_PREDIV + 1) - 1) -#endif - #if DEVICE_LOWPOWERTIMER static void (*irq_handler)(void); static void RTC_IRQHandler(void); @@ -61,38 +47,38 @@ RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; // Enable access to Backup domain + __HAL_RCC_PWR_CLK_ENABLE(); HAL_PWR_EnableBkUpAccess(); - RtcHandle.Instance = RTC; - RtcHandle.State = HAL_RTC_STATE_RESET; + if (rtc_isenabled()) { + return; + } -#if !RTC_LSI - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE; +#if MBED_CONF_TARGET_LSE_AVAILABLE + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_LSE; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured! RCC_OscInitStruct.LSEState = RCC_LSE_ON; RCC_OscInitStruct.LSIState = RCC_LSI_OFF; - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) == HAL_OK) { - __HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSE); - __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE); - } else { + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { error("Cannot initialize RTC with LSE\n"); } + __HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSE); + __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE); + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC; PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { error("PeriphClkInitStruct RTC failed with LSE\n"); } -#else /* !RTC_LSI */ - __HAL_RCC_PWR_CLK_ENABLE(); - +#else /* MBED_CONF_TARGET_LSE_AVAILABLE */ // Reset Backup domain __HAL_RCC_BACKUPRESET_FORCE(); __HAL_RCC_BACKUPRESET_RELEASE(); // Enable LSI clock - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI; + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_LSE; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured! RCC_OscInitStruct.LSEState = RCC_LSE_OFF; RCC_OscInitStruct.LSIState = RCC_LSI_ON; @@ -108,46 +94,50 @@ if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { error("PeriphClkInitStruct RTC failed with LSI\n"); } -#endif /* !RTC_LSI */ +#endif /* MBED_CONF_TARGET_LSE_AVAILABLE */ // Enable RTC __HAL_RCC_RTC_ENABLE(); + RtcHandle.Instance = RTC; + RtcHandle.State = HAL_RTC_STATE_RESET; + #if TARGET_STM32F1 RtcHandle.Init.AsynchPrediv = RTC_AUTO_1_SECOND; #else /* TARGET_STM32F1 */ RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24; - RtcHandle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV; - RtcHandle.Init.SynchPrediv = RTC_SYNCH_PREDIV; + + /* PREDIV_A : 7-bit asynchronous prescaler */ +#if DEVICE_LOWPOWERTIMER + /* PREDIV_A is set to a small value to improve the SubSeconds resolution */ + /* with a 32768Hz clock, PREDIV_A=7 gives a precision of 244us */ + RtcHandle.Init.AsynchPrediv = 7; +#else + /* PREDIV_A is set to the maximum value to improve the consumption */ + RtcHandle.Init.AsynchPrediv = 0x007F; +#endif + /* PREDIV_S : 15-bit synchronous prescaler */ + /* PREDIV_S is set in order to get a 1 Hz clock */ + RtcHandle.Init.SynchPrediv = RTC_CLOCK / (RtcHandle.Init.AsynchPrediv + 1) - 1; RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE; RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; #endif /* TARGET_STM32F1 */ if (HAL_RTC_Init(&RtcHandle) != HAL_OK) { - error("RTC error: RTC initialization failed."); + error("RTC initialization failed"); } -#if DEVICE_LOWPOWERTIMER + rtc_synchronize(); // Wait for RSF -#if !RTC_LSI - if (!rtc_isenabled()) -#endif /* !RTC_LSI */ - { + if (!rtc_isenabled()) { rtc_write(0); } - - NVIC_ClearPendingIRQ(RTC_WKUP_IRQn); - NVIC_DisableIRQ(RTC_WKUP_IRQn); - NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler); - NVIC_EnableIRQ(RTC_WKUP_IRQn); - -#endif /* DEVICE_LOWPOWERTIMER */ } void rtc_free(void) { -#if RTC_LSI +#if !MBED_CONF_TARGET_LSE_AVAILABLE // Enable Power clock __HAL_RCC_PWR_CLK_ENABLE(); @@ -279,8 +269,12 @@ #endif /* TARGET_STM32F1 */ // Change the RTC current date/time - HAL_RTC_SetDate(&RtcHandle, &dateStruct, RTC_FORMAT_BIN); - HAL_RTC_SetTime(&RtcHandle, &timeStruct, RTC_FORMAT_BIN); + if (HAL_RTC_SetDate(&RtcHandle, &dateStruct, RTC_FORMAT_BIN) != HAL_OK) { + error("HAL_RTC_SetDate error\n"); + } + if (HAL_RTC_SetTime(&RtcHandle, &timeStruct, RTC_FORMAT_BIN) != HAL_OK) { + error("HAL_RTC_SetTime error\n"); + } } int rtc_isenabled(void) @@ -292,11 +286,20 @@ #endif /* TARGET_STM32F1 */ } +void rtc_synchronize(void) +{ + RtcHandle.Instance = RTC; + if (HAL_RTC_WaitForSynchro(&RtcHandle) != HAL_OK) { + error("rtc_synchronize error\n"); + } +} + #if DEVICE_LOWPOWERTIMER static void RTC_IRQHandler(void) { /* Update HAL state */ + RtcHandle.Instance = RTC; HAL_RTCEx_WakeUpTimerIRQHandler(&RtcHandle); /* In case of registered handler, call it. */ if (irq_handler) { @@ -304,35 +307,52 @@ } } -void rtc_set_irq_handler(uint32_t handler) -{ - irq_handler = (void (*)(void))handler; -} - uint32_t rtc_read_subseconds(void) { - return 1000000.f * ((double)(RTC_SYNCH_PREDIV - RTC->SSR) / (RTC_SYNCH_PREDIV + 1)); + return 1000000.f * ((double)((RTC->PRER & RTC_PRER_PREDIV_S) - RTC->SSR) / ((RTC->PRER & RTC_PRER_PREDIV_S) + 1)); } void rtc_set_wake_up_timer(uint32_t delta) { - uint32_t wake_up_counter = delta / (2000000 / RTC_CLOCK); + /* Ex for Wakeup period resolution with RTCCLK=32768 Hz : + * RTCCLK_DIV2: ~122us < wakeup period < ~4s + * RTCCLK_DIV4: ~244us < wakeup period < ~8s + * RTCCLK_DIV8: ~488us < wakeup period < ~16s + * RTCCLK_DIV16: ~976us < wakeup period < ~32s + * CK_SPRE_16BITS: 1s < wakeup period < (0xFFFF+ 1) x 1 s = 65536 s (18 hours) + * CK_SPRE_17BITS: 18h+1s < wakeup period < (0x1FFFF+ 1) x 1 s = 131072 s (36 hours) + */ + uint32_t WakeUpClock[6] = {RTC_WAKEUPCLOCK_RTCCLK_DIV2, RTC_WAKEUPCLOCK_RTCCLK_DIV4, RTC_WAKEUPCLOCK_RTCCLK_DIV8, RTC_WAKEUPCLOCK_RTCCLK_DIV16, RTC_WAKEUPCLOCK_CK_SPRE_16BITS, RTC_WAKEUPCLOCK_CK_SPRE_17BITS}; + uint8_t ClockDiv[4] = {2, 4, 8, 16}; + uint32_t WakeUpCounter; + uint8_t DivIndex = 0; - if (HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, wake_up_counter, - RTC_WAKEUPCLOCK_RTCCLK_DIV2) != HAL_OK) { - error("Set wake up timer failed\n"); + do { + WakeUpCounter = delta / (ClockDiv[DivIndex] * 1000000 / RTC_CLOCK); + DivIndex++; + } while ( (WakeUpCounter > 0xFFFF) && (DivIndex < 4) ); + + if (WakeUpCounter > 0xFFFF) { + WakeUpCounter = delta / 1000000; + DivIndex++; + } + + irq_handler = (void (*)(void))lp_ticker_irq_handler; + NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler); + NVIC_EnableIRQ(RTC_WKUP_IRQn); + + RtcHandle.Instance = RTC; + if (HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, 0xFFFF & WakeUpCounter, WakeUpClock[DivIndex-1]) != HAL_OK) { + error("rtc_set_wake_up_timer init error (%d)\n", DivIndex); } } void rtc_deactivate_wake_up_timer(void) { + RtcHandle.Instance = RTC; HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle); } -void rtc_synchronize(void) -{ - HAL_RTC_WaitForSynchro(&RtcHandle); -} #endif /* DEVICE_LOWPOWERTIMER */ #endif /* DEVICE_RTC */