Skip to main content
lutztonineubert
Associate II
August 7, 2020
Solved

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

  • August 7, 2020
  • 4 replies
  • 1443 views

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;
}

This topic has been closed for replies.
Best answer by lutztonineubert

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.

4 replies

waclawek.jan
Super User
August 7, 2020

> 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

lutztonineubert
Associate II
August 7, 2020

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
 

waclawek.jan
Super User
August 7, 2020

Write a minimal program exhibiting the problem and post it.

JW

lutztonineubert
lutztonineubertAuthorBest answer
Associate II
August 10, 2020

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.