mbed library sources
Dependents: frdm_kl05z_gpio_test
Fork of mbed-src by
Diff: targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/rtc_api.c
- Revision:
- 172:2f4f8c56b261
- Parent:
- 125:23cc3068a9e4
- Child:
- 185:e752b4ee7de1
diff -r 3d240fda1f07 -r 2f4f8c56b261 targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/rtc_api.c --- a/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/rtc_api.c Fri Apr 25 14:45:06 2014 +0100 +++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/rtc_api.c Mon Apr 28 16:00:08 2014 +0100 @@ -28,7 +28,9 @@ ******************************************************************************* */ #include "rtc_api.h" -#include "stm32f4xx_hal.h" + +#if DEVICE_RTC + #include "error.h" static int rtc_inited = 0; @@ -36,6 +38,9 @@ static RTC_HandleTypeDef RtcHandle; void rtc_init(void) { + RCC_OscInitTypeDef RCC_OscInitStruct; + uint32_t rtc_freq = 0; + if (rtc_inited) return; rtc_inited = 1; @@ -44,41 +49,51 @@ // Enable Power clock __PWR_CLK_ENABLE(); - // Allow access to RTC + // Enable access to Backup domain HAL_PWR_EnableBkUpAccess(); // Reset Backup domain - __HAL_RCC_BACKUPRESET_FORCE(); + __HAL_RCC_BACKUPRESET_FORCE(); __HAL_RCC_BACKUPRESET_RELEASE(); - - // Enable LSI clock - RCC_OscInitTypeDef RCC_OscInitStruct; - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; - RCC_OscInitStruct.LSIState = RCC_LSI_ON; - RCC_OscInitStruct.LSEState = RCC_LSE_OFF; - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { - error("RTC error: LSI clock initialization failed."); + + // Enable LSE Oscillator + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; /* Mandatory, otherwise the PLL is reconfigured! */ + RCC_OscInitStruct.LSEState = RCC_LSE_ON; /* External 32.768 kHz clock on OSC_IN/OSC_OUT */ + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) == HAL_OK) + { + // Connect LSE to RTC + __HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSE); + __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE); + rtc_freq = LSE_VALUE; + } else { + // Enable LSI clock + 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; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { + error("RTC error: LSI clock initialization failed."); + } + // Connect LSI to RTC + __HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSI); + __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSI); + // [TODO] This value is LSI typical value. To be measured precisely using a timer input capture + rtc_freq = 32000; } - - // Connect LSI to RTC - __HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSI); - __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSI); - - // Enable RTC clock + + // Enable RTC __HAL_RCC_RTC_ENABLE(); - - // [TODO] This value is LSI typical value. To be measured precisely using a timer input capture - uint32_t lsi_freq = 32000; - + RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24; RtcHandle.Init.AsynchPrediv = 127; - RtcHandle.Init.SynchPrediv = (lsi_freq / 128) - 1; + RtcHandle.Init.SynchPrediv = (rtc_freq / 128) - 1; RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE; RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; + if (HAL_RTC_Init(&RtcHandle) != HAL_OK) { - error("RTC error: RTC initialization failed."); + error("RTC error: RTC initialization failed."); } } @@ -86,20 +101,24 @@ // Enable Power clock __PWR_CLK_ENABLE(); - // Allow access to RTC + // Enable access to Backup domain HAL_PWR_EnableBkUpAccess(); // Reset Backup domain - __HAL_RCC_BACKUPRESET_FORCE(); + __HAL_RCC_BACKUPRESET_FORCE(); __HAL_RCC_BACKUPRESET_RELEASE(); - // Disable LSI clock + // Disable access to Backup domain + HAL_PWR_DisableBkUpAccess(); + + // Disable LSI and LSE clocks RCC_OscInitTypeDef RCC_OscInitStruct; - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; - RCC_OscInitStruct.LSIState = RCC_LSI_OFF; + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; + RCC_OscInitStruct.LSIState = RCC_LSI_OFF; + RCC_OscInitStruct.LSEState = RCC_LSE_OFF; HAL_RCC_OscConfig(&RCC_OscInitStruct); - + rtc_inited = 0; } @@ -128,14 +147,14 @@ RTC_DateTypeDef dateStruct; RTC_TimeTypeDef timeStruct; struct tm timeinfo; - + RtcHandle.Instance = RTC; - + // Read actual date and time // Warning: the time must be read first! HAL_RTC_GetTime(&RtcHandle, &timeStruct, FORMAT_BIN); HAL_RTC_GetDate(&RtcHandle, &dateStruct, FORMAT_BIN); - + // Setup a tm structure based on the RTC timeinfo.tm_wday = dateStruct.WeekDay; timeinfo.tm_mon = dateStruct.Month - 1; @@ -144,11 +163,11 @@ timeinfo.tm_hour = timeStruct.Hours; timeinfo.tm_min = timeStruct.Minutes; timeinfo.tm_sec = timeStruct.Seconds; - + // Convert to timestamp time_t t = mktime(&timeinfo); - - return t; + + return t; } void rtc_write(time_t t) { @@ -156,10 +175,10 @@ RTC_TimeTypeDef timeStruct; RtcHandle.Instance = RTC; - + // Convert the time into a tm struct tm *timeinfo = localtime(&t); - + // Fill RTC structures dateStruct.WeekDay = timeinfo->tm_wday; dateStruct.Month = timeinfo->tm_mon + 1; @@ -171,8 +190,10 @@ timeStruct.TimeFormat = RTC_HOURFORMAT12_PM; timeStruct.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; timeStruct.StoreOperation = RTC_STOREOPERATION_RESET; - + // Change the RTC current date/time HAL_RTC_SetDate(&RtcHandle, &dateStruct, FORMAT_BIN); HAL_RTC_SetTime(&RtcHandle, &timeStruct, FORMAT_BIN); } + +#endif