Skip to main content
Visitor II
August 9, 2024
Solved

Is there a secret code required to read and write the RTC value in a STM32H7A3RIT chip?

  • August 9, 2024
  • 2 replies
  • 2309 views

Hi Folks,

I'm having an issue with just reading and writing new values to the RTC. I'm using a custom board that contains a 32.786Khz crystal and in CubeIDE the LSE is setup properly. I also have a battery connected to Vbatt,

I'm using the following to read the RTC values:

 

 

if (HAL_RTC_GetTime(&hrtc, &rtcTime, RTC_FORMAT_BCD) != HAL_OK)
 {
 Error_Handler();
 }

if (HAL_RTC_GetDate(&hrtc, &rtcDate, RTC_FORMAT_BCD) != HAL_OK)
 {
 Error_Handler();
 }

 

 

And to write the RTC values:

 

 

if (HAL_RTC_SetTime(&hrtc, &rtcTime, RTC_FORMAT_BCD) != HAL_OK)
 {
 Error_Handler();
 }

if (HAL_RTC_SetDate(&hrtc, &rtcDate, RTC_FORMAT_BCD) != HAL_OK)
 {
 Error_Handler();
 }

 

This code seems to work as long as I don't hit the reset button or turn off the power.

Why wouldn't the Vbatt voltage keep the values as set? Is there something else I need to do to

write the values into memory?

Thanks,

Richard

 

 

    This topic has been closed for replies.
    Best answer by RCooke88

    I got it working by only using half of what you originally suggested. This is what works (so far):

     /* USER CODE BEGIN Check_RTC_BKUP */
     if((RCC->BDCR & 0x8000) == 0)			// rtc enabled ? <-- this 2 lines
    	 	{
     /* USER CODE END Check_RTC_BKUP */
    	/** Initialize RTC and set the Time and Date
    	*/
    	sTime.Hours = 0x0;
    	sTime.Minutes = 0x0;
    	sTime.Seconds = 0x0;
    	sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
    	sTime.StoreOperation = RTC_STOREOPERATION_RESET;
    	if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
    	{
    	Error_Handler();
    	}
    	sDate.WeekDay = RTC_WEEKDAY_MONDAY;
    	sDate.Month = RTC_MONTH_JANUARY;
    	sDate.Date = 0x1;
    	sDate.Year = 0x0;
    
    	if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
    	{
    	Error_Handler();
    	}
     /* USER CODE BEGIN RTC_Init 2 */
    	}
    	PWR->CR2 |= 0x01;					// bren enable 2
     /* USER CODE END RTC_Init 2 */
    }

    I have reset the board multiple times and cycled the power multiple times and the clock data stays as programmed.

    Thanks for your help. You saved me multiple hours.

    Richard

    2 replies

    Super User
    August 9, 2024

    What does your code look like at initialization? If I recall correctly, the HAL generated stuff will reset the time on startup. You'll need to circumvent that with a check of some sort.

    Set a breakpoint prior to where RTC gets initialized and see if the register values are still there. Probably they are.

    Super User
    August 9, 2024

    Yes, the HAL code will start and init the RTC , as you (user) expect. ok.

    BUT on next start - it will do the same. Not what you want... :)

    Now you want : init new chip, set to a time, but on next start, just dont touch the clock, let time run as expected.

    This is simple, if you put some code in the "user areas" , to get this behaviour:

    static void MX_RTC_Init(void)
    {
    
     /* USER CODE BEGIN RTC_Init 0 */
    
    if((RCC->BDCR & 0x8000) == 0)			// rtc enabled ? <-- this 2 lines
    {
    
    
     /* USER CODE END RTC_Init 0 */

    and at end of mx..init :

     /* USER CODE BEGIN RTC_Init 2 */
    }
    	PWR->CR2 |= 0x01;					// bren enable 2
     /* USER CODE END RTC_Init 2 */

    -> so you just let mx..init run only, if RTC is not enabled = at first start.

    After this its enabled and the IF { ... }  goes without the init and just lets the RTC running.

    RCooke88Author
    Visitor II
    August 9, 2024

    I'm not quite following what you are suggesting. Here is the STM32CubeIDE generated RTC.C code:

    /* RTC init function */
    void MX_RTC_Init(void)
    {
     /* USER CODE BEGIN RTC_Init 0 */
    
     /* USER CODE END RTC_Init 0 */
    	 RTC_TimeTypeDef sTime = {0};
    	 RTC_DateTypeDef sDate = {0};
    	 /* USER CODE BEGIN RTC_Init 1 */
    
    	 /* USER CODE END RTC_Init 1 */
    	 /** Initialize RTC Only
    	 */
    	 hrtc.Instance = RTC;
    	 hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
    	 hrtc.Init.AsynchPrediv = 127;
    	 hrtc.Init.SynchPrediv = 255;
    	 hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
    	 hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
    	 hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
    	 hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
    	 if (HAL_RTC_Init(&hrtc) != HAL_OK)
    	 {
    		Error_Handler();
    	 }
    
     /* USER CODE BEGIN Check_RTC_BKUP */
     /* USER CODE END Check_RTC_BKUP */
    	/** Initialize RTC and set the Time and Date
    	*/
    	sTime.Hours = 0x0;
    	sTime.Minutes = 0x0;
    	sTime.Seconds = 0x0;
    	sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
    	sTime.StoreOperation = RTC_STOREOPERATION_RESET;
    	if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
    	{
    	Error_Handler();
    	}
    	sDate.WeekDay = RTC_WEEKDAY_MONDAY;
    	sDate.Month = RTC_MONTH_JANUARY;
    	sDate.Date = 0x1;
    	sDate.Year = 0x0;
    
    	if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
    	{
    	Error_Handler();
    	}
     /* USER CODE BEGIN RTC_Init 2 */
     /* USER CODE END RTC_Init 2 */
    }

    I'm not 100% sure I know where to put the 2 lines you've recommended. Also what should I do with the Initialize RTC and Set Time and Date code starting at line 31? Do I need this if I'm setting up the clock in my code later?

    Thanks,

    Richard

    Super User
    August 11, 2024

    Now the best thing to do is not to use Cube at all, then you'll have full control over your code, and it can then be easily debugged just by having a look at the registers and into the RM.

    The Cube functions apparently anticipate something to be set, which "normally" is set in HAL_RTC_Init(). Maybe you can still run that function, except I don't know (and I don't care to know) if it still does this.

    You can also try to guess what's missing - one of the things is disabling the debug domain protection (by setting the DBP bit), @AScha.3 's last line is supposed to take care of that (check if it does so in your STM32 model), but maybe your STM32 has an RTC enable bit in RCC and then that needs to be set, too.

    And, of course, you can simply debug Cube as your own code - it's open source - so just step through HAL_RTC_SetTime(), find out where does it return the error and why, and proceed accordingly.

    It's probably obvious, that I don't use Cube/CubeMX.

    JW