cancel
Showing results for 
Search instead for 
Did you mean: 

Changing Clock Frequency on STM32F4xx

martinmartin9
Associate II
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
11 REPLIES 11
martinmartin9
Associate II
Posted on January 20, 2015 at 17:12

Within the HAL_RCC_ClockConfig() function there is a call to,

    HAL_InitTick(TICK_INT_PRIORITY);

If I comment out that line, the target seems to behave, although now the systick interrupt is at the wrong frequency.  There would seem to be some coupling between the HAL tick and the FreeRTOS kernel that is the root cause of the issue....

martinmartin9
Associate II
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.