This is a RTC additional function. This is only for Nucleo F401RE & F411RE mbed(Added L152RE, F334R8, L476RG & F746xx). If you connected battery backup circuit for internal RTC, you can make a power-off and reset condition. RTC still has proper time and date.

Dependents:   Nucleo_rtos_sample PB_Emma_Ethernet

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers rtc_api_F4xx.c Source File

rtc_api_F4xx.c

00001 #if 0
00002 /* mbed Microcontroller Library
00003  *******************************************************************************
00004  * Copyright (c) 2014, STMicroelectronics
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are met:
00009  *
00010  * 1. Redistributions of source code must retain the above copyright notice,
00011  *    this list of conditions and the following disclaimer.
00012  * 2. Redistributions in binary form must reproduce the above copyright notice,
00013  *    this list of conditions and the following disclaimer in the documentation
00014  *    and/or other materials provided with the distribution.
00015  * 3. Neither the name of STMicroelectronics nor the names of its contributors
00016  *    may be used to endorse or promote products derived from this software
00017  *    without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00020  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00023  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00024  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00025  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00026  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00027  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00028  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *******************************************************************************
00030  */
00031 #include "rtc_api.h"
00032 
00033 #if DEVICE_RTC
00034 
00035 #include "mbed_error.h"
00036 
00037 #if DEVICE_RTC_LSI
00038 static int rtc_inited = 0;
00039 #endif
00040 
00041 static RTC_HandleTypeDef RtcHandle;
00042 
00043 //#define ORIGINAL
00044 #if defined(ORIGINAL)
00045 #warning "You cannot use SetRTC functions"
00046 #else
00047 #warning "You modified mbed-src rtc_api.c for SetRTC functions"
00048 #endif
00049 
00050 #if defined(ORIGINAL)   // modify part1 of 4 (Start)
00051 #else
00052 #define RTC_DAT0    0x55aa55aa
00053 #define RTC_DAT1    0xaa55aa55
00054 
00055 uint32_t RTC_ReadBackupRegister(uint32_t RTC_BKP_DR)
00056 {
00057     __IO uint32_t tmp = 0;
00058 
00059     // Check the parameters
00060     assert_param(IS_RTC_BKP(RTC_BKP_DR));
00061     tmp = RTC_BASE + 0x50;
00062     tmp += (RTC_BKP_DR * 4);
00063     // Read the specified register
00064     return (*(__IO uint32_t *)tmp);
00065 }
00066 
00067 /* Check RTC Backup registers contents */
00068 uint32_t Check_Rtc_backup_reg( void )
00069 {
00070     if ( RTC_ReadBackupRegister( RTC_BKP_DR0 ) == RTC_DAT0 ) {
00071         if ( RTC_ReadBackupRegister( RTC_BKP_DR1 ) == RTC_DAT1 ) {
00072             return 1;
00073         }
00074     }
00075     return 0;
00076 }
00077 
00078 void RTC_WriteBackupRegister(uint32_t RTC_BKP_DR, uint32_t Data)
00079 {
00080     __IO uint32_t tmp = 0;
00081 
00082     // Check the parameters/
00083     assert_param(IS_RTC_BKP(RTC_BKP_DR));
00084     tmp = RTC_BASE + 0x50;
00085     tmp += (RTC_BKP_DR * 4);
00086     // Write the specified register/
00087     *(__IO uint32_t *)tmp = (uint32_t)Data;
00088 }
00089 #endif   // modify part1 of 4 (End)
00090 
00091 void rtc_init(void)
00092 {
00093     RCC_OscInitTypeDef RCC_OscInitStruct;
00094     uint32_t rtc_freq = 0;
00095 
00096 #if DEVICE_RTC_LSI
00097     rtc_inited = 1;
00098 #endif
00099 
00100     RtcHandle.Instance = RTC;
00101 
00102 #if defined(ORIGINAL)   // modify part2 of 4 (Start)
00103 #else
00104     // Enable Power clock
00105     __PWR_CLK_ENABLE();
00106 
00107     // Enable access to Backup domain
00108     HAL_PWR_EnableBkUpAccess();
00109 
00110     // Check backup condition
00111     if ( Check_Rtc_backup_reg() ) {
00112         return;
00113     }
00114 #endif   // modify part2 of 4 (End)
00115 #if !DEVICE_RTC_LSI
00116     // Enable LSE Oscillator
00117     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
00118     RCC_OscInitStruct.PLL.PLLState   = RCC_PLL_NONE; /* Mandatory, otherwise the PLL is reconfigured! */
00119     RCC_OscInitStruct.LSEState       = RCC_LSE_ON; /* External 32.768 kHz clock on OSC_IN/OSC_OUT */
00120     if (HAL_RCC_OscConfig(&RCC_OscInitStruct) == HAL_OK) {
00121         // Connect LSE to RTC
00122         __HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSE);
00123         __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE);
00124         rtc_freq = LSE_VALUE;
00125     }
00126     else {
00127       error("RTC error: LSE clock initialization failed.");
00128     }
00129 #else
00130     // Enable Power clock
00131     __PWR_CLK_ENABLE();
00132 
00133     // Enable access to Backup domain
00134     HAL_PWR_EnableBkUpAccess();
00135 
00136     // Reset Backup domain
00137     __HAL_RCC_BACKUPRESET_FORCE();
00138     __HAL_RCC_BACKUPRESET_RELEASE();
00139 
00140     // Enable LSI clock
00141     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE;
00142     RCC_OscInitStruct.PLL.PLLState   = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured!
00143     RCC_OscInitStruct.LSEState       = RCC_LSE_OFF;
00144     RCC_OscInitStruct.LSIState       = RCC_LSI_ON;
00145     if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
00146         error("RTC error: LSI clock initialization failed.");
00147     }
00148     // Connect LSI to RTC
00149     __HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSI);
00150     __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSI);
00151     // [TODO] This value is LSI typical value. To be measured precisely using a timer input capture
00152     rtc_freq = LSI_VALUE;
00153 #endif    
00154 
00155     // Enable RTC
00156     __HAL_RCC_RTC_ENABLE();
00157 
00158     RtcHandle.Init.HourFormat     = RTC_HOURFORMAT_24;
00159     RtcHandle.Init.AsynchPrediv   = 127;
00160     RtcHandle.Init.SynchPrediv    = (rtc_freq / 128) - 1;
00161     RtcHandle.Init.OutPut         = RTC_OUTPUT_DISABLE;
00162     RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
00163     RtcHandle.Init.OutPutType     = RTC_OUTPUT_TYPE_OPENDRAIN;
00164 
00165 #if defined(ORIGINAL)   // modify part3 of 4 (Start)
00166 #else
00167     /* Write backup data into the backup RAM */
00168     RTC_WriteBackupRegister( RTC_BKP_DR0, RTC_DAT0 );
00169     RTC_WriteBackupRegister( RTC_BKP_DR1, RTC_DAT1 );
00170 #endif   // modify part3 of 4 (End)
00171 
00172     if (HAL_RTC_Init(&RtcHandle) != HAL_OK) {
00173         error("RTC error: RTC initialization failed.");
00174     }
00175 }
00176 
00177 void rtc_free(void)
00178 {
00179 #if DEVICE_RTC_LSI
00180     // Enable Power clock
00181     __PWR_CLK_ENABLE();
00182 
00183     // Enable access to Backup domain
00184     HAL_PWR_EnableBkUpAccess();
00185 
00186     // Reset Backup domain
00187     __HAL_RCC_BACKUPRESET_FORCE();
00188     __HAL_RCC_BACKUPRESET_RELEASE();
00189 
00190     // Disable access to Backup domain
00191     HAL_PWR_DisableBkUpAccess();
00192 #endif
00193 
00194     // Disable LSI and LSE clocks
00195     RCC_OscInitTypeDef RCC_OscInitStruct;
00196     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE;
00197     RCC_OscInitStruct.PLL.PLLState   = RCC_PLL_NONE;
00198     RCC_OscInitStruct.LSIState       = RCC_LSI_OFF;
00199     RCC_OscInitStruct.LSEState       = RCC_LSE_OFF;
00200     HAL_RCC_OscConfig(&RCC_OscInitStruct);
00201 #if DEVICE_RTC_LSI
00202     rtc_inited = 0;
00203 #endif
00204 }
00205 
00206 int rtc_isenabled(void)
00207 {
00208 #if DEVICE_RTC_LSI
00209     return rtc_inited;
00210 #else
00211 #if defined(ORIGINAL)   // modify part4 of 4 (Start)
00212     if ((RTC->ISR & RTC_ISR_INITS) ==  RTC_ISR_INITS) return 1;
00213     else return 0;
00214 #else
00215     return Check_Rtc_backup_reg();
00216 #endif   // modify part4 of 4 (End)
00217 #endif
00218 }
00219 
00220 /*
00221  RTC Registers
00222    RTC_WeekDay 1=monday, 2=tuesday, ..., 7=sunday
00223    RTC_Month   1=january, 2=february, ..., 12=december
00224    RTC_Date    day of the month 1-31
00225    RTC_Year    year 0-99
00226  struct tm
00227    tm_sec      seconds after the minute 0-61
00228    tm_min      minutes after the hour 0-59
00229    tm_hour     hours since midnight 0-23
00230    tm_mday     day of the month 1-31
00231    tm_mon      months since January 0-11
00232    tm_year     years since 1900
00233    tm_wday     days since Sunday 0-6
00234    tm_yday     days since January 1 0-365
00235    tm_isdst    Daylight Saving Time flag
00236 */
00237 time_t rtc_read(void)
00238 {
00239     RTC_DateTypeDef dateStruct;
00240     RTC_TimeTypeDef timeStruct;
00241     struct tm timeinfo;
00242 
00243     RtcHandle.Instance = RTC;
00244 
00245     // Read actual date and time
00246     // Warning: the time must be read first!
00247     HAL_RTC_GetTime(&RtcHandle, &timeStruct, FORMAT_BIN);
00248     HAL_RTC_GetDate(&RtcHandle, &dateStruct, FORMAT_BIN);
00249 
00250     // Setup a tm structure based on the RTC
00251     timeinfo.tm_wday = dateStruct.WeekDay;
00252     timeinfo.tm_mon  = dateStruct.Month - 1;
00253     timeinfo.tm_mday = dateStruct.Date;
00254     timeinfo.tm_year = dateStruct.Year + 100;
00255     timeinfo.tm_hour = timeStruct.Hours;
00256     timeinfo.tm_min  = timeStruct.Minutes;
00257     timeinfo.tm_sec  = timeStruct.Seconds;
00258 
00259     // Convert to timestamp
00260     time_t t = mktime(&timeinfo);
00261 
00262     return t;
00263 }
00264 
00265 void rtc_write(time_t t)
00266 {
00267     RTC_DateTypeDef dateStruct;
00268     RTC_TimeTypeDef timeStruct;
00269 
00270     RtcHandle.Instance = RTC;
00271 
00272     // Convert the time into a tm
00273     struct tm *timeinfo = localtime(&t);
00274 
00275     // Fill RTC structures
00276     dateStruct.WeekDay        = timeinfo->tm_wday;
00277     dateStruct.Month          = timeinfo->tm_mon + 1;
00278     dateStruct.Date           = timeinfo->tm_mday;
00279     dateStruct.Year           = timeinfo->tm_year - 100;
00280     timeStruct.Hours          = timeinfo->tm_hour;
00281     timeStruct.Minutes        = timeinfo->tm_min;
00282     timeStruct.Seconds        = timeinfo->tm_sec;
00283     timeStruct.TimeFormat     = RTC_HOURFORMAT12_PM;
00284     timeStruct.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
00285     timeStruct.StoreOperation = RTC_STOREOPERATION_RESET;
00286 
00287     // Change the RTC current date/time
00288     HAL_RTC_SetDate(&RtcHandle, &dateStruct, FORMAT_BIN);
00289     HAL_RTC_SetTime(&RtcHandle, &timeStruct, FORMAT_BIN);
00290 }
00291 
00292 #endif
00293 #endif
00294