Skip to main content
DPitt.2
Associate
April 24, 2023
Solved

Issue with the RTC REF_IN on STM32F439NIHx

  • April 24, 2023
  • 17 replies
  • 3397 views

Hi,

I'm having some trouble with trying to correct the RTC drift on a STM32F439NIHx. I've enabled the REF_IN and provided a 50Hz signal on the pin, but the RTC still drifts by around 1s per day.

I've also tested that the 50Hz signal is correctly received by changing the pin to an external interrupt and correctly generated 50 interrupts per seconds.

Am I missing something or doing something wrong in the setup:

Enabling the RTC and the ref in :

 RTC_HandleTypeDef hrtc = RTC_HandleTypeDef();
 hrtc.Instance = RTC;
 hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
 hrtc.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;
 hrtc.Init.SynchPrediv = RTC_SYNCH_PREDIV;
 hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
 hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
 hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
 
 if (HAL_RTC_Init(hrtc) != HAL_OK)
 {
 Error_Handler();
 }
 
 if (HAL_RTCEx_EnableBypassShadow(hrtc) != HAL_OK)
 {
 Error_Handler(); 
 }
 
 if (HAL_RTCEx_SetRefClock(hrtc) != HAL_OK)
 {
 Error_Handler();
 }

and the HAL_RTC_MspInit function:

void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc) {
 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
 GPIO_InitTypeDef GPIO_InitStruct = {0};
 
 /**RTC GPIO Configuration
 PB15 ------> RTC_REFIN
 */
 
 GPIO_InitStruct.Pin = GPIO_PIN_15;
 GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 
 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 HAL_GPIO_LockPin(GPIOB, RTC_REF_IN_PIN); // Lock Pin configuration
 
 // Configure LSE as RTC clock source
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
 RCC_OscInitStruct.LSEState = RCC_LSE_ON;
 RCC_OscInitStruct.LSIState = RCC_LSI_OFF;
 
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
 // Initialization Error
 return;
 }
 
 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
 PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
 
 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
 // Initialization Error
 return;
 }
 
 // Enable RTC peripheral Clocks
 __HAL_RCC_RTC_ENABLE();
 
 // Configure the NVIC for RTC Alarm
 HAL_NVIC_SetPriority(RTC_Alarm_IRQn, 0x0F, 0);
 HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
}

This topic has been closed for replies.
Best answer by waclawek.jan

> GPIO_InitStruct.Pin = GPIO_PIN_15;

> GPIO_InitStruct.Mode = GPIO_MODE_INPUT;

According to Datasheet, RTC_REFIN is PB15 AF0, so you want to set it to Alternate Function.

JW

17 replies

waclawek.jan
Super User
April 24, 2023

I don't have experience with the REF_IN facility, but 1s/day is around 10ppm, are you sure your 50Hz source more precise than that?

What's the raw precision of the LSE?

At any case, read out and check/post content of RTC and RCC_BDTR registers.

JW

DPitt.2
DPitt.2Author
Associate
April 24, 2023

The 50Hz source is a lot more precise than that, under 0.01ppm.

I'm not sure about the LSE precision, but given we get the 1s/day drift also when we don't set the REF_IN, probably around 10ppm.

I don't see a RCC_BDTR register, but RCC_BDCR has the value 0x00008103

The RTC registers are as follow:

RTC_CR 0x00001130
RTC_ISR 0x00000017
RTC_PRER 0x007F00FF
RTC_WURT 0X0000FFFF
RTC_CALIBR 0X00000000
RTC_ALRMAR 0XC1808080
RTC_ALRMBR 0X00000000
RTC_ALRMASSR 0X0F000000
RTC_RESERVED7 0X00002000
RTC_BKP0R 0X000032F2

with the other RTC registers at 0x00000000, or changing for TR, DR and SSR

waclawek.jan
Super User
April 24, 2023

> RTC_BKP0R 0X000032F2

Oh, that unnecessary Cube "signature".

Which makes me to ask: do you power-on/reset the device within the 24-hour period? If yes, couldn't it be this?

JW

DPitt.2
DPitt.2Author
Associate
April 24, 2023

