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

rtc_api_L152.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 static int rtc_inited = 0;
00038 
00039 static RTC_HandleTypeDef RtcHandle;
00040 
00041 //#define ORIGINAL
00042 #if defined(ORIGINAL)
00043 #warning "You cannot use SetRTC functions"
00044 #else
00045 #warning "You modified mbed-src rtc_api.c for SetRTC functions"
00046 #endif
00047 
00048 #if defined(ORIGINAL)   // modify part1 of 4 (Start)
00049 #else
00050 #define RTC_DAT0    0x55aa55aa
00051 #define RTC_DAT1    0xaa55aa55
00052 
00053 uint32_t RTC_ReadBackupRegister(uint32_t RTC_BKP_DR)
00054 {
00055     __IO uint32_t tmp = 0;
00056 
00057     // Check the parameters
00058     assert_param(IS_RTC_BKP(RTC_BKP_DR));
00059     tmp = RTC_BASE + 0x50;
00060     tmp += (RTC_BKP_DR * 4);
00061     // Read the specified register
00062     return (*(__IO uint32_t *)tmp);
00063 }
00064 
00065 /* Check RTC Backup registers contents */
00066 uint32_t Check_Rtc_backup_reg( void )
00067 {
00068     if ( RTC_ReadBackupRegister( RTC_BKP_DR0 ) == RTC_DAT0 ) {
00069         if ( RTC_ReadBackupRegister( RTC_BKP_DR1 ) == RTC_DAT1 ) {
00070             return 1;
00071         }
00072     }
00073     return 0;
00074 }
00075 
00076 void RTC_WriteBackupRegister(uint32_t RTC_BKP_DR, uint32_t Data)
00077 {
00078     __IO uint32_t tmp = 0;
00079 
00080     // Check the parameters/
00081     assert_param(IS_RTC_BKP(RTC_BKP_DR));
00082     tmp = RTC_BASE + 0x50;
00083     tmp += (RTC_BKP_DR * 4);
00084     // Write the specified register/
00085     *(__IO uint32_t *)tmp = (uint32_t)Data;
00086 }
00087 #endif   // modify part1 of 4 (End)
00088 
00089 void rtc_init(void)
00090 {
00091     RCC_OscInitTypeDef RCC_OscInitStruct;
00092     uint32_t rtc_freq = 0;
00093 
00094 #if defined(ORIGINAL)   // modify part2 of 4 (Start)
00095     if (rtc_inited) return;
00096     rtc_inited = 1;
00097 
00098     RtcHandle.Instance = RTC;
00099 
00100     // Enable Power clock
00101     __PWR_CLK_ENABLE();
00102 
00103     // Enable access to Backup domain
00104     HAL_PWR_EnableBkUpAccess();
00105 #else
00106     RtcHandle.Instance = RTC;
00107 
00108     // Enable Power clock
00109     __PWR_CLK_ENABLE();
00110 
00111     // Enable access to Backup domain
00112     HAL_PWR_EnableBkUpAccess();
00113 
00114     // Check backup condition
00115     if ( Check_Rtc_backup_reg() ) {
00116         return;
00117     }
00118 #endif   // modify part2 of 4 (End)
00119 
00120     // Reset Backup domain
00121     __HAL_RCC_BACKUPRESET_FORCE();
00122     __HAL_RCC_BACKUPRESET_RELEASE();
00123 
00124     // Enable LSE Oscillator
00125     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
00126     RCC_OscInitStruct.PLL.PLLState   = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured!
00127     RCC_OscInitStruct.LSEState       = RCC_LSE_ON; // External 32.768 kHz clock on OSC_IN/OSC_OUT
00128     if (HAL_RCC_OscConfig(&RCC_OscInitStruct) == HAL_OK) {
00129         // Connect LSE to RTC
00130         __HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSE);
00131         __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE);
00132         rtc_freq = LSE_VALUE;
00133     } else {
00134         // Enable LSI clock
00135         RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE;
00136         RCC_OscInitStruct.PLL.PLLState   = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured!
00137         RCC_OscInitStruct.LSEState       = RCC_LSE_OFF;
00138         RCC_OscInitStruct.LSIState       = RCC_LSI_ON;
00139         if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
00140             error("RTC error: LSI clock initialization failed.");
00141         }
00142         // Connect LSI to RTC
00143         __HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSI);
00144         __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSI);
00145         // This value is LSI typical value. To be measured precisely using a timer input capture for example.
00146         rtc_freq = 40000;
00147     }
00148 
00149     // Enable RTC
00150     __HAL_RCC_RTC_ENABLE();
00151 
00152     RtcHandle.Init.HourFormat     = RTC_HOURFORMAT_24;
00153 #ifdef TARGET_MOTE_L152RC
00154     /* SubSecond resolution of 16384Hz */
00155     RtcHandle.Init.AsynchPrediv   = 1;
00156     RtcHandle.Init.SynchPrediv    = (rtc_freq / 2) - 1;
00157 #else
00158     RtcHandle.Init.AsynchPrediv   = 127;
00159     RtcHandle.Init.SynchPrediv    = (rtc_freq / 128) - 1;
00160 #endif
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     // Enable Power clock
00180     __PWR_CLK_ENABLE();
00181 
00182     // Enable access to Backup domain
00183     HAL_PWR_EnableBkUpAccess();
00184 
00185     // Reset Backup domain
00186     __HAL_RCC_BACKUPRESET_FORCE();
00187     __HAL_RCC_BACKUPRESET_RELEASE();
00188 
00189     // Disable access to Backup domain
00190     HAL_PWR_DisableBkUpAccess();
00191 
00192     // Disable LSI and LSE clocks
00193     RCC_OscInitTypeDef RCC_OscInitStruct;
00194     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE;
00195     RCC_OscInitStruct.PLL.PLLState   = RCC_PLL_NONE;
00196     RCC_OscInitStruct.LSIState       = RCC_LSI_OFF;
00197     RCC_OscInitStruct.LSEState       = RCC_LSE_OFF;
00198     HAL_RCC_OscConfig(&RCC_OscInitStruct);
00199 
00200     rtc_inited = 0;
00201 }
00202 
00203 int rtc_isenabled(void)
00204 {
00205 #if defined(ORIGINAL)   // modify part4 of 4 (Start)
00206     return rtc_inited;
00207 #else
00208     return Check_Rtc_backup_reg();
00209 #endif   // modify part4 of 4 (End)
00210 }
00211 
00212 /*
00213  RTC Registers
00214    RTC_WeekDay 1=monday, 2=tuesday, ..., 7=sunday
00215    RTC_Month   1=january, 2=february, ..., 12=december
00216    RTC_Date    day of the month 1-31
00217    RTC_Year    year 0-99
00218  struct tm
00219    tm_sec      seconds after the minute 0-61
00220    tm_min      minutes after the hour 0-59
00221    tm_hour     hours since midnight 0-23
00222    tm_mday     day of the month 1-31
00223    tm_mon      months since January 0-11
00224    tm_year     years since 1900
00225    tm_wday     days since Sunday 0-6
00226    tm_yday     days since January 1 0-365
00227    tm_isdst    Daylight Saving Time flag
00228 */
00229 time_t rtc_read(void)
00230 {
00231     RTC_DateTypeDef dateStruct;
00232     RTC_TimeTypeDef timeStruct;
00233     struct tm timeinfo;
00234 
00235     RtcHandle.Instance = RTC;
00236 
00237     // Read actual date and time
00238     // Warning: the time must be read first!
00239     HAL_RTC_GetTime(&RtcHandle, &timeStruct, FORMAT_BIN);
00240     HAL_RTC_GetDate(&RtcHandle, &dateStruct, FORMAT_BIN);
00241 
00242     // Setup a tm structure based on the RTC
00243     timeinfo.tm_wday = dateStruct.WeekDay;
00244     timeinfo.tm_mon  = dateStruct.Month - 1;
00245     timeinfo.tm_mday = dateStruct.Date;
00246     timeinfo.tm_year = dateStruct.Year + 100;
00247     timeinfo.tm_hour = timeStruct.Hours;
00248     timeinfo.tm_min  = timeStruct.Minutes;
00249     timeinfo.tm_sec  = timeStruct.Seconds;
00250 
00251     // Convert to timestamp
00252     time_t t = mktime(&timeinfo);
00253 
00254     return t;
00255 }
00256 
00257 void rtc_write(time_t t)
00258 {
00259     RTC_DateTypeDef dateStruct;
00260     RTC_TimeTypeDef timeStruct;
00261 
00262     RtcHandle.Instance = RTC;
00263 
00264     // Convert the time into a tm
00265     struct tm *timeinfo = localtime(&t);
00266 
00267     // Fill RTC structures
00268     dateStruct.WeekDay        = timeinfo->tm_wday;
00269     dateStruct.Month          = timeinfo->tm_mon + 1;
00270     dateStruct.Date           = timeinfo->tm_mday;
00271     dateStruct.Year           = timeinfo->tm_year - 100;
00272     timeStruct.Hours          = timeinfo->tm_hour;
00273     timeStruct.Minutes        = timeinfo->tm_min;
00274     timeStruct.Seconds        = timeinfo->tm_sec;
00275     timeStruct.TimeFormat     = RTC_HOURFORMAT12_PM;
00276     timeStruct.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
00277     timeStruct.StoreOperation = RTC_STOREOPERATION_RESET;
00278 
00279     // Change the RTC current date/time
00280     HAL_RTC_SetDate(&RtcHandle, &dateStruct, FORMAT_BIN);
00281     HAL_RTC_SetTime(&RtcHandle, &timeStruct, FORMAT_BIN);
00282 }
00283 
00284 #endif
00285 
00286 #endif