2019-10-03 12:47 AM
Hello,
I have a custom board with the F413ZH controller on it. For retaining RTC information after power loss, I have connected a 3.3V coin cell and a 32.768 khz crystal on LSE. However, I am facing issues with the Backup registers on the software side.
Please find my code and do help out. I may be missing something very vital and minor.
//My custom Lib for RTC
#define InternalRTCHandle &hrtc
typedef enum{
InternalRTC_OK = 0x00,
InternalRTC_TimeNotSet = 0x01,
InternalRTC_DateNotSet = 0x02,
InternalRTC_TimeNotOK = 0x11,
InternalRTC_DateNotOK = 0x12
}InternalRTC_Status;
typedef struct{
uint8_t seconds; /*!< Seconds parameter, from 00 to 59 */
uint8_t minutes; /*!< Minutes parameter, from 00 to 59 */
uint8_t hours; /*!< Hours parameter, 24Hour mode, 00 to 23 */
uint8_t day; /*!< Day in a week, from 1 to 7 */
uint8_t date; /*!< Date in a month, 1 to 31 */
uint8_t month; /*!< Month in a year, 1 to 12 */
uint8_t year; /*!< Year parameter, 00 to 99, 00 is 2000 and 99 is 2099 */
}InternalRTC_DateTime;
InternalRTC_DateTime ISetCurrentDateTime;
InternalRTC_DateTime IGetCurrentDateTime;
InternalRTC_Status InternalRTC_SetDateTime(InternalRTC_DateTime *time)
{
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef sDate = {0};
sTime.Hours = time->hours;
sTime.Minutes = time->minutes;
sTime.Seconds = time->seconds;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(InternalRTCHandle, &sTime, RTC_FORMAT_BIN) != HAL_OK)
{
return InternalRTC_TimeNotSet;
}
sDate.Month = time->month;
sDate.Date = time->date;
sDate.Year = time->year;
sDate.WeekDay = time->day;
if (HAL_RTC_SetDate(InternalRTCHandle, &sDate, RTC_FORMAT_BIN) != HAL_OK)
{
return InternalRTC_DateNotSet;
}
return InternalRTC_OK;
}
InternalRTC_Status InternalRTC_GetDateTime(InternalRTC_DateTime *time)
{
RTC_DateTypeDef gDate;
RTC_TimeTypeDef gTime;
if((HAL_RTC_GetTime(InternalRTCHandle, &gTime, RTC_FORMAT_BIN)) != HAL_OK)
{
return InternalRTC_TimeNotOK;
}
time->seconds = gTime.Seconds;
time->minutes = gTime.Minutes;
time->hours = gTime.Hours;
if((HAL_RTC_GetDate(InternalRTCHandle, &gDate, RTC_FORMAT_BIN)) != HAL_OK)
{
return InternalRTC_DateNotOK;
}
time->date = gDate.Date;
time->month = gDate.Month;
time->year = gDate.Year;
time->day = gDate.WeekDay;
return InternalRTC_OK;
}
uint32_t InternalRTC_ReadBackupRegs(uint32_t BackupRegTime, uint32_t BackupRegDate)
{
uint32_t tempTime = 0;
uint32_t tempDate = 0;
uint32_t epochtime = 0;
tempTime = HAL_RTCEx_BKUPRead(InternalRTCHandle, BackupRegTime);
tempDate = HAL_RTCEx_BKUPRead(InternalRTCHandle, BackupRegDate);
epochtime = (tempTime << 16) + (tempDate);
return epochtime;
}
void InternalRTC_WriteBackupRegs(uint32_t BackupRegTime, uint32_t BackupRegDate, uint32_t data)
{
HAL_RTCEx_BKUPWrite(InternalRTCHandle, BackupRegTime, (data >> 16));
HAL_RTCEx_BKUPWrite(InternalRTCHandle, BackupRegDate, (uint16_t)(data));
}
uint32_t returnEpochTime (InternalRTC_DateTime *time1)
{
struct tm ts;
ts.tm_sec = time1->seconds;
ts.tm_min = time1->minutes;
ts.tm_hour = time1->hours;
ts.tm_wday = time1->day - 1;
ts.tm_mday = time1->date;
ts.tm_mon = time1->month - 1;
ts.tm_year = time1->year + 2000 - 1900;
ts.tm_isdst = 0;
return (mktime (&ts));
}
void returnTimeStructurefromEpochTime (uint32_t timefromBackupRegs, InternalRTC_DateTime *time1)
{
time_t rawtime = timefromBackupRegs;
struct tm ts;
ts = *localtime (&rawtime);
time1->seconds = ts.tm_sec;
time1->minutes = ts.tm_min;
time1->hours = ts.tm_hour;
time1->day = ts.tm_wday;
time1->date = ts.tm_mday;
time1->month = ts.tm_mon + 1;
time1->year = ts.tm_year + 1900 - 2000;
}
Here is what I wrote in main.c
#define SetDateTimeOnly 0
#define GetDateTimeOnly 1
HAL_PWREx_EnableBkUpReg(); //Enables Backup Regulator
#if SetDateTimeOnly
ISetCurrentDateTime.seconds = 40;
ISetCurrentDateTime.minutes = 19;
ISetCurrentDateTime.hours = 18;
ISetCurrentDateTime.day = 03;
ISetCurrentDateTime.date = 02;
ISetCurrentDateTime.month = 10;
ISetCurrentDateTime.year = 19;
InternalRTC_SetDateTime(&ISetCurrentDateTime);
uint32_t currentTime = returnEpochTime(&ISetCurrentDateTime);
InternalRTC_WriteBackupRegs(RTC_BKP_DR1, RTC_BKP_DR2, currentTime);
#if IndependentDebugging_Main_C
custom_printf("Set Time: %02u:%02u:%02u\t%02u/%02u/20%02u\tDay:%02u\r\n", ISetCurrentDateTime.hours, ISetCurrentDateTime.minutes, ISetCurrentDateTime.seconds, ISetCurrentDateTime.date, ISetCurrentDateTime.month, ISetCurrentDateTime.year, ISetCurrentDateTime.day);
custom_printf("Set Epoch Time: In Dec:- %lu\tIn Hex: %lX\r\n", currentTime, currentTime);
#endif
#endif
#if GetDateTimeOnly
uint32_t currentTime1 = InternalRTC_ReadBackupRegs(RTC_BKP_DR1, RTC_BKP_DR2);
#if IndependentDebugging_Main_C
custom_Printf("Get Epoch Time: In Dec:- %lu\tIn Hex: %lX\r\n", currentTime1, currentTime1);
#endif
returnTimeStructurefromEpochTime(currentTime1, &IGetCurrentDateTime);
InternalRTC_SetDateTime(&IGetCurrentDateTime);
#if IndependentDebugging_Main_C
custom_Printf("Get Parsed Time: %02u:%02u:%02u\t%02u/%02u/20%02u\tDay:%02u\r\n", IGetCurrentDateTime.hours, IGetCurrentDateTime.minutes, IGetCurrentDateTime.seconds, IGetCurrentDateTime.date, IGetCurrentDateTime.month, IGetCurrentDateTime.year, IGetCurrentDateTime.day);
#endif
#endif
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
#if GetDateTimeOnly
InternalRTC_GetDateTime(&IGetCurrentDateTime);
#if IndependentDebugging_Main_C
custom_Printf("%02u:%02u:%02u\t%02u/%02u/20%02u\tDay:%02u\r\n", IGetCurrentDateTime.hours, IGetCurrentDateTime.minutes,IGetCurrentDateTime.seconds, IGetCurrentDateTime.date, IGetCurrentDateTime.month, IGetCurrentDateTime.year, IGetCurrentDateTime.day);
#endif
uint32_t currentTime2 = returnEpochTime(&IGetCurrentDateTime);
InternalRTC_WriteBackupRegs(RTC_BKP_DR1, RTC_BKP_DR2, currentTime2);
HAL_Delay(1000);
#endif
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
If I do not switch off the power supply, the backup registers maintain their values. However, power up just resets them back to 0.
Any help is appreciated.
Thanking You.
2019-12-04 12:57 AM
Is voltage on VBAT high enough and stable, while power is off?
(LSE stability may be impacted by a different supply voltage - during runtime it's VDD, whereas in powerdown it's VBAT)
Does power off mean that VDDA vs. VSSA is zero volts?
Do you have BOD enabled in the option bytes? Try experimenting with it.
(The latter two questions are aimed at the VDD/VBAT switchover)
JW