Skip to main content
martinmartin9
Associate II
January 9, 2015
Question

Changing Clock Frequency on STM32F4xx

  • January 9, 2015
  • 11 replies
  • 3631 views
Posted on January 10, 2015 at 00:05

Having trouble changing the STM32F4 clock (M4 clock) on the fly, dynamically. When I do, the target fails, sometimes not right away, but within a few dozen seconds. How do I know its failing? I have a task attached to a button, that toggles LEDs. When I change the clock frequency, I push the button, and eventually the LEDs no longer toggle. The UART debug interface dies right away - note that when I change frequencies, I keep the peripheral bus at the same frequency. GDB shows the target is stuck in a task that was sending chars out the UART...

Using: FreeRTOS ver 8.1.2. STM32F439 STM32Cube generates the following code for setting the clock on power up,

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE; 
RCC_OscInitStruct.HSEState = RCC_HSE_ON; 
RCC_OscInitStruct.HSIState = RCC_HSI_ON; 
RCC_OscInitStruct.HSICalibrationValue = 6; 
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; 
RCC_OscInitStruct.PLL.PLLM = 8; 
RCC_OscInitStruct.PLL.PLLN = 192; 
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV8; 
RCC_OscInitStruct.PLL.PLLQ = 4; 
HAL_RCC_OscConfig(&RCC_OscInitStruct); 
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK; 
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; 
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV2; 
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; 
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; 
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);

This works fine. I can use Cube32 to select other clock frequencies and they also work, when run at power up.

The dynamic switching code looks like this,

case
POWMAN_LOW: 
// 12MHz 
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE; 
RCC_OscInitStruct.HSEState = RCC_HSE_ON; 
RCC_OscInitStruct.HSIState = RCC_HSI_ON; 
RCC_OscInitStruct.HSICalibrationValue = 6; 
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; 
RCC_OscInitStruct.PLL.PLLM = 8; 
RCC_OscInitStruct.PLL.PLLN = 192; 
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV8; 
RCC_OscInitStruct.PLL.PLLQ = 4; 
HAL_RCC_OscConfig(&RCC_OscInitStruct); 
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK; 
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; 
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV2; 
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; 
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; 
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0); 
break
; 
case
POWMAN_MED: 
// 48MHz 
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE; 
RCC_OscInitStruct.HSEState = RCC_HSE_ON; 
RCC_OscInitStruct.HSIState = RCC_HSI_ON; 
RCC_OscInitStruct.HSICalibrationValue = 6; 
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; 
RCC_OscInitStruct.PLL.PLLM = 8; 
RCC_OscInitStruct.PLL.PLLN = 192; 
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4; 
RCC_OscInitStruct.PLL.PLLQ = 4; 
HAL_RCC_OscConfig(&RCC_OscInitStruct); 
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1 
|RCC_CLOCKTYPE_PCLK2; 
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; 
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; 
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; 
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV4; 
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1); 
break
;

I have reviewed the RCC examples for the STM32F4, read the Power Modes app note, read the HAL library documentation, etc... I am not sure if this is a FreeRTOS issue, or if I am using HAL the wrong way....? #stm32f4-rcc #pll
This topic has been closed for replies.

11 replies

martinmartin9
Associate II
January 20, 2015
Posted on January 20, 2015 at 18:20

It seems to be a priority issue. STM HAL wants to set the sys tick int priority to 0 (highest priority), whereas FreeRTOS wants to set the priority to 15 (lowest priority). The function to re-init the systick interrupt frequency/priority is a __weak function, so I have overridden and I remove the code that set the priority. This seems to work. It also violates comments in HAL where they indicate they need priority 0 for systick for some of the HAL driver...

* @note In the 
default
implementation, SysTick timer is the source of 
time
base. 
* It is used to generate interrupts at regular 
time
intervals. 
* Care must be taken 
if
HAL_Delay() is called from a peripheral ISR process, 
* The the SysTick interrupt must have higher priority (numerically lower) 
* than the peripheral interrupt. Otherwise the caller ISR process will be blocked. 
* The function is declared as __weak to be overwritten in 
case
of other 
* implementation in user file.