stm32h753 rtc resets after power down (vbat is connected)
Started by 5 years ago●2 replies●latest reply 5 years ago●1379 viewsHello,
I am using a stm32h753 and stm32cubemx, and trying to run the RTC module on VBAT. To do this I have connected a battery to the MCU. RTC is connected to LSE. Next, I set the RTC in my code and then I disconnect the MCU from power source, and then reconnect it again. Based on the documentation, this should automatically switch the RTC power source from VDD to VBAT.
I have commented the MX_RTC_Init() in the startup, so that RTC is not reset when the MCU restart.
Below are the code for system clock config, RTC Init, and the code to read the RTC registers after reset.
- void SystemClock_Config(void)
- {
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
- RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
- RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
- /** Supply configuration update enable
- */
- HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
- /** Configure the main internal regulator output voltage
- */
- __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
- while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
- /** Configure LSE Drive Capability
- */
- HAL_PWR_EnableBkUpAccess();
- __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
- /** Macro to configure the PLL clock source
- */
- __HAL_RCC_PLL_PLLSOURCE_CONFIG(RCC_PLLSOURCE_HSE);
- /** Initializes the CPU, AHB and APB busses clocks
- */
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE;
- RCC_OscInitStruct.HSEState = RCC_HSE_ON;
- RCC_OscInitStruct.LSEState = RCC_LSE_ON;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
- RCC_OscInitStruct.PLL.PLLM = 1;
- RCC_OscInitStruct.PLL.PLLN = 84;
- RCC_OscInitStruct.PLL.PLLP = 2;
- RCC_OscInitStruct.PLL.PLLQ = 4;
- RCC_OscInitStruct.PLL.PLLR = 2;
- RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
- RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
- RCC_OscInitStruct.PLL.PLLFRACN = 0;
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
- {
- Error_Handler();
- }
- /** Initializes the CPU, AHB and APB busses clocks
- */
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
- |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
- |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
- RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
- RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
- RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
- RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV4;
- RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV4;
- RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
- if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
- {
- Error_Handler();
- }
- PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_USART3
- |RCC_PERIPHCLK_SPI1|RCC_PERIPHCLK_SDMMC
- |RCC_PERIPHCLK_ADC;
- PeriphClkInitStruct.PLL2.PLL2M = 1;
- PeriphClkInitStruct.PLL2.PLL2N = 25;
- PeriphClkInitStruct.PLL2.PLL2P = 4;
- PeriphClkInitStruct.PLL2.PLL2Q = 2;
- PeriphClkInitStruct.PLL2.PLL2R = 2;
- PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_3;
- PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOMEDIUM;
- PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
- PeriphClkInitStruct.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL;
- PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
- PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
- PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
- PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
- if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
- {
- Error_Handler();
- }
- }
next is the RTC Init Code
- static 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};
- RTC_AlarmTypeDef sAlarm = {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();
- }
- /** Enable the Alarm A
- */
- sAlarm.AlarmTime.Hours = 0x0;
- sAlarm.AlarmTime.Minutes = 0x20;
- sAlarm.AlarmTime.Seconds = 0x0;
- sAlarm.AlarmTime.SubSeconds = 0x0;
- sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
- sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
- sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY|RTC_ALARMMASK_HOURS;
- sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
- sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
- sAlarm.AlarmDateWeekDay = 0x1;
- sAlarm.Alarm = RTC_ALARM_A;
- if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BCD) != HAL_OK)
- {
- Error_Handler();
- }
- /** Enable the Alarm B
- */
- sAlarm.AlarmTime.Minutes = 0x40;
- sAlarm.Alarm = RTC_ALARM_B;
- if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BCD) != HAL_OK)
- {
- Error_Handler();
- }
- /* USER CODE BEGIN RTC_Init 2 */
- /* USER CODE END RTC_Init 2 */
- }
Next is the code I use to read RTC register values after power reset
- HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
- HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
- float subSecondsFloat = (255 - sTime.SubSeconds );
- subSecondsFloat = (subSecondsFloat /255);
- subSecondsFloat = (subSecondsFloat * 1000);
- year = (uint32_t) (sDate.Year);
- month = (uint32_t) (sDate.Month);
- day = (uint32_t) (sDate.Date);
- hours = (uint32_t) (sTime.Hours);
- minutes = (uint32_t) (sTime.Minutes);
- seconds = (uint32_t) (sTime.Seconds);
- subseconds = (uint32_t) (subSecondsFloat);
- sprintf(usartSendBuffer,"\n%lu,%lu,%lu,%lu,%lu,%lu,%lu\n", year,month,day,hours, minutes,seconds,subseconds);
- printf(usartSendBuffer);
When I disconnect the MCU from power source, and reconnect it to power source, the above code gives the following results (RTC register values) after a power reset:
159,10,9,32,51,51,4294967295
So the RTC is reset somewhere in the MCU reset. Considering that I have disabled the MX_RTC_Init(), I do not know where the RTC is reset.
sorry if the question is elementary, I am really new to this field.
I greatly appreciate any help, thank you.
Best regards,
Vouria
I'm not familiar with this particular chip, nor with the cubemx framework, but I often work with other STM32 chips
On those, to configure the RTC (and some of the oscillators) you need to enable access to them, all sorts of magic words written to enable registers and setting write enable bits in others.
The other thing you could do is to check with a scope whether the LSE is actually running. Put the scope on the X1 pin (which is the drive pin), you should see a low amplitude but stable 32kHz signal there.
In fact, you are not supposed to select the LSE as clock source until a status bit in a register indicates that the oscillator is running and stable. It can take several hundred ms-s (yes, millisecs!) from enabling it, so you need to be patient.
Also, putting a scope on the Vdd and Vbat to see what happens when you disconnect the power might prove to be useful.
Admittedly, that's not much, but maybe someone who's familiar with the cubemx internals will be more helpful.
Hello Kocsonya,
Thank you for your reply, and for the information provided.
I found an example in the firmware package and there was a solution there. The problem is solved by calling the RTC setup in the beginning of the code in main along with other initialization functions. I copy the RTC Init code here.
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.Instance = RTC;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
The information you provided was useful.
Thank you and best regards,
Vouria