Using STM32 RTC backup registers

The STM32F4's RTC has 20 x 32-bit backup registers RTC_BKP_DR0 to RTC_BKP_DR19, which are maintained while in a power-off state if Vbat is supplied from a coin-cell battery or other.

There is no support in mbed's libraries for reading/writing from them, but again we can use STM HAL library calls instead.

I wrote a couple of functions as wrappers around the HAL calls:

uint32_t rtc_read_backup_reg(uint32_t BackupRegister) {
    RTC_HandleTypeDef RtcHandle;
    RtcHandle.Instance = RTC;
    return HAL_RTCEx_BKUPRead(&RtcHandle, BackupRegister);
}

void rtc_write_backup_reg(uint32_t BackupRegister, uint32_t data) {
    RTC_HandleTypeDef RtcHandle;
    RtcHandle.Instance = RTC;
    HAL_PWR_EnableBkUpAccess();
    HAL_RTCEx_BKUPWrite(&RtcHandle, BackupRegister, data);
    HAL_PWR_DisableBkUpAccess();
}

Currently, if you set the time using the mbed library, the backup registers are erased.To avoid this, we must use mbed-dev & edit your STM32`s rtc_api.c. Comment out

rtc_api.c rtc_init()

/*
        __HAL_RCC_BACKUPRESET_FORCE();
        __HAL_RCC_BACKUPRESET_RELEASE();
*/

then your data will survive setting the clock. Issue raised.


5 comments on Using STM32 RTC backup registers:

25 Jan 2017

Hi Dave,

accessing the RTC backup registers works on a Nucleo F401RE but not on a Nucleo F103RB.

Obviously the HW is different. The data sheet for the F103 says: "The backup registers are ten 16-bit registers used to store 20 bytes ..." For the F401: "The backup registers are 32-bit registers used to store 80 bytes..." That may explain why the wrapper functions (above) don't work for the F103.

Can somebody explain what to do to access the backup registers in the F103 ??

03 Mar 2020

Hi all Already implemented RTC backup for STM32F103 in the RTCInit with those function above. Check this.

  1. include "rtc.h"
  2. define HOUR_BCKP_REG 1
  3. define MIN_BCKP_REG 2
  4. define SEC_BCKP_REG 3
  5. define WEEKDAY_BCKP_REG 4
  6. define MONTH_BCKP_REG 5
  7. define DATE_BCKP_REG 6
  8. define YEAR_BCKP_REG 7
  9. define WEEKDAY_CURR 2
  10. define MONTH_CURR 2
  11. define DATE_CURR 3
  12. define YEAR_CURR 20 RTC_HandleTypeDef hrtc; static uint8_t DayCurr=0; void rtc_write_backup_reg(uint32_t BackupRegister, uint32_t data); uint32_t rtc_read_backup_reg(uint32_t BackupRegister); RTC_DateTypeDef DateToUpdate = {0}; void MX_RTC_Init(void) { RTC_TimeTypeDef sTime={0}; volatile uint8_t weekday; volatile uint8_t month; volatile uint8_t date; volatile uint8_t year; /*Initialize RTC Only */ hrtc.Instance = RTC; hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND; hrtc.Init.OutPut = RTC_OUTPUTSOURCE_ALARM; if (HAL_RTC_Init(&hrtc) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN Check_RTC_BKUP */ weekday = rtc_read_backup_reg (WEEKDAY_BCKP_REG); month = rtc_read_backup_reg (MONTH_BCKP_REG); date = rtc_read_backup_reg (DATE_BCKP_REG); year = rtc_read_backup_reg (YEAR_BCKP_REG); if ((weekday && month && date && year) == 0) { DateToUpdate.WeekDay = WEEKDAY_CURR; DateToUpdate.Month = MONTH_CURR; DateToUpdate.Date = DATE_CURR; DateToUpdate.Year = YEAR_CURR; rtc_write_backup_reg(WEEKDAY_BCKP_REG,DateToUpdate.WeekDay & 0x00FF); rtc_write_backup_reg(MONTH_BCKP_REG,DateToUpdate.Month & 0x00FF); rtc_write_backup_reg(DATE_BCKP_REG,DateToUpdate.Date & 0x00FF); rtc_write_backup_reg(YEAR_BCKP_REG, DateToUpdate.Year & 0x00FF); } else { DateToUpdate.WeekDay = weekday; DateToUpdate.Month = month; DateToUpdate.Date = date; DateToUpdate.Year = year; } /* USER CODE END Check_RTC_BKUP */ sTime.Hours = 0x0; sTime.Minutes = 0x0; sTime.Seconds = 0x0; if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK) { Error_Handler(); } if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BCD) != HAL_OK) { Error_Handler(); } } void rtc_write_backup_reg(uint32_t BackupRegister, uint32_t data) { hrtc.Instance = RTC; HAL_PWR_EnableBkUpAccess(); HAL_RTCEx_BKUPWrite(&hrtc, BackupRegister, data); HAL_PWR_DisableBkUpAccess(); }

uint32_t rtc_read_backup_reg(uint32_t BackupRegister) { hrtc.Instance = RTC; return HAL_RTCEx_BKUPRead(&hrtc, BackupRegister); }

18 Mar 2022 This post is awaiting moderation

Can somebody explain what to do to access the backup registers in the F103 ??

29 Mar 2022 This post is awaiting moderation

i'm using Nucleo F103 RB to use back up register i used the functions above all you have to do is to copy and past the two functions to your main or your freetos it depends in the way your working after that you just call those functions .

in the code bellow i tried to calculate the number of hours my stm is working where H_S is the number of hour of service Note that you must connect the VBAT pin to a battery otherwise your back up register will be erase with each reset

uint32_t rtc_read_backup_reg(uint32_t BackupRegister) { RTC_HandleTypeDef RtcHandle; RtcHandle.Instance = RTC; return HAL_RTCEx_BKUPRead(&RtcHandle, BackupRegister); }

void rtc_write_backup_reg(uint32_t BackupRegister, uint32_t data) { RTC_HandleTypeDef RtcHandle; RtcHandle.Instance = RTC; HAL_PWR_EnableBkUpAccess(); HAL_RTCEx_BKUPWrite(&RtcHandle, BackupRegister, data); HAL_PWR_DisableBkUpAccess(); }

/* USER CODE END 2 */

/* Infinite loop */ /* USER CODE BEGIN WHILE */ RTC_TimeTypeDef currTime ; RTC_DateTypeDef currDate = {0}; uint32_t H_S = rtc_read_backup_reg(RTC_BKP_DR1) ; init the variable directly from the backup register(must be unit32_t) int time_state = 1; char * str = malloc (sizeof(str)); char buffer[50];

while (1) { HAL_RTC_GetTime(&hrtc, &currTime, RTC_FORMAT_BIN); HAL_RTC_GetDate(&hrtc, &currDate, RTC_FORMAT_BIN); if(currTime.Minutes == 59){++H_S;} if (H_S != time_state){ rtc_write_backup_reg(RTC_BKP_DR1, H_S); write to the backup register itoa(H_S,str,10); sprintf(buffer, "hours of service : %s \r\n", str); HAL_UART_Transmit(&huart2, buffer, sizeof(buffer), 100); time_state = H_S;

}

HAL_Delay(1000); /* USER CODE END WHILE */

29 Mar 2022 This post is awaiting moderation

uint32_t rtc_read_backup_reg(uint32_t BackupRegister) {
	    RTC_HandleTypeDef RtcHandle;
	    RtcHandle.Instance = RTC;
	    return HAL_RTCEx_BKUPRead(&RtcHandle, BackupRegister);
	}

	void rtc_write_backup_reg(uint32_t BackupRegister, uint32_t data) {
	    RTC_HandleTypeDef RtcHandle;
	    RtcHandle.Instance = RTC;
	    HAL_PWR_EnableBkUpAccess();
	    HAL_RTCEx_BKUPWrite(&RtcHandle, BackupRegister, data);
	    HAL_PWR_DisableBkUpAccess();
	}

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  	  	RTC_TimeTypeDef currTime ;
  	  	RTC_DateTypeDef currDate = {0};
      	uint32_t H_S = rtc_read_backup_reg(RTC_BKP_DR1) ;
      	int time_state = 1;
      	char * str = malloc (sizeof(str));
      	char * stm = malloc (sizeof(stm));
      	char * sth = malloc (sizeof(sth));
      	char buffer[50];

  while (1)
  {
	     HAL_RTC_GetTime(&hrtc, &currTime, RTC_FORMAT_BIN);
		 HAL_RTC_GetDate(&hrtc, &currDate, RTC_FORMAT_BIN);
		 if(currTime.Seconds >= 20){++H_S;}
		 if (H_S != time_state){
			 rtc_write_backup_reg(RTC_BKP_DR1, H_S);
			 itoa(H_S,str,10);
			 sprintf(buffer, "hours of service : %s \r\n", str);
			 HAL_UART_Transmit(&huart2, buffer, sizeof(buffer), 100);
			 time_state = H_S;

		 }

		 HAL_Delay(1000);
    /* USER CODE END WHILE */

Please log in to post comments.