EmbeddedRelated.com
Forums

stm32h753 rtc resets after power down (vbat is connected)

Started by vouria 5 years ago2 replieslatest reply 5 years ago1379 views

Hello,

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.

  1. void SystemClock_Config(void)
  2. {
  3. RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  4. RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  5. RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  6. /** Supply configuration update enable
  7. */
  8. HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
  9. /** Configure the main internal regulator output voltage
  10. */
  11. __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  12. while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
  13. /** Configure LSE Drive Capability
  14. */
  15. HAL_PWR_EnableBkUpAccess();
  16. __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
  17. /** Macro to configure the PLL clock source
  18. */
  19. __HAL_RCC_PLL_PLLSOURCE_CONFIG(RCC_PLLSOURCE_HSE);
  20. /** Initializes the CPU, AHB and APB busses clocks
  21. */
  22. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE;
  23. RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  24. RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  25. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  26. RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  27. RCC_OscInitStruct.PLL.PLLM = 1;
  28. RCC_OscInitStruct.PLL.PLLN = 84;
  29. RCC_OscInitStruct.PLL.PLLP = 2;
  30. RCC_OscInitStruct.PLL.PLLQ = 4;
  31. RCC_OscInitStruct.PLL.PLLR = 2;
  32. RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
  33. RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  34. RCC_OscInitStruct.PLL.PLLFRACN = 0;
  35. if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  36. {
  37. Error_Handler();
  38. }
  39. /** Initializes the CPU, AHB and APB busses clocks
  40. */
  41. RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  42. |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
  43. |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  44. RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  45. RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  46. RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
  47. RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  48. RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV4;
  49. RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV4;
  50. RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
  51. if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  52. {
  53. Error_Handler();
  54. }
  55. PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_USART3
  56. |RCC_PERIPHCLK_SPI1|RCC_PERIPHCLK_SDMMC
  57. |RCC_PERIPHCLK_ADC;
  58. PeriphClkInitStruct.PLL2.PLL2M = 1;
  59. PeriphClkInitStruct.PLL2.PLL2N = 25;
  60. PeriphClkInitStruct.PLL2.PLL2P = 4;
  61. PeriphClkInitStruct.PLL2.PLL2Q = 2;
  62. PeriphClkInitStruct.PLL2.PLL2R = 2;
  63. PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_3;
  64. PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOMEDIUM;
  65. PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
  66. PeriphClkInitStruct.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL;
  67. PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
  68. PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
  69. PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
  70. PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
  71. if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  72. {
  73. Error_Handler();
  74. }
  75. }

next is the RTC Init Code

  1. static void MX_RTC_Init(void)
  2. {
  3. /* USER CODE BEGIN RTC_Init 0 */
  4. /* USER CODE END RTC_Init 0 */
  5. RTC_TimeTypeDef sTime = {0};
  6. RTC_DateTypeDef sDate = {0};
  7. RTC_AlarmTypeDef sAlarm = {0};
  8. /* USER CODE BEGIN RTC_Init 1 */
  9. /* USER CODE END RTC_Init 1 */
  10. /** Initialize RTC Only
  11. */
  12. hrtc.Instance = RTC;
  13. hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
  14. hrtc.Init.AsynchPrediv = 127;
  15. hrtc.Init.SynchPrediv = 255;
  16. hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
  17. hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  18. hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
  19. hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
  20. if (HAL_RTC_Init(&hrtc) != HAL_OK)
  21. {
  22. Error_Handler();
  23. }
  24. /* USER CODE BEGIN Check_RTC_BKUP */
  25. /* USER CODE END Check_RTC_BKUP */
  26. /** Initialize RTC and set the Time and Date
  27. */
  28. sTime.Hours = 0x0;
  29. sTime.Minutes = 0x0;
  30. sTime.Seconds = 0x0;
  31. sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  32. sTime.StoreOperation = RTC_STOREOPERATION_RESET;
  33. if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
  34. {
  35. Error_Handler();
  36. }
  37. sDate.WeekDay = RTC_WEEKDAY_MONDAY;
  38. sDate.Month = RTC_MONTH_JANUARY;
  39. sDate.Date = 0x1;
  40. sDate.Year = 0x0;
  41. if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
  42. {
  43. Error_Handler();
  44. }
  45. /** Enable the Alarm A
  46. */
  47. sAlarm.AlarmTime.Hours = 0x0;
  48. sAlarm.AlarmTime.Minutes = 0x20;
  49. sAlarm.AlarmTime.Seconds = 0x0;
  50. sAlarm.AlarmTime.SubSeconds = 0x0;
  51. sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  52. sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
  53. sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY|RTC_ALARMMASK_HOURS;
  54. sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
  55. sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
  56. sAlarm.AlarmDateWeekDay = 0x1;
  57. sAlarm.Alarm = RTC_ALARM_A;
  58. if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BCD) != HAL_OK)
  59. {
  60. Error_Handler();
  61. }
  62. /** Enable the Alarm B
  63. */
  64. sAlarm.AlarmTime.Minutes = 0x40;
  65. sAlarm.Alarm = RTC_ALARM_B;
  66. if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BCD) != HAL_OK)
  67. {
  68. Error_Handler();
  69. }
  70. /* USER CODE BEGIN RTC_Init 2 */
  71. /* USER CODE END RTC_Init 2 */
  72. }

Next is the code I use to read RTC register values after power reset

  1. HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
  2. HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
  3. float subSecondsFloat = (255 - sTime.SubSeconds );
  4. subSecondsFloat = (subSecondsFloat /255);
  5. subSecondsFloat = (subSecondsFloat * 1000);
  6. year = (uint32_t) (sDate.Year);
  7. month = (uint32_t) (sDate.Month);
  8. day = (uint32_t) (sDate.Date);
  9. hours = (uint32_t) (sTime.Hours);
  10. minutes = (uint32_t) (sTime.Minutes);
  11. seconds = (uint32_t) (sTime.Seconds);
  12. subseconds = (uint32_t) (subSecondsFloat);
  13. sprintf(usartSendBuffer,"\n%lu,%lu,%lu,%lu,%lu,%lu,%lu\n", year,month,day,hours, minutes,seconds,subseconds);
  14. 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

[ - ]
Reply by KocsonyaMarch 26, 2020

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.

[ - ]
Reply by vouriaMarch 26, 2020

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