/** ****************************************************************************** * File Name : brtc.c * Description : This file provides code for the configuration * of board real time clock. ****************************************************************************** * @attention * *

© Copyright (c) 2019 STMicroelectronics. * All rights reserved.

* * This software component is licensed by ST under Ultimate Liberty license * SLA0044, the "License"; You may not use this file except in compliance with * the License. You may obtain a copy of the License at: * www.st.com/SLA0044 * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "brtc.h" #include "includes.h" #include "date_calc.h" #include "app_ver.h" #include "asutil.h" #include "device_param.h" #include "dflash_sf1.h" #include "dflash_chg_ctrl.h" #include "vi.h" #include "io.h" #include "calc_soc.h" #include "alarm.h" #include "pl455_comm.h" #include "task_manager.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Uncomment the corresponding line to select the RTC Clock source */ #define RTC_CLOCK_SOURCE_LSE /* LSE used as RTC source clock */ /*#define RTC_CLOCK_SOURCE_LSI *//* LSI used as RTC source clock. The RTC Clock may varies due to LSI frequency dispersion. */ #define FIRST_DATA 0x32F2 /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ RTC_TimeTypeDef RTC_TimeStructure; RTC_InitTypeDef RTC_InitStructure; RTC_DateTypeDef RTC_DateStructure; vu32 AsynchPrediv = 0, SynchPrediv = 0; vu32 LocalTime; /* this variable is used to create a time reference incremented by 10ms */ u32 UnixTimeStamp, BakUnixTimeStamp, disUnixTimeStamp, SetUnixTimeStamp; u32 BuildTimeStamp; struct DateAndTime aDateAndTime; u32 OptimeStamp, disOptimeStamp; _TTIME DEVICE_TIME, SetTime; u8 bak_sec; OS_TMR RTC_TMR; u8 reset_flag = 0; u8 set_time_flag = 0; u32 WarmingUp = WARMING_UP_TIME; const uint8_t samurai[] = {31,28,31,30,31,30,31,31,30,31,30,31}; /* Private function prototypes -----------------------------------------------*/ void Get_Time(void); void RTC_Config(void); void RTC_TimeRegulate(void); void Real_RTC_Init(void); void RTC_Update(_PTIME datetime); u32 GetRealTimeStamp(void); /* Private functions ---------------------------------------------------------*/ void Init_RTC(void) { OS_ERR err; #ifdef CONSOLE_DEBUG BuildTimeStamp = GetBuildTimeStamp(); #endif // #ifdef CONSOLE_DEBUG OSTmrCreate (&RTC_TMR, "RTC Timer", 100, 1, OS_OPT_TMR_PERIODIC, (OS_TMR_CALLBACK_PTR)&Time_Update, NULL, &err); OSTmrStart (&RTC_TMR, &err); Real_RTC_Init(); UnixTimeStamp = GetRealTimeStamp(); aDateAndTime.year = reverse16(2016); aDateAndTime.month = 5; aDateAndTime.day = 2; aDateAndTime.hour = 10; aDateAndTime.minutes = 46; aDateAndTime.seconds = 30; aDateAndTime.deci_seconds = 3; aDateAndTime.UTC_direction = '+'; aDateAndTime.UTC_hours = 8; aDateAndTime.UTC_minutes = 0; OptimeStamp = 0; } void Real_RTC_Init(void) { if (RTC_ReadBackupRegister(RTC_BKP_DR0) != FIRST_DATA) { /* RTC configuration */ RTC_Config(); /* Configure the RTC data register and RTC prescaler */ RTC_InitStructure.RTC_AsynchPrediv = AsynchPrediv; RTC_InitStructure.RTC_SynchPrediv = SynchPrediv; RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24; /* Check on RTC init */ if (RTC_Init(&RTC_InitStructure) == ERROR) { // APP_TRACE("\r\n /!\\***** RTC Prescaler Config failed ********/!\\ \n\r"); } /* Configure the time register */ RTC_TimeRegulate(); } else { /* Check if the Power On Reset flag is set */ if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET) { reset_flag = 1; } /* Check if the Pin Reset flag is set */ else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET) { reset_flag = 2; } /* Enable the PWR clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); /* Allow access to RTC */ PWR_BackupAccessCmd(ENABLE); /* Wait for RTC APB registers synchronisation */ RTC_WaitForSynchro(); } } u8 GetResetFlag(void) { u8 result = reset_flag; reset_flag = 0; return result; } u16 GetTimeYear(void) { return (DEVICE_TIME.year + UTC_YEAR); } u16 GetTimeMonth(void) { return DEVICE_TIME.month; } u16 GetTimeDate(void) { return DEVICE_TIME.date; } u16 GetTimeHour(void) { return DEVICE_TIME.hour; } u16 GetTimeMinute(void) { return DEVICE_TIME.min; } u16 GetTimeSec(void) { return DEVICE_TIME.sec; } u16 GetTimeSubSec(void) { return DEVICE_TIME.sub_sec; } u32 GetTimeStamp(void) { return UnixTimeStamp; } /** * @brief Configure the RTC peripheral by selecting the clock source. * @param None * @retval None */ void RTC_Config(void) { /* Enable the PWR clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); /* Allow access to RTC */ PWR_BackupAccessCmd(ENABLE); /* Enable the LSE OSC */ RCC_LSEConfig(RCC_LSE_ON); /* Wait till LSE is ready */ while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) { } /* Select the RTC Clock Source */ RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); SynchPrediv = 0xFF; AsynchPrediv = 0x7F; /* Enable the RTC Clock */ RCC_RTCCLKCmd(ENABLE); /* Wait for RTC APB registers synchronisation */ RTC_WaitForSynchro(); } void RTC_TimeRegulate(void) { Get_Time(); RTC_TimeStructure.RTC_Hours = DEVICE_TIME.hour; RTC_TimeStructure.RTC_Minutes = DEVICE_TIME.min; RTC_TimeStructure.RTC_Seconds = DEVICE_TIME.sec; /* Set the Date */ RTC_DateStructure.RTC_Month = DEVICE_TIME.month; RTC_DateStructure.RTC_Date = DEVICE_TIME.date; RTC_DateStructure.RTC_Year = (DEVICE_TIME.year + 1970) % 100; RTC_DateStructure.RTC_WeekDay = DEVICE_TIME.wday; /* Configure the RTC time register */ RTC_SetTime(RTC_Format_BIN, &RTC_TimeStructure); RTC_SetDate(RTC_Format_BIN, &RTC_DateStructure); RTC_TimeShow(); /* Indicator for the RTC configuration */ RTC_WriteBackupRegister(RTC_BKP_DR0, FIRST_DATA); } void RTC_TimeSet(_TTIME *aTIME) { int diffhour = DEVICE_TIME.hour - aTIME->hour; int diffmin = DEVICE_TIME.min - aTIME->min; if ((diffhour > 0) || ((diffmin > 2) || (diffmin < -2))) { RTC_TimeStructure.RTC_Hours = aTIME->hour; RTC_TimeStructure.RTC_Minutes = aTIME->min; RTC_TimeStructure.RTC_Seconds = aTIME->sec; /* Set the Date */ RTC_DateStructure.RTC_Month = aTIME->month; RTC_DateStructure.RTC_Date = aTIME->date; RTC_DateStructure.RTC_Year = (aTIME->year) % 100; RTC_DateStructure.RTC_WeekDay = aTIME->wday; /* Configure the RTC time register */ RTC_SetTime(RTC_Format_BIN, &RTC_TimeStructure); RTC_SetDate(RTC_Format_BIN, &RTC_DateStructure); } } void RTC_TimeShow(void) { u32 aa[2]; /* Get the current Time */ RTC_GetDate(RTC_Format_BIN, &RTC_DateStructure); aa[0] = (u32)RTC->TR; RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure); aa[1] = (u32)RTC->DR; printf("\r\nDate : 0x%08X[0x%08X]", aa[0], aa[1]); printf("\r\nThe current datetime is : %0.2d/%0.2d/%0.2d %0.2d:%0.2d:%0.2d \r\n", RTC_DateStructure.RTC_Year, RTC_DateStructure.RTC_Month, RTC_DateStructure.RTC_Date, RTC_TimeStructure.RTC_Hours, RTC_TimeStructure.RTC_Minutes, RTC_TimeStructure.RTC_Seconds ); } u32 Get_Local_Time(void) { return LocalTime; } void Set_Local_Time(u32 localtime) { LocalTime = localtime; } u32 GetRealTimeStamp(void) { u32 DateTimeStamp; u32 iTotalDays; _TTIME aTime; /* Get the current Time */ RTC_GetDate(RTC_Format_BIN, &RTC_DateStructure); RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure); aTime.hour = RTC_TimeStructure.RTC_Hours; aTime.min = RTC_TimeStructure.RTC_Minutes; aTime.sec = RTC_TimeStructure.RTC_Seconds; aTime.month = RTC_DateStructure.RTC_Month; aTime.date = RTC_DateStructure.RTC_Date; aTime.year = ((CPU_INT16U)RTC_DateStructure.RTC_Year + 2000)- UTC_YEAR; aTime.wday = RTC_DateStructure.RTC_WeekDay; iTotalDays = CalcDay((u32)aTime.year + UTC_YEAR, aTime.month, aTime.date); DateTimeStamp = iTotalDays - UTC_TIMESTAMP; return (DateStampToTimeStamp(DateTimeStamp) + ((u32)aTime.hour * 60 * 60) + ((u32)aTime.min * 60) + ((u32)aTime.sec)); } void SetRealTimeStamp(u32 NewTimeStamp) { UnixTimeStamp = NewTimeStamp; Get_Time(); RTC_TimeRegulate(); } void SetUpTimeStamp(s16 value, u8 MsbLsb) { if (MsbLsb == 1) { if (set_time_flag == 0) { SetUnixTimeStamp = 0; SetUnixTimeStamp |= ((u32)((value << 16)& 0xFFFF0000)); set_time_flag = 1; } } else { if (set_time_flag == 1) { SetUnixTimeStamp |= (u32)((value << 0)& 0x0000FFFF); set_time_flag = 2; } } if (set_time_flag == 2) { SetRealTimeStamp(SetUnixTimeStamp); set_time_flag = 0; } } void *GetDateAndTimeEx(void) { return (void *)&aDateAndTime; } void Get_Time(void) { UnixTimeStamp = GetRealTimeStamp(); if (UnixTimeStamp != BakUnixTimeStamp) { CalcTimeStampToDateTime(UnixTimeStamp + UTC_KOREA, &DEVICE_TIME); BakUnixTimeStamp = UnixTimeStamp; } } #ifdef CONSOLE_DEBUG u32 GetBuildTimeStamp(void) { u8 datetime[15]; u32 DateTimeStamp; u32 iTotalDays; _TTIME aTime; GET_BUILD_DATETIME(datetime); datetime[14] = 0; printf("Build : %s", datetime); aTime.year = StrToInt32(&datetime[ 0], 4) - UTC_YEAR; aTime.month = StrToInt32(&datetime[ 4], 2); aTime.date = StrToInt32(&datetime[ 6], 2); aTime.hour = StrToInt32(&datetime[ 8], 2); aTime.min = StrToInt32(&datetime[10], 2); aTime.sec = StrToInt32(&datetime[12], 2); iTotalDays = CalcDay((u32)aTime.year + UTC_YEAR, aTime.month, aTime.date); DateTimeStamp = iTotalDays - UTC_TIMESTAMP; return (DateStampToTimeStamp(DateTimeStamp) + ((u32)aTime.hour * 60 * 60) + ((u32)aTime.min * 60) + ((u32)aTime.sec)); } void Get_TimeStr(u8 *text) { Int32ToStr((DEVICE_TIME.year % 100)+ 1970, text, 4); Int32ToStr((DEVICE_TIME.month % 100), &text[ 4], 2); Int32ToStr((DEVICE_TIME.date % 100), &text[ 6], 2); Int32ToStr((DEVICE_TIME.hour % 100), &text[ 8], 2); Int32ToStr((DEVICE_TIME.min % 100), &text[10], 2); Int32ToStr((DEVICE_TIME.sec % 100), &text[12], 2); } /* input(ASCII) : YYYYMMDDhhmmss */ s8 Set_Time(u8 *time) { u16 size, i; size = 0; while (time[size] != 0x00) size++; /* Measure total string length */ if (size != 14 ) return 1; i = 0; DEVICE_TIME.year = (StrToInt(&time[i], 4)) - 1970; i += 4; DEVICE_TIME.month = StrToInt(&time[i], 2); i += 2; DEVICE_TIME.date = StrToInt(&time[i], 2); i += 2; DEVICE_TIME.hour = StrToInt(&time[i], 2); i += 2; DEVICE_TIME.min = StrToInt(&time[i], 2); i += 2; DEVICE_TIME.sec = StrToInt(&time[i], 2); i += 2; DEVICE_TIME.sub_sec = 0; /* Allow access to RTC */ PWR_BackupAccessCmd(ENABLE); /* Wait for RTC APB registers synchronisation */ RTC_WaitForSynchro(); RTC_TimeStructure.RTC_Hours = DEVICE_TIME.hour; RTC_TimeStructure.RTC_Minutes = DEVICE_TIME.min; RTC_TimeStructure.RTC_Seconds = DEVICE_TIME.sec; /* Set the Date */ RTC_DateStructure.RTC_Month = DEVICE_TIME.month; RTC_DateStructure.RTC_Date = DEVICE_TIME.date; RTC_DateStructure.RTC_Year = (DEVICE_TIME.year + 1970) % 100; RTC_DateStructure.RTC_WeekDay = DEVICE_TIME.wday; /* Configure the RTC time register */ RTC_SetTime(RTC_Format_BIN, &RTC_TimeStructure); RTC_SetDate(RTC_Format_BIN, &RTC_DateStructure); RTC_TimeShow(); return 0; } #endif // #ifdef CONSOLE_DEBUG /*------------------------------------------*/ /* Get time in UTC */ /*------------------------------------------*/ int rtc_getutc (uint32_t* tmr) { *tmr = UnixTimeStamp; return 1; } /*------------------------------------------*/ /* Get time in calendar form */ /*------------------------------------------*/ int rtc_gettime (_TTIME* rtc) { rtc->year = DEVICE_TIME.year + UTC_YEAR; rtc->month = DEVICE_TIME.month; rtc->date = DEVICE_TIME.date; rtc->wday = DEVICE_TIME.wday; rtc->hour = DEVICE_TIME.hour; rtc->min = DEVICE_TIME.min; rtc->sec = DEVICE_TIME.sec; return 1; } int rtc_gettime1 (_TTIME* rtc) { uint32_t utc, n, i, d; if (!rtc_getutc(&utc)) return 0; utc += (long)(UTC_KOREA); rtc->sec = (uint8_t)(utc % 60); utc /= 60; rtc->min = (uint8_t)(utc % 60); utc /= 60; rtc->hour = (uint8_t)(utc % 24); utc /= 24; rtc->date = (uint8_t)((utc + 4) % 7); rtc->year = (uint16_t)(1970 + utc / 1461 * 4); utc %= 1461; n = ((utc >= 1096) ? utc - 1 : utc) / 365; rtc->year += n; utc -= n * 365 + (n > 2 ? 1 : 0); for (i = 0; i < 12; i++) { d = samurai[i]; if (i == 1 && n == 2) d++; if (utc < d) break; utc -= d; } rtc->month = (uint8_t)(1 + i); rtc->date = (uint8_t)(1 + utc); return 1; } /** * @brief Returns the current time in milliseconds * when LWIP_TIMERS == 1 and NO_SYS == 1 * @param None * @retval Time */ u32 sys_now(void) { // return HAL_GetTick(); return LocalTime; } u32 GetWarmingUp(void) { return WarmingUp; } void WarmingUp_Process(u16 tick) { if (WarmingUp > tick) { WarmingUp -= tick; } else { device_status.battery_status.bit.INIT = true; } } void Time_Update(void *ptmr, void *parg) { LocalTime += RTC_TMR_PERIOD_TIME; DEVICE_TIME.sub_sec++; if (DEVICE_TIME.sub_sec >= 100) { OptimeStamp++; DEVICE_TIME.sub_sec = 0; } Get_Time(); WarmingUp_Process(RTC_TMR_PERIOD_TIME); DecIOTaskTick(RTC_TMR_PERIOD_TIME); Calculation_10ms_Current(RTC_TMR_PERIOD_TIME); dec_cb_tick(RTC_TMR_PERIOD_TIME); dec_soc_tick(RTC_TMR_PERIOD_TIME); dec_relexation_tick(RTC_TMR_PERIOD_TIME); dec_tapper_tick(RTC_TMR_PERIOD_TIME); dec_alarm_tick(RTC_TMR_PERIOD_TIME); #ifdef CONSOLE_DEBUG CalOSTaskCtxSwCtrPerSec(RTC_TMR_PERIOD_TIME); #endif // #ifdef CONSOLE_DEBUG IWDG_ReloadCounter(); } /* Display Function *************************************************/ #ifdef CONSOLE_DEBUG void ODisplayDateTime(u8 p) { u8 text[30]; if (p || (DEVICE_TIME.sec != bak_sec)) { sprintf((char *)text, "%04d/%02d/%02d", DEVICE_TIME.year + UTC_YEAR, DEVICE_TIME.month, DEVICE_TIME.date ); GreenOutXY(70, 19, text); sprintf((char *)text, "%02d:%02d:%02d", DEVICE_TIME.hour, DEVICE_TIME.min, DEVICE_TIME.sec ); GreenOutXY(71, 20, text); bak_sec = DEVICE_TIME.sec; } } void SDisplayDateTime(u8 p) { u8 text[30]; if (p || (DEVICE_TIME.sec != bak_sec)) { sprintf((char *)text, "%04d%02d%02d%02d%02d%02d", DEVICE_TIME.year + UTC_YEAR, DEVICE_TIME.month, DEVICE_TIME.date, DEVICE_TIME.hour, DEVICE_TIME.min, DEVICE_TIME.sec ); GreenOutXY(65, 16, text); bak_sec = DEVICE_TIME.sec; } } #endif // #ifdef CONSOLE_DEBUG