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_F334.c Source File

rtc_api_F334.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     RtcHandle.Instance = RTC;
00105 
00106     // Enable Power clock
00107     __PWR_CLK_ENABLE();
00108 
00109     // Enable access to Backup domain
00110     HAL_PWR_EnableBkUpAccess();
00111 
00112     // Check backup condition
00113     if ( Check_Rtc_backup_reg() ) {
00114         return;
00115     }
00116 #endif   // modify part2 of 4 (End)
00117 #if !DEVICE_RTC_LSI
00118     // Enable LSE Oscillator
00119     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
00120     RCC_OscInitStruct.PLL.PLLState   = RCC_PLL_NONE; /* Mandatory, otherwise the PLL is reconfigured! */
00121     RCC_OscInitStruct.LSEState       = RCC_LSE_ON; /* External 32.768 kHz clock on OSC_IN/OSC_OUT */
00122     if (HAL_RCC_OscConfig(&RCC_OscInitStruct) == HAL_OK) {
00123         // Connect LSE to RTC
00124         __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE);
00125         rtc_freq = LSE_VALUE;
00126     }
00127     else {
00128       error("RTC error: LSE clock initialization failed.");
00129     }
00130 #else
00131     // Enable Power clock
00132     __PWR_CLK_ENABLE();
00133 
00134     // Enable access to Backup domain
00135     HAL_PWR_EnableBkUpAccess();
00136 
00137     // Reset Backup domain
00138     __HAL_RCC_BACKUPRESET_FORCE();
00139     __HAL_RCC_BACKUPRESET_RELEASE();
00140     
00141     // Enable LSI clock
00142     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE;
00143     RCC_OscInitStruct.PLL.PLLState   = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured!
00144     RCC_OscInitStruct.LSEState       = RCC_LSE_OFF;
00145     RCC_OscInitStruct.LSIState       = RCC_LSI_ON;
00146     if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
00147         error("RTC error: LSI clock initialization failed.");
00148     }
00149     // Connect LSI to RTC
00150     __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSI);
00151     // Note: The LSI clock can 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 
00202 #if DEVICE_RTC_LSI
00203     rtc_inited = 0;
00204 #endif
00205 }
00206 
00207 int rtc_isenabled(void)
00208 {
00209 #if DEVICE_RTC_LSI
00210     return rtc_inited;
00211 #else
00212 #if defined(ORIGINAL)   // modify part4 of 4 (Start)
00213     if ((RTC->ISR & RTC_ISR_INITS) ==  RTC_ISR_INITS) return 1;
00214     else return 0;
00215 #else
00216     return Check_Rtc_backup_reg();
00217 #endif   // modify part4 of 4 (End)
00218 #endif
00219 }
00220 
00221 /*
00222  RTC Registers
00223    RTC_WeekDay 1=monday, 2=tuesday, ..., 7=sunday
00224    RTC_Month   1=january, 2=february, ..., 12=december
00225    RTC_Date    day of the month 1-31
00226    RTC_Year    year 0-99
00227  struct tm
00228    tm_sec      seconds after the minute 0-61
00229    tm_min      minutes after the hour 0-59
00230    tm_hour     hours since midnight 0-23
00231    tm_mday     day of the month 1-31
00232    tm_mon      months since January 0-11
00233    tm_year     years since 1900
00234    tm_wday     days since Sunday 0-6
00235    tm_yday     days since January 1 0-365
00236    tm_isdst    Daylight Saving Time flag
00237 */
00238 time_t rtc_read(void)
00239 {
00240     RTC_DateTypeDef dateStruct;
00241     RTC_TimeTypeDef timeStruct;
00242     struct tm timeinfo;
00243 
00244     RtcHandle.Instance = RTC;
00245 
00246     // Read actual date and time
00247     // Warning: the time must be read first!
00248     HAL_RTC_GetTime(&RtcHandle, &timeStruct, FORMAT_BIN);
00249     HAL_RTC_GetDate(&RtcHandle, &dateStruct, FORMAT_BIN);
00250 
00251     // Setup a tm structure based on the RTC
00252     timeinfo.tm_wday = dateStruct.WeekDay;
00253     timeinfo.tm_mon  = dateStruct.Month - 1;
00254     timeinfo.tm_mday = dateStruct.Date;
00255     timeinfo.tm_year = dateStruct.Year + 100;
00256     timeinfo.tm_hour = timeStruct.Hours;
00257     timeinfo.tm_min  = timeStruct.Minutes;
00258     timeinfo.tm_sec  = timeStruct.Seconds;
00259 
00260     // Convert to timestamp
00261     time_t t = mktime(&timeinfo);
00262 
00263     return t;
00264 }
00265 
00266 void rtc_write(time_t t)
00267 {
00268     RTC_DateTypeDef dateStruct;
00269     RTC_TimeTypeDef timeStruct;
00270 
00271     RtcHandle.Instance = RTC;
00272 
00273     // Convert the time into a tm
00274     struct tm *timeinfo = localtime(&t);
00275 
00276     // Fill RTC structures
00277     dateStruct.WeekDay        = timeinfo->tm_wday;
00278     dateStruct.Month          = timeinfo->tm_mon + 1;
00279     dateStruct.Date           = timeinfo->tm_mday;
00280     dateStruct.Year           = timeinfo->tm_year - 100;
00281     timeStruct.Hours          = timeinfo->tm_hour;
00282     timeStruct.Minutes        = timeinfo->tm_min;
00283     timeStruct.Seconds        = timeinfo->tm_sec;
00284     timeStruct.TimeFormat     = RTC_HOURFORMAT12_PM;
00285     timeStruct.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
00286     timeStruct.StoreOperation = RTC_STOREOPERATION_RESET;
00287 
00288     // Change the RTC current date/time
00289     HAL_RTC_SetDate(&RtcHandle, &dateStruct, FORMAT_BIN);
00290     HAL_RTC_SetTime(&RtcHandle, &timeStruct, FORMAT_BIN);
00291 }
00292 
00293 #endif
00294 #endif