cancel
Showing results for 
Search instead for 
Did you mean: 

RTC not working on Vbat

Karakala
Associate II

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 :

  • RTC is clocked on LSE
  • LSE drive capabilty is HIGH
  • TAMP secure zone is deactivated
  • VBAT stays at approx. 3V3 during reset
  • LSE still on after reset
  • BREN bit of PWR->BDCR is set (to enable backup regulator)

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 ?

1 ACCEPTED SOLUTION

Accepted Solutions
Karakala
Associate II

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

 

View solution in original post

10 REPLIES 10
Andrew Neil
Super User

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.

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.
Karakala
Associate II

Hi again,

Here is my connection diagram :

Karakala_0-1765375132570.png

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%.

 

Gyessine
ST Employee

hello @Karakala 
If you review the diagram in the datasheet, you will find out that the backup domain contains RTC and other peripherals.

Gyessine_0-1765554079681.png

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.

waclawek.jan
Super User

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

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 ?

 

Hi @waclawek.jan 

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

 

Read out and check/compare-to-pre-reset-state/post content of RTC, TAMPER and RCC_BDCR registers,

JW

Karakala
Associate II

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

 

waclawek.jan
Super User

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