Skip to content

Instantly share code, notes, and snippets.

@tuanpmt
Created May 5, 2017 16:07
Show Gist options
  • Save tuanpmt/cdd59066955b5cc098cb6c404acec586 to your computer and use it in GitHub Desktop.
Save tuanpmt/cdd59066955b5cc098cb6c404acec586 to your computer and use it in GitHub Desktop.
#include "rtc.h"
#include "hw_config.h"
#define UPDATE_INTERVAL (24*60*60)
DATE_TIME sysTime, localTime;
static enum {
INITIAL,
WAIT_GPS,
STANDBY
} clkState;
static U32 clkTick;
/*******************************************************************************
* Function Name : RTC_Configuration
* Description : Configures the RTC.
* Input : None.
* Output : None
* Return : None
*******************************************************************************/
static void RTC__Init(void)
{
/* PWR and BKP clocks selection --------------------------------------------*/
return;
/* Reset Backup Domain */
BKP_DeInit();
/* 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);
/* Enable the RTC Clock */
RCC_RTCCLKCmd(ENABLE);
/* Wait for RTC registers synchronization */
RTC_WaitForSynchro();
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
/* Enable the RTC Second */
RTC_ITConfig(RTC_IT_SEC, ENABLE);
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
/* Set RTC prescaler: set RTC period to 1sec */
RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
NVIC_Config(RTC_IRQn, RTCSEC_PRIORITY, ENABLE);
}
void RTC_Init(void)
{
//RCC_BackupResetCmd(DISABLE);
return;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
RTC_WaitForLastTask();
if(BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5) {
RTC__Init();
localTime.year = 2014;
localTime.month = 1;
localTime.mday = 1;
localTime.hour = 0;
localTime.min = 0;
localTime.sec = 0;
RTC_Sync(&localTime, sysCfg.timeZone);
PWR_BackupAccessCmd(ENABLE);
BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);
} else {
RTC_WaitForLastTask();
RTC_ITConfig(RTC_IT_SEC, ENABLE);
NVIC_Config(RTC_IRQn, RTCSEC_PRIORITY, ENABLE);
RTC_CalcTime(&localTime, RTC_GetCounter());
RTC_WaitForLastTask();
//PWR_BackupAccessCmd(DISABLE);
}
}
void RTC_CalcTime(DATE_TIME *dt, U32 unixTime)
{
struct tm *gt;
time_t epoch;
epoch = unixTime;
gt = localtime(&epoch);
dt->sec = gt->tm_sec;
dt->min = gt->tm_min;
dt->hour = gt->tm_hour;
dt->mday = gt->tm_mday;
dt->wday = gt->tm_wday + 1; // tm_wday 0 - 6 (0 = sunday)
dt->month = gt->tm_mon + 1; // tm_mon 0 - 11 (0 = Jan)
dt->year = gt->tm_year + 1900; // tm_year = current year - 1900
}
U32 RTC_GetUnixTimestamp(DATE_TIME *dt)
{
struct tm t;
time_t t_of_day;
t.tm_year = dt->year - 1900;
t.tm_mon = dt->month - 1; // Month, 0 - jan
t.tm_mday = dt->mday; // Day of the month
t.tm_hour = dt->hour;
t.tm_min = dt->min;
t.tm_sec = dt->sec;
t.tm_isdst = -1; // Is DST on? 1 = yes, 0 = no, -1 = unknown
t_of_day = mktime(&t);
return (U32)t_of_day;
}
void RTC_Now(DATE_TIME *dt)
{
return;
RTC_ITConfig(RTC_IT_SEC, DISABLE);
*dt = localTime;
RTC_ITConfig(RTC_IT_SEC, ENABLE);
}
void RTC_Sync(DATE_TIME *dt, U8 timeZone)
{
return;
RTC_ITConfig(RTC_IT_SEC, DISABLE);
PWR_BackupAccessCmd(ENABLE);
RTC_SetCounter(RTC_GetUnixTimestamp(dt) + (timeZone * 60 * 60));
RTC_CalcTime(&localTime, RTC_GetCounter());
RTC_ITConfig(RTC_IT_SEC, ENABLE);
}
void RTC_Manage(void)
{
GPS_INFOF mygps;
return;
switch(clkState) {
case INITIAL:
GPS_Info(&mygps);
if(mygps.gpsDataGood && mygps.satCount >= 3 && mygps.dateTime.year >= 111) {
// pause the tracker task, so we can freely modify the RTC
//TRACKER_Pause();
// convert back to UTC time struct
RTC_Sync(&mygps.dateTime, sysCfg.timeZone);
clkTick = RTC_GetUnixTimestamp(&mygps.dateTime);
//LOG("CLKSYNC: System clock synced\n");
clkState = STANDBY;
} else {
clkTick = RTC_GetCounter();
clkState = WAIT_GPS;
}
break;
case WAIT_GPS:
if(RTC_GetCounter() - clkTick >= 5)
clkState = INITIAL;
break;
case STANDBY:
if(RTC_GetCounter() - clkTick >= UPDATE_INTERVAL)
clkState = INITIAL;
break;
}
}
/*******************************************************************************
* Function Name : RTC_IRQHandler
* Description : This function handles RTC global interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void RTC_IRQHandler(void)
{
if(RTC_GetITStatus(RTC_IT_SEC) == SET) {
RTC_CalcTime(&localTime, RTC_GetCounter());
RTC_ClearITPendingBit(RTC_IT_SEC);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment