Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dev by
Diff: targets/TARGET_STM/rtc_api.c
- Revision:
- 181:96ed750bd169
- Parent:
- 176:447f873cad2f
diff -r b0033dcd6934 -r 96ed750bd169 targets/TARGET_STM/rtc_api.c
--- 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 */
