cancel
Showing results for 
Search instead for 
Did you mean: 

Timeout in RTC_INIT with HSE if an unused register does not have a unspecific entry is set!?

lutztonineubert
Associate III

I have an STM32F446 with a HSE attached. Everything works fine (freeRTOS, CAN, I2C, ADC).

Now I want to use the RTC but I cannot initialized it if I not set PeriphClkInitStruct.PLLI2SDivQ to an unspecific value. RTC_EnterInitMode() from the HAL library does not receive the INIT state of the RTC->ISR.

I don't understand what's happening, because this variable is never read or used else where. There must be a rare side-effect which I don't see.

I compared the assembly output of the whole program with and without `PeriphClkInitStruct.PLLI2SDivQ`. There is no different besides the 0xFFFFFFFF write. :( I compiled the code with GCC 9.2/9.3 for C++ with and without optimization.

The example is from RTC_Calendar of the STM32F446 Nucleo Board. Adjusted to my needs.

RTC_HandleTypeDef RtcHandle{};
 
#define RTC_ASYNCH_PREDIV 124
#define RTC_SYNCH_PREDIV 7999
 
void Error_Handler() {
	while (true) {}
}
 
void init_rtc() {
	RtcHandle.Instance = RTC;
	RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24;
	RtcHandle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;
	RtcHandle.Init.SynchPrediv = RTC_SYNCH_PREDIV;
	RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
	RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
	RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
	__HAL_RTC_RESET_HANDLE_STATE(&RtcHandle);
	
	// Fails with timeout if for ever reason, PLLI2SDivQ is not set to some specific value?
	if (HAL_RTC_Init(&RtcHandle) != HAL_OK)
	{
		/* Initialization Error */
		Error_Handler();
	}
}
 
extern "C" void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc)
{
	RCC_OscInitTypeDef        RCC_OscInitStruct{};
	RCC_PeriphCLKInitTypeDef  PeriphClkInitStruct{};
 
	/*##-1- Enables the PWR Clock and Enables access to the backup domain ###################################*/
	/* To change the source clock of the RTC feature (LSE, LSI), You have to:
	   - Enable the power clock using __HAL_RCC_PWR_CLK_ENABLE()
	   - Enable write access using HAL_PWR_EnableBkUpAccess() function before to
		 configure the RTC clock source (to be done once after reset).
	   - Reset the Back up Domain using __HAL_RCC_BACKUPRESET_FORCE() and
		 __HAL_RCC_BACKUPRESET_RELEASE().
	   - Configure the needed RTc clock source */
	__HAL_RCC_PWR_CLK_ENABLE();
	HAL_PWR_EnableBkUpAccess();
 
	PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
	PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV16;
       // ??????????????????????????????????????????????????????????????????	
        // If this particular member is initialized (not all values work)
	// RTC is in INIT state, otherwise RTC_EnterInitMode timeouts.
	// This value is not used in HAL_RCCEx_PeriphCLKConfig at all!
	// What is happening?
	PeriphClkInitStruct.PLLI2SDivQ = 0xFFFFFFFF; 
	
	if(HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
	{
		Error_Handler();
	}
 
	/*##-3- Enable RTC peripheral Clocks #######################################*/
	/* Enable RTC Clock */
	__HAL_RCC_RTC_ENABLE();
}
 
void SystemClock_Init() {
	if (HAL_Init() != HAL_OK) {
		Error_Handler();
	}
 
	/* Enable Power Control clock */
	__HAL_RCC_PWR_CLK_ENABLE();
 
	/* The voltage scaling allows optimizing the power consumption when the device is
	   clocked below the maximum system frequency, to update the voltage scaling value
	   regarding system frequency refer to product datasheet.  */
	__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
 
	/* Enable HSE Oscillator and activate PLL with HSE as source */
	RCC_OscInitTypeDef RCC_OscInitStruct{.OscillatorType = RCC_OSCILLATORTYPE_HSE,
	                                     .HSEState = RCC_HSE_ON,
	                                     .LSEState = RCC_LSE_OFF,
	                                     .HSIState = RCC_HSI_OFF,
	                                     .HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT,
	                                     .LSIState = RCC_LSI_OFF,
	                                     .PLL = {
	                                       .PLLState = RCC_PLL_ON,
	                                       .PLLSource = RCC_PLLSOURCE_HSE,
	                                       .PLLM = 16,
	                                       .PLLN = 288,
	                                       .PLLP = RCC_PLLP_DIV2,
	                                       .PLLQ = 2,
	                                       .PLLR = 2,
	                                     }};
	if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
		Error_Handler();
	}
 
	/* Activate the Over-Drive mode */
	if (HAL_PWREx_EnableOverDrive() != HAL_OK) {
		Error_Handler();
	}
 
	/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
	clocks dividers */
	RCC_ClkInitTypeDef RCC_ClkInitStruct{
	  .ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2,
	  .SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK,
	  .AHBCLKDivider = RCC_SYSCLK_DIV1,
	  .APB1CLKDivider = RCC_HCLK_DIV4,
	  .APB2CLKDivider = RCC_HCLK_DIV2,
	};
	if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) {
		Error_Handler();
	}
 
	// Check clock configuration.
	// If any value has been changed, the peripheral clocks (PWM, CAN...) have to be adjusted.
	if (HAL_RCC_GetSysClockFreq() != 144000000) {
		Error_Handler();
	}
	if (HAL_RCC_GetHCLKFreq() != 144000000) {
		Error_Handler();
	}
	if (HAL_RCC_GetPCLK1Freq() != 36000000) {
		Error_Handler();
	}
	if (HAL_RCC_GetPCLK2Freq() != 72000000) {
		Error_Handler();
	}
}
 
