2025-12-05 1:37 AM - edited 2025-12-05 7:03 AM
Hi everyone,
I am using a STM32H563RG and I need the RTC to work even if the VDD is powered off. To do that, I am plugging a battery on the VBAT pin to power the RTC and the Backup domain. But I tested it and it seems the RTC is stopped and the backup domain is cleared when VDD is powered off.
Here is my initialisation code :
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_GPDMA1_Init();
MX_ICACHE_Init();
MX_CRC_Init();
MX_SPI1_Init();
MX_TIM3_Init();
//MX_RTC_Init();
MX_ADC1_Init();
MX_ADC2_Init();
MX_TIM2_Init();
MX_FileX_Init();
MX_IWDG_Init();
MX_TouchGFX_Init();
/* USER CODE BEGIN 2 */
LL_PWR_EnableBkUpRegulator();
LL_PWR_EnableBkUpAccess();
if(LL_RTC_BKP_GetRegister(RTC,LL_RTC_BKP_DR0) == 0x32F2){ //Read Backup register to see if it was previously written
RTC_Datas.RTC_initialized = 1; //Set flag
GPIO_Set(Led_orang); //Turn Orange LED On
}
else{ //If not previously written
RTC_Datas.RTC_initialized = 0; //Clear flag
MX_RTC_Init(); //Call RTC_Init() to initialise RTC
}
RTC_Datas.Jour = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_DATE_GetDay(RTC)); //Read day
RTC_Datas.Mois = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_DATE_GetMonth(RTC)); //Read month
RTC_Datas.Annee = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_DATE_GetYear(RTC)) + 2000; //Read year
RTC_Datas.Minute = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_TIME_GetMinute(RTC));//Read minutes
RTC_Datas.Heure = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_TIME_GetHour(RTC)); //Read hours
The value 0x32F2 is written in the BKR0 backup register by the MX_RTC_Init() function. It should stay written in it even if there is a µC reset (with VBAT at 3,3V). I check if the RTC was previously initialised by reading this backup register : if I read 0x32F2, it means it was initialised and a Orange LED is turned ON. However, after a reset (performed by the VDD being powered off then powered on right away), the Orange LED doesn't turn ON and the RTC values are reinitialised.
What I made sure of :
It seems there is no Backup domain reset happening since the RTCSEL bit field of RCC->BDCR stays at 1 after reset ( it would be equal to 0 after a bakcup domain reset).
I therefore have three questions :
1) Are the RTC values saved in the backup domain or it is two different things ?
2) Is my test method correct to prove the Backup register is cleared ?
3) What could clear the Backup register and the RTC values reset ?
Solved! Go to Solution.
2025-12-15 3:19 AM
Ok I solved my issue. At reset, we must set RTCAPBEN in RCC->APB3ENR to enable the backup domain clock, and enable the IRQ on RTC (not saved in the Backup domain apparently).I also added a small delay after reading the backup register and before reading the saved RTC values because the date I read wasn't always correct. I suspect a startup latency of the backup regulator.
Here is my code :
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
LL_EXTI_DisableIT_0_31(LL_EXTI_LINE_0); //Désactivation des interruption sur KEY_SELECT
LL_EXTI_DisableIT_0_31(LL_EXTI_LINE_10); //Désactivation des interruptions sur PSE
LL_EXTI_DisableFallingTrig_0_31(LL_EXTI_LINE_13); //Disable IRQ on T_com
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_GPDMA1_Init();
MX_ICACHE_Init();
MX_CRC_Init();
MX_SPI1_Init();
MX_TIM3_Init();
//MX_RTC_Init();
MX_ADC1_Init();
MX_ADC2_Init();
MX_TIM2_Init();
MX_FileX_Init();
MX_IWDG_Init();
MX_TouchGFX_Init();
/* USER CODE BEGIN 2 */
LL_PWR_EnableBkUpRegulator();
LL_APB3_GRP1_EnableClock(LL_APB3_GRP1_PERIPH_RTCAPB); //Enable Backup domain clock
LL_PWR_EnableBkUpAccess();
if(LL_RTC_BKP_GetRegister(RTC,LL_RTC_BKP_DR0) == 0x32F2){ //Read Backup register to see if it was previously written
NVIC_SetPriority(RTC_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(RTC_IRQn); //Enable RTC IRQ
HAL_Delay(20); //Small delay before reading RTC values
}
else{ //If not previously written
MX_RTC_Init(); //Call RTC_Init() to initialise RTC
}
RTC_Datas.Jour = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_DATE_GetDay(RTC)); //Récuperation du jour
RTC_Datas.Mois = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_DATE_GetMonth(RTC)); //Récuperation du mois
RTC_Datas.Annee = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_DATE_GetYear(RTC)) + 2000;//Récuperation de l'année
RTC_Datas.Minute = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_TIME_GetMinute(RTC));//Récuperation de la minute
RTC_Datas.Heure = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_TIME_GetHour(RTC)); //Récuperation de l'heure
2025-12-05 1:42 AM
Welcome to the forum.
Please see: How to write your question to maximize your chances to find a solution for best results.
In particular, please give details of your hardware.
2025-12-10 5:59 AM - edited 2025-12-10 6:04 AM
Hi again,
Here is my connection diagram :
Vbat is around 3,5V normally. It is not charged by the µC but by a dedicated circuit. I also deactivated the measure on Vbat since the measuring error is about 10%.
2025-12-12 8:13 AM
hello @Karakala
If you review the diagram in the datasheet, you will find out that the backup domain contains RTC and other peripherals.
Honestly, this is not a commonly known issue because The RTC is supposed to be functional in VBAT mode and in all low-power modes when it is clocked by the LSE. however, can you verify the selected LSE driving capability option is compatible with your gain margin? you can use AN2867 to calculate it.
You can refer to this thread also.
Hope that helps as a start
Gyessine
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2025-12-13 10:27 AM
Does the problem happen only upon power off/on, or also when using a NRST reset?
Read out and check/compare-to-pre-reset-state/post content of RTC, TAMPER and RCC_BDCR registers. Do you have enabled RCC_APB3ENR.RTCAPBEN?
JW
2025-12-15 1:07 AM
Hi @Gyessine
Thanks for answering me. I calculated it with my quartz parametters (ESR = 50kR typ/70kR max, C0 = 1,7pF and CL = 12,5pF), I makes gmcrit = 1,71µA/V. It means that only the High Drive Capabilty has a higher value (2,7µA/V) according to the STM32H563 datasheet. My gain margin would be inferior to 5 ?
But yet it works since my RTC is running correctly when it is powered. This could explain that it is not saved ?
2025-12-15 1:15 AM - edited 2025-12-15 1:24 AM
Thanks for your answer.
It didn't work also using a NRST reset. But at reset I didn't enabled RCC_APB3ENR.RTCAPBEN, I thought it was supposed to be saved at reset. Now it's enabled before reading the backup register, and the RTC is saved using a NRST reset, but not using a power off reset. However the value 0x32F2 is saved in the backup register BKPDR0 in both reset case. I checked again if there was no voltage drop on Vbat and if the quartz still runs at power off, no issue there.
That's not finished yet, but that's an advance !
Here is my updated code :
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
LL_EXTI_DisableIT_0_31(LL_EXTI_LINE_0); //Désactivation des interruption sur KEY_SELECT
LL_EXTI_DisableIT_0_31(LL_EXTI_LINE_10); //Désactivation des interruptions sur PSE
LL_EXTI_DisableFallingTrig_0_31(LL_EXTI_LINE_13); //Disable IRQ on T_com
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_GPDMA1_Init();
MX_ICACHE_Init();
MX_CRC_Init();
MX_SPI1_Init();
MX_TIM3_Init();
//MX_RTC_Init();
MX_ADC1_Init();
MX_ADC2_Init();
MX_TIM2_Init();
MX_FileX_Init();
MX_IWDG_Init();
MX_TouchGFX_Init();
/* USER CODE BEGIN 2 */
LL_PWR_EnableBkUpRegulator();
LL_APB3_GRP1_EnableClock(LL_APB3_GRP1_PERIPH_RTCAPB);
LL_PWR_EnableBkUpAccess();
if(LL_RTC_BKP_GetRegister(RTC,LL_RTC_BKP_DR0) == 0x32F2){ //Read Backup register to see if it was previously written
RTC_Datas.RTC_initialized = 1; //Set flag
LL_RCC_EnableRTC();
GPIO_Set(Led_orang); //Turn Orange LED On
}
else{ //If not previously written
RTC_Datas.RTC_initialized = 0; //Clear flag
MX_RTC_Init(); //Call RTC_Init() to initialise RTC
}
RTC_Datas.Jour = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_DATE_GetDay(RTC)); //Récuperation du jour
RTC_Datas.Mois = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_DATE_GetMonth(RTC)); //Récuperation du mois
RTC_Datas.Annee = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_DATE_GetYear(RTC)) + 2000;//Récuperation de l'année
RTC_Datas.Minute = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_TIME_GetMinute(RTC));//Récuperation de la minute
RTC_Datas.Heure = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_TIME_GetHour(RTC)); //Récuperation de l'heure
2025-12-15 3:14 AM
Read out and check/compare-to-pre-reset-state/post content of RTC, TAMPER and RCC_BDCR registers,
JW
2025-12-15 3:19 AM
Ok I solved my issue. At reset, we must set RTCAPBEN in RCC->APB3ENR to enable the backup domain clock, and enable the IRQ on RTC (not saved in the Backup domain apparently).I also added a small delay after reading the backup register and before reading the saved RTC values because the date I read wasn't always correct. I suspect a startup latency of the backup regulator.
Here is my code :
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
LL_EXTI_DisableIT_0_31(LL_EXTI_LINE_0); //Désactivation des interruption sur KEY_SELECT
LL_EXTI_DisableIT_0_31(LL_EXTI_LINE_10); //Désactivation des interruptions sur PSE
LL_EXTI_DisableFallingTrig_0_31(LL_EXTI_LINE_13); //Disable IRQ on T_com
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_GPDMA1_Init();
MX_ICACHE_Init();
MX_CRC_Init();
MX_SPI1_Init();
MX_TIM3_Init();
//MX_RTC_Init();
MX_ADC1_Init();
MX_ADC2_Init();
MX_TIM2_Init();
MX_FileX_Init();
MX_IWDG_Init();
MX_TouchGFX_Init();
/* USER CODE BEGIN 2 */
LL_PWR_EnableBkUpRegulator();
LL_APB3_GRP1_EnableClock(LL_APB3_GRP1_PERIPH_RTCAPB); //Enable Backup domain clock
LL_PWR_EnableBkUpAccess();
if(LL_RTC_BKP_GetRegister(RTC,LL_RTC_BKP_DR0) == 0x32F2){ //Read Backup register to see if it was previously written
NVIC_SetPriority(RTC_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(RTC_IRQn); //Enable RTC IRQ
HAL_Delay(20); //Small delay before reading RTC values
}
else{ //If not previously written
MX_RTC_Init(); //Call RTC_Init() to initialise RTC
}
RTC_Datas.Jour = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_DATE_GetDay(RTC)); //Récuperation du jour
RTC_Datas.Mois = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_DATE_GetMonth(RTC)); //Récuperation du mois
RTC_Datas.Annee = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_DATE_GetYear(RTC)) + 2000;//Récuperation de l'année
RTC_Datas.Minute = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_TIME_GetMinute(RTC));//Récuperation de la minute
RTC_Datas.Heure = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_TIME_GetHour(RTC)); //Récuperation de l'heure
2025-12-15 3:26 AM
I also added a small delay after reading the backup register and before reading the saved RTC values because the date I read wasn't always correct.
If you don't have RTC_CR.BYPSHAD set (and I suspect you don't, as that's the default), you have to wait until RTC_ICSR.RSF is set before reading the RTC time and date, see Reading the calendar subchapter in RTC chapter in RM.
JW