mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
Diff: targets/TARGET_STM/rtc_api.c
- Revision:
- 188:bcfe06ba3d64
- Parent:
- 187:0387e8f68319
- Child:
- 189:f392fc9709a3
--- a/targets/TARGET_STM/rtc_api.c Thu Sep 06 13:40:20 2018 +0100 +++ b/targets/TARGET_STM/rtc_api.c Thu Nov 08 11:46:34 2018 +0000 @@ -36,8 +36,8 @@ #include "mbed_critical.h" #if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM -volatile uint32_t LP_continuous_time = 0; -volatile uint32_t LP_last_RTC_time = 0; +volatile uint32_t LPTICKER_counter = 0; +volatile uint32_t LPTICKER_RTC_time = 0; #endif static int RTC_inited = 0; @@ -60,14 +60,12 @@ #if MBED_CONF_TARGET_LSE_AVAILABLE RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured! + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; RCC_OscInitStruct.LSEState = RCC_LSE_ON; - 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; @@ -76,19 +74,13 @@ error("PeriphClkInitStruct RTC failed with LSE\n"); } #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.PLL.PLLState = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured! + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; RCC_OscInitStruct.LSIState = RCC_LSI_ON; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { error("Cannot initialize RTC with LSI\n"); } - __HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSI); __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSI); PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC; @@ -116,14 +108,14 @@ #endif /* TARGET_STM32F1 */ if (HAL_RTC_Init(&RtcHandle) != HAL_OK) { - error("RTC initialization failed"); + error("RTC initialization failed\n"); } #if !(TARGET_STM32F1) && !(TARGET_STM32F2) /* STM32F1 : there are no shadow registers */ /* STM32F2 : shadow registers can not be bypassed */ if (HAL_RTCEx_EnableBypassShadow(&RtcHandle) != HAL_OK) { - error("EnableBypassShadow error"); + error("EnableBypassShadow error\n"); } #endif /* TARGET_STM32F1 || TARGET_STM32F2 */ } @@ -149,51 +141,15 @@ For date, there is no specific register, only a software structure. It is then not a problem to not use shifts. */ -#if TARGET_STM32F1 time_t rtc_read(void) { - RTC_DateTypeDef dateStruct = {0}; - RTC_TimeTypeDef timeStruct = {0}; - struct tm timeinfo; +#if TARGET_STM32F1 RtcHandle.Instance = RTC; - - // Read actual date and time - // Warning: the time must be read first! - HAL_RTC_GetTime(&RtcHandle, &timeStruct, RTC_FORMAT_BIN); - HAL_RTC_GetDate(&RtcHandle, &dateStruct, RTC_FORMAT_BIN); - - /* date information is null before first write procedure */ - /* set 01/01/1970 as default values */ - if (dateStruct.Year == 0) { - dateStruct.Year = 2 ; - dateStruct.Month = 1 ; - dateStruct.Date = 1 ; - } - - // Setup a tm structure based on the RTC - /* tm_wday information is ignored by _rtc_maketime */ - /* tm_isdst information is ignored by _rtc_maketime */ - timeinfo.tm_mon = dateStruct.Month - 1; - timeinfo.tm_mday = dateStruct.Date; - timeinfo.tm_year = dateStruct.Year + 68; - timeinfo.tm_hour = timeStruct.Hours; - timeinfo.tm_min = timeStruct.Minutes; - timeinfo.tm_sec = timeStruct.Seconds; - - // Convert to timestamp - time_t t; - if (_rtc_maketime(&timeinfo, &t, RTC_4_YEAR_LEAP_YEAR_SUPPORT) == false) { - return 0; - } - - return t; -} + return RTC_ReadTimeCounter(&RtcHandle); #else /* TARGET_STM32F1 */ -time_t rtc_read(void) -{ struct tm timeinfo; /* Since the shadow registers are bypassed we have to read the time twice and compare them until both times are the same */ @@ -231,12 +187,23 @@ } return t; + +#endif /* TARGET_STM32F1 */ } -#endif /* TARGET_STM32F1 */ + void rtc_write(time_t t) { +#if TARGET_STM32F1 + + RtcHandle.Instance = RTC; + if (RTC_WriteTimeCounter(&RtcHandle, t) != HAL_OK) { + error("RTC_WriteTimeCounter error\n"); + } + +#else /* TARGET_STM32F1 */ + RTC_DateTypeDef dateStruct = {0}; RTC_TimeTypeDef timeStruct = {0}; @@ -261,22 +228,19 @@ timeStruct.Hours = timeinfo.tm_hour; timeStruct.Minutes = timeinfo.tm_min; timeStruct.Seconds = timeinfo.tm_sec; - -#if !(TARGET_STM32F1) timeStruct.TimeFormat = RTC_HOURFORMAT_24; timeStruct.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; timeStruct.StoreOperation = RTC_STOREOPERATION_RESET; -#endif /* TARGET_STM32F1 */ #if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM - /* Need to update LP_continuous_time value before new RTC time */ + /* Before setting the new time, we need to update the LPTICKER_counter value */ + /* rtc_read_lp function is then called */ rtc_read_lp(); - /* LP_last_RTC_time value is updated with the new RTC time */ - LP_last_RTC_time = timeStruct.Seconds + timeStruct.Minutes * 60 + timeStruct.Hours * 60 * 60; - - /* Save current SSR */ - uint32_t Read_SubSeconds = (uint32_t)(RTC->SSR); + /* In rtc_read_lp, LPTICKER_RTC_time value has been updated with the current time */ + /* We need now to overwrite the value with the new RTC time */ + /* Note that when a new RTC time is set by HW, the RTC SubSeconds counter is reset to PREDIV_S_VALUE */ + LPTICKER_RTC_time = (timeStruct.Seconds + timeStruct.Minutes * 60 + timeStruct.Hours * 60 * 60) * PREDIV_S_VALUE; #endif /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */ // Change the RTC current date/time @@ -287,12 +251,8 @@ error("HAL_RTC_SetTime error\n"); } -#if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM - while (Read_SubSeconds != (RTC->SSR)) { - } -#endif /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */ - core_util_critical_section_exit(); +#endif /* TARGET_STM32F1 */ } int rtc_isenabled(void) @@ -341,11 +301,18 @@ uint32_t rtc_read_lp(void) { + /* RTC_time_tick is the addition of the RTC time register (in second) and the RTC sub-second register + * This time value is breaking each 24h (= 86400s = 0x15180) + * In order to get a U32 continuous time information, we use an internal counter : LPTICKER_counter + * This counter is the addition of each spent time since last function call + * Current RTC time is saved into LPTICKER_RTC_time + * NB: rtc_read_lp() output is not the time in us, but the LPTICKER_counter (frequency LSE/4 = 8kHz => 122us) + */ + core_util_critical_section_enter(); struct tm timeinfo; /* Since the shadow registers are bypassed we have to read the time twice and compare them until both times are the same */ /* We don't have to read date as we bypass shadow registers */ - uint32_t Read_SecondFraction = (uint32_t)(RTC->PRER & RTC_PRER_PREDIV_S); uint32_t Read_time = (uint32_t)(RTC->TR & RTC_TR_RESERVED_MASK); uint32_t Read_SubSeconds = (uint32_t)(RTC->SSR); @@ -358,17 +325,18 @@ timeinfo.tm_min = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_MNT | RTC_TR_MNU)) >> 8)); timeinfo.tm_sec = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_ST | RTC_TR_SU)) >> 0)); - uint32_t RTC_time_s = timeinfo.tm_sec + timeinfo.tm_min * 60 + timeinfo.tm_hour * 60 * 60; // Max 0x0001-517F => * 8191 + 8191 = 0x2A2E-AE80 + uint32_t RTC_time_tick = (timeinfo.tm_sec + timeinfo.tm_min * 60 + timeinfo.tm_hour * 60 * 60) * PREDIV_S_VALUE + PREDIV_S_VALUE - Read_SubSeconds; // Max 0x0001-517F * 8191 + 8191 = 0x2A2E-AE80 - if (LP_last_RTC_time <= RTC_time_s) { - LP_continuous_time += (RTC_time_s - LP_last_RTC_time); + if (LPTICKER_RTC_time <= RTC_time_tick) { + LPTICKER_counter += (RTC_time_tick - LPTICKER_RTC_time); } else { - /* Add 24h */ - LP_continuous_time += (24 * 60 * 60 + RTC_time_s - LP_last_RTC_time); + /* When RTC time is 0h00.01 and was 11H59.59, difference is "current time + 24h - previous time" */ + LPTICKER_counter += (RTC_time_tick + 24 * 60 * 60 * PREDIV_S_VALUE - LPTICKER_RTC_time); } - LP_last_RTC_time = RTC_time_s; + LPTICKER_RTC_time = RTC_time_tick; - return LP_continuous_time * PREDIV_S_VALUE + Read_SecondFraction - Read_SubSeconds; + core_util_critical_section_exit(); + return LPTICKER_counter; } void rtc_set_wake_up_timer(timestamp_t timestamp) @@ -388,7 +356,9 @@ WakeUpCounter = 0xFFFF; } + core_util_critical_section_enter(); RtcHandle.Instance = RTC; + HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle); if (HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, WakeUpCounter, RTC_WAKEUPCLOCK_RTCCLK_DIV4) != HAL_OK) { error("rtc_set_wake_up_timer init error\n"); } @@ -396,6 +366,7 @@ NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler); irq_handler = (void (*)(void))lp_ticker_irq_handler; NVIC_EnableIRQ(RTC_WKUP_IRQn); + core_util_critical_section_exit(); } void rtc_fire_interrupt(void) @@ -410,10 +381,7 @@ void rtc_deactivate_wake_up_timer(void) { RtcHandle.Instance = RTC; - __HAL_RTC_WRITEPROTECTION_DISABLE(&RtcHandle); - __HAL_RTC_WAKEUPTIMER_DISABLE(&RtcHandle); - __HAL_RTC_WAKEUPTIMER_DISABLE_IT(&RtcHandle, RTC_IT_WUT); - __HAL_RTC_WRITEPROTECTION_ENABLE(&RtcHandle); + HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle); NVIC_DisableIRQ(RTC_WKUP_IRQn); }