int main() {
	SystemClock_Init();
 
	init_rtc();
 
	return 0;
}

1 ACCEPTED SOLUTION

Accepted Solutions
lutztonineubert
Associate III

I found the issue but I am surprised I found it not before using the RTC.

We have a C++-HAL library between our application and the stm32f4xx C-HAL library. My application used the C++-HAL library with STM32F446xx support but builds the stm32f44xx library for the STM32F439xx (which was wrong). I really wonder why this didn't crash my application earlier because ADC, CAN, I2C etc. worked quit well.

View solution in original post

4 REPLIES 4

> I compared the assembly output of the whole program with and without `PeriphClkInitStruct.PLLI2SDivQ`.

> There is no different besides the 0xFFFFFFFF write.

What write? Show us.

Or just simply ditch Cube, sparing time for you and us.

JW

I changed the code a little bit to show the one change (same result).

I changed it to:

RCC_PeriphCLKInitTypeDef  PeriphClkInitStruct{
  .PeriphClockSelection = RCC_PERIPHCLK_RTC,
  .PLLI2SDivQ = 0xFFFFFFFF,
  .RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV16,
};
 
extern "C" void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc)
{
 
	/*##-1- Enables the PWR Clock and Enables access to the backup domain ###################################*/
	/* To change the source clock of the RTC feature (LSE, LSI), You have to:
	   - Enable the power clock using __HAL_RCC_PWR_CLK_ENABLE()
	   - Enable write access using HAL_PWR_EnableBkUpAccess() function before to
		 configure the RTC clock source (to be done once after reset).
	   - Reset the Back up Domain using __HAL_RCC_BACKUPRESET_FORCE() and
		 __HAL_RCC_BACKUPRESET_RELEASE().
	   - Configure the needed RTc clock source */
	__HAL_RCC_PWR_CLK_ENABLE();
	HAL_PWR_EnableBkUpAccess();
 
	if(HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
	{
		Error_Handler();
	}
 
	/*##-3- Enable RTC peripheral Clocks #######################################*/
	/* Enable RTC Clock */
	__HAL_RCC_RTC_ENABLE();
}

And here is the assembly diff:

@@ -191883,7 +191883,7 @@ 
   .word   0x00000000 
   .word   0x00000000 
   .word   0x00000000 
-  .word   0x00000000 
+  .word   0xFFFFFFFF 
   .word   0x00000000 
   .word   0x00000000 
   .word   0x00000000
 

Write a minimal program exhibiting the problem and post it.

JW

lutztonineubert
Associate III

I found the issue but I am surprised I found it not before using the RTC.

We have a C++-HAL library between our application and the stm32f4xx C-HAL library. My application used the C++-HAL library with STM32F446xx support but builds the stm32f44xx library for the STM32F439xx (which was wrong). I really wonder why this didn't crash my application earlier because ADC, CAN, I2C etc. worked quit well.