You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32创建FreeRTOS互斥量后HAL Tick停滞问题求助

问题:创建FreeRTOS互斥量后HAL Tick计时器停止增长

环境信息

  • 开发环境:STM32CubeIDE 1.11.2
  • 代码生成工具:CubeMX 6.7.0
  • 测试平台:Nucleo-F767ZI

复现步骤

  1. 在STM32CubeIDE中新建默认配置的STM32项目;
  2. 在MX视角打开ioc文件,添加CMSIS_V2接口的FreeRTOS支持;
  3. 在main.c的osKernelInitialize()后添加以下代码:
osMutexId_t mutex = osMutexNew(0);
HAL_Delay(100);

现象

代码卡在HAL_Delay()中,SysTick_Handler不再被调用,HAL_GetTick()始终返回固定值(测试中为10)。已尝试使用CMSIS及FreeRTOS原生互斥量函数、更换SysTick时基、更换Nucleo开发板,问题均未解决。


问题分析与解决

核心原因

在操作系统内核未启动的阶段调用了FreeRTOS互斥量创建函数osMutexNew(),会触发FreeRTOS内部的临界区操作,但此时内核调度器尚未启动,SysTick的调度定时器逻辑被破坏,最终导致HAL Tick停止更新。

osKernelInitialize()仅完成内核初始化,调度器并未启动,FreeRTOS的核心调度逻辑(包括SysTick接管)还未进入正常工作状态。此时调用内核对象创建函数会打乱系统定时器的正常执行流程,而后续的HAL_Delay()依赖SysTick计时,自然会卡住。

解决方法

将互斥量创建及HAL_Delay()的调用移到内核启动之后(即osKernelStart()执行完毕后),或者直接在CubeMX预留的内核对象创建块中操作,避免在osKernelInitialize()和osKernelStart()之间调用依赖调度的API。

方案一:移至内核启动后

修改main.c代码如下:

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();

  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Init scheduler */
  osKernelInitialize();

  /* Create the mutexes */
  /* USER CODE BEGIN RTOS_MUTEX */
  /* 可在此块创建互斥量,但不要调用HAL_Delay */
  /* USER CODE END RTOS_MUTEX */

  /* Create the thread(s) */
  /* USER CODE BEGIN RTOS_THREADS */
  /* USER CODE END RTOS_THREADS */

  /* Start scheduler */
  osKernelStart();

  /* USER CODE BEGIN 3 */
  // 内核启动后执行以下操作
  osMutexId_t mutex = osMutexNew(0);
  HAL_Delay(100);
  /* USER CODE END 3 */

  while (1)
  {
  }
}

方案二:在预留块中创建互斥量(推荐)

直接在CubeMX生成的RTOS_MUTEX注释块中创建互斥量,确保调度器启动前完成对象初始化,之后在任务中调用HAL_Delay():

/* Create the mutexes */
/* USER CODE BEGIN RTOS_MUTEX */
osMutexId_t mutex = osMutexNew(0);
/* USER CODE END RTOS_MUTEX */

/* Create the thread(s) */
/* USER CODE BEGIN RTOS_THREADS */
osThreadNew(TaskFunction, NULL, &TaskAttributes);
/* USER CODE END RTOS_THREADS */

// 任务函数示例
void TaskFunction(void *argument)
{
  for(;;)
  {
    HAL_Delay(100);
    osDelay(100); // 推荐使用FreeRTOS原生延时API
  }
}

补充说明

  1. FreeRTOS内核对象(互斥量、队列、线程等)建议在调度器启动前创建,CubeMX预留的RTOS_MUTEX、RTOS_THREADS块就是为此设计的。
  2. HAL_Delay()依赖SysTick,而FreeRTOS启动后会接管SysTick作为调度定时器,因此不能在调度器未启动时调用HAL_Delay(),推荐在任务中使用FreeRTOS原生的osDelay()或vTaskDelay()。

内容的提问来源于stack exchange,提问作者Gwen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 17:07:45