No, though I also have that issue with the reset, in this case the drift happens without any reset on the device during the test.. (The drift is also forward, gaining 1s/day, so it can't be caused by a similar issue, since it would then lose 1s/day).

AScha.3
Super User
April 24, 2023

>under 0.01ppm

thats 10e-8 -- so you have an atomic clock around all the time ?

If you feel a post has answered your question, please click on " Best Answer ".
Tesla DeLorean
Guru
April 24, 2023

GPS or AC Grid synchronization..​

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
AScha.3
Super User
April 24, 2023

obvious ... but : afaik GPS makes 1 Hz output, not 50.

and grid ... now i looked: actual -240ppm away, so "under 0.01ppm" you might get in 10..20 month average, never in 24 h. https://www.netzfrequenzmessung.de/

that's why I'm puzzled...

If you feel a post has answered your question, please click on " Best Answer ".
waclawek.jan
waclawek.janBest answer
Super User
April 24, 2023

> GPIO_InitStruct.Pin = GPIO_PIN_15;

> GPIO_InitStruct.Mode = GPIO_MODE_INPUT;

According to Datasheet, RTC_REFIN is PB15 AF0, so you want to set it to Alternate Function.

JW

DPitt.2
DPitt.2Author
Associate
April 25, 2023

I think we'd already tested with GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; before and the drift was the same.

for GPIO_InitStruct.Alternate = GPIO_AF0_RTC_50Hz; it doesn't change anything since its default value is already 0.

I'll restart a test with GPIO_MODE_AF_PP to be sure, but I don't think that's the issue.

AScha.3
Super User
April 25, 2023

i set refclk in Cube->


_legacyfs_online_stmicro_images_0693W00000bilqFQAQ.pngthen cube gen ->

 /** Enable the reference Clock input
 */
 if (HAL_RTCEx_SetRefClock(&hrtc) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN RTC_Init 2 */

-> and no GPIO_PIN_15 init in main ... !

If you feel a post has answered your question, please click on " Best Answer ".
DPitt.2
DPitt.2Author
Associate
April 25, 2023

I don't use Cube, so I'm not sure how the code generation works, but the GPIO init is probably somewhere. Still, as waclawek.jan said, the GPIO mode I had was INPUT while your screenshot shows it in Alternate, so I'm redoing the test with it in GPIO_MODE_AF_PP. (I think we'd tried this config before, but better to be sure)

AScha.3
Super User
April 25, 2023

so is HAL doing the rtc init:

/**
 * @brief RTC Initialization Function
 * @param None
 * @retval None
 */
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};
 
 /* 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 = 0x11;
 sTime.Minutes = 0x22;
 sTime.Seconds = 0x0;
 sTime.DayLightSaving = RTC_DAYLIGHTSAVING_ADD1H;
 sTime.StoreOperation = RTC_STOREOPERATION_RESET;
 if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
 {
 Error_Handler();
 }
 sDate.WeekDay = RTC_WEEKDAY_TUESDAY;
 sDate.Month = RTC_MONTH_MAY;
 sDate.Date = 0x18;
 sDate.Year = 0x0;
 
 if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
 {
 Error_Handler();
 }
 /** Enable the reference Clock input
 */
 if (HAL_RTCEx_SetRefClock(&hrtc) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN RTC_Init 2 */
 
 /* USER CODE END RTC_Init 2 */
 
}

+ look /step in debug , is it relly going to HAL_RTCEx_SetRefClock()

and doing there ->

/**
 * @brief Enter the RTC Initialization mode.
 * @note The RTC Initialization mode is write protected, use the
 * __HAL_RTC_WRITEPROTECTION_DISABLE() before calling this function.
 * @param hrtc RTC handle
 * @retval HAL status
 */
HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef *hrtc)
{
 uint32_t tickstart;
 HAL_StatusTypeDef status = HAL_OK;
 /* Check if the Initialization mode is set */
#if defined(RTC_ICSR_INITF)
 if((hrtc->Instance->ICSR & RTC_ICSR_INITF) == 0U)
 {
 /* Set the Initialization mode */
 SET_BIT(hrtc->Instance->ICSR, RTC_ICSR_INIT);
 
 tickstart = HAL_GetTick();
 /* Wait till RTC is in INIT state and if Time out is reached exit */
 while (((hrtc->Instance->ICSR & RTC_ICSR_INITF) == 0U) && (status != HAL_TIMEOUT))
 {
 if((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
 {
 status = HAL_TIMEOUT;
 hrtc->State = HAL_RTC_STATE_TIMEOUT;
 }
 }
 }

+

>the GPIO init is probably somewhere

right - found it in HAL_RTC_MspInit( ) :

__HAL_RCC_GPIOB_CLK_ENABLE();
 /**RTC GPIO Configuration
 PB15 ------> RTC_REFIN
 */
 GPIO_InitStruct.Pin = GPIO_PIN_15;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 GPIO_InitStruct.Alternate = GPIO_AF0_RTC_50Hz;
 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
 /* USER CODE BEGIN RTC_MspInit 1 */

 -- this you didnt - right ? >GPIO_InitStruct.Alternate = GPIO_AF0_RTC_50Hz;

If you feel a post has answered your question, please click on " Best Answer ".
waclawek.jan
Super User
April 27, 2023

Any conclusions yet?

JW

DPitt.2
DPitt.2Author
Associate
April 27, 2023

It was indeed the GPIO_InitStruct.Mode = GPIO_MODE_INPUT; that was wrong.

The setup is running now for two days with GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; and the time hasn't drifted.

Thanks a lot for the help.

DP

waclawek.jan
Super User
April 27, 2023

Thanks.

JW