The primary cause of the apparent slowdown is a mismatch between the system clock and the FreeRTOS tick configuration. If SystemCoreClock isn’t updated correctly before FreeRTOS initializes, or if the tick source gets reconfigured without notifying the RTOS, then each RTOS tick may no longer represent the intended 1 ms. In certain board examples like the BLE demo on WBA55CG, this mismatch can stretch delays to around ten times longer than expected. Essentially, vTaskDelay() (which osDelay() calls internally) is counting ticks, not milliseconds.
To fix this, ensure that after the clock setup in your system initialization, you call SystemCoreClockUpdate() so that FreeRTOS knows the correct clock frequency. Additionally, verify configSYSTICK_CLOCK_HZ and configTICK_RATE_HZ in your FreeRTOSConfig.h still align with your hardware configuration. If the SysTick is used as the RTOS tick source—and isn’t updated to reflect a newer clock rate—the RTOS will miscalculate the duration of each tick. ST forums confirm that if the timebase source or system clock changes without proper RTOS updating, then delays can end up being extended by unintended multipliers.
Alternatively, if the HAL tick is coming from a different timer (e.g., TIM6 or TIM7) while FreeRTOS still uses SysTick (or vice versa), this can create divergence between HAL_Delay() (which relies on the HAL tick) and osDelay() (which relies on the RTOS tick). A common workaround is to switch the HAL timebase source to a timer that doesn’t conflict with FreeRTOS's tick, or align both mechanisms to use the same base frequency. This way, both delay functions work consistently and avoid unexpected timing artefacts.
For a look into a different embedded environment combining Rust and FreeRTOS, you might find this article interesting: Running Rust and FreeRTOS on the PADI IoT Stamp