FreeRTOS Clock Configuration

Hello everyone,
I’m using an STM32F303CCT6 to control a TMC5160, a W5500 and some other stuffs. I’m using the STM32Duino FreeRTOS lib with the Arduino frameworks. Everything is working fine except the clock system … The max CPU frequency achievable is 72 MHz. I have a 32 MHz HSE on my board (homemade), I have generated my SystemClockConfig function with STM32CubeMX.

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI
                              |RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV4;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|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_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB|RCC_PERIPHCLK_USART1
                              |RCC_PERIPHCLK_USART2|RCC_PERIPHCLK_I2C1
                              |RCC_PERIPHCLK_RTC;
  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_SYSCLK;
  PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_SYSCLK;
  PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_HSI;
  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
  PeriphClkInit.USBClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

If I check HSE_IN with an oscilloscope I have my 32MHz, as soon as I remove the code above, my crystal stops running as expected. I would say that my clock hardware is fine.

Now, I have just created a dummy sketch to test things:

static void vTask( void * pvParameters)
{
  vTaskDelay(1);

  while (true)
  {
    SerialUSB.println(millis());
    SerialUSB.println(HAL_RCC_GetHCLKFreq()); // return 180 000 000, but should be 72 000 000 ?
    vTaskDelay(1000 / portTICK_PERIOD_MS); // should be a 1 sec delay, but it is rather a 100ms one ...
  }
  
}

void setup()
{
  SystemCoreClock = 72000000; // it has the same behavior with or without this.
  SystemCoreClockUpdate();

  SerialUSB.begin(115200);
  while (!SerialUSB);

  delay(1000);

  xTaskCreate(vTask, "task1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);

  vTaskStartScheduler();
  
}

void loop()
{
  ;
}

This is the first time I’m playing with CPU clocks frequencies. I’m pretty sure I missed something in the documentation.

I tried:

  • Put board_build.f_cpu = 72000000 in the platformio.ini but I read that it’s reserved for esp, isn’t it ? And it doesn’t work anyway, The task is still running 10 times a second;
  • Modify system_stm32f3xx.h to write SystemCoreClock = 72000000;
  • Re-write configCPU_CLOCK_HZ in my STM32FreeRTOSConfig_extra.h;
  • Re-write configTICK_RATE_HZ in my STM32FreeRTOSConfig_extra.h;

Nothing worked for now. If anyone has any idea, or documentation that I might have missed …
Thanks for your help !

What is the platformio.ini? is this using board =robotdyn_blackpill_f303cc?

Hey,
My platformio.ini is as follow:

[env:genericSTM32F303CC]
platform = ststm32
board = genericSTM32F303CC
framework = arduino
lib_deps = stm32duino/STM32duino FreeRTOS@^10.3.2

board_build.f_cpu = 72000000

build_flags =
    -fexceptions
    -D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC
    -D USBCON
;    -D USBD_USE_CDC
	-D HAL_PCD_MODULE_ENABLED


upload_protocol = stlink

I’ve created my own platform, forked from ST STM32 platforms : GitHub - EG-Julien/platform-ststm32: ST STM32: development platform for PlatformIO
I’m using this: https://github.com/EG-Julien/platform-ststm32/blob/develop/boards/genericSTM32F303CC.json

Usually this function has C linkage. If you copy pasted the function into a .cpp file it must be as

extern "C" void SystemClock_Config(void)

otherwise you’re not properly overwriting your default code.

You should not manually do that, remove those lines. The startup files and Arduino framework should call into your overwritten system clock functions, nothing else.

Yep I agree with you:

This part is working since, if I call this function my external quartz start oscillating and all my code is working “faster” than expected.

Yess but nothing is working to set the desired frequency. If I remove all the code that I added, it’s still running more than 10 times faster than expected. And indeed, SystemClock_Config is calling HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) which would set up the correct frequency. And I tried with my STLink and it execute this code but the frequency is not set …

To be on the safe side, I just tried again by removing all the “weird” lines and put extern "C" but it didn’t changed anything. I also tried to put it on an another .cpp file. Same result.

Ah. The STM32HAL needs to know your HSE speed too. So you need

[env:genericSTM32F303CC]
platform = ststm32
board = genericSTM32F303CC
framework = arduino
lib_deps = stm32duino/STM32duino FreeRTOS@^10.3.2
build_flags =
    -fexceptions
    -D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC
    -D USBCON
;    -D USBD_USE_CDC
	-D HAL_PCD_MODULE_ENABLED
; change from default 8MHz to 32MHz
    -DHSE_VALUE=32000000
1 Like

I’m trying right now, I wasn’t aware of this flag …

Is the solution to this problem. Thanks mate for your help.

For completness’ sake, the relevant lines in the code are

Since HSE = 32MHz is probably inherent to your board, you should directly add it in the board’s JSON file’s extra_flags section with -DHSE_VALUE=32000000U.

Another note I can make is that you didn’t really need a whole fork of platform-ststm32 just to add your board defs, if it is one-shot project you can also equivalently put the json file in the project’s board directory.

grafik

For reusability accross many projects, sure then a fork can be used.

1 Like

Yes, I was about to do it. Thanks for extra links, it’s appreciate.

I’m not used to PIO yet, I’ll take a look to the documentation. Indeed just put the JSON file is way easier to maintain over time.

Anyway, thanks a lot for your help.