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

STM32H中FreeRTOS跨任务操作信号量异常问题排查

问题排查与修复

核心问题点

  1. 高优先级任务未释放信号量
    你代码里的高优先级任务获取信号量后,只执行了休眠操作,完全没调用osSemaphoreRelease释放信号量。按照预期流程,高优先级任务休眠后应该释放信号量,不然信号量要么被永久持有,要么被普通任务重复释放导致计数混乱,直接打乱整个同步逻辑。

  2. 误用HAL_Delay导致任务调度异常
    HAL_Delay在FreeRTOS环境下不会触发任务切换,高优先级任务执行HAL_Delay(10000)时会一直占用CPU,普通和低优先级任务根本没机会运行,自然没法执行释放信号量或闪烁LED的逻辑。

  3. 高优先级抢占导致低优先级任务永远拿不到信号量
    就算普通任务能释放信号量,高优先级任务因为优先级最高,会立刻抢占CPU再次获取信号量,低优先级任务完全没机会抢到,这也是你看不到低优先级任务执行的直接原因。

修复步骤

1. 给高优先级任务补充信号量释放逻辑

在高优先级任务的休眠操作后,添加信号量释放代码,保证“获取-释放”配对:

void StartHighTask(void *argument)
{
  for(;;)
  {
      if ( osSemaphoreAcquire(BinSemHandle, osWaitForever)== osOK){
          char *s1 = " Semaphore Acquired by High Task\n\r";
          HAL_UART_Transmit(&huart3, (uint8_t*)s1, strlen(s1), 1000);
          osDelay(10000); // 替换为osDelay
          // 新增信号量释放操作
          osSemaphoreRelease(BinSemHandle);
          char *s_release = " Semaphore released by High Task\n\r";
          HAL_UART_Transmit(&huart3, (uint8_t*)s_release, strlen(s_release), 1000);
      } else {
          char *s3 = " Waiting for the Semaphore \n\r";
          HAL_UART_Transmit(&huart3, (uint8_t*)s3, strlen(s3), 1000);
      }
      osDelay(1000);
  }
}

2. 替换所有HAL_Delay为osDelay

osDelay会让任务进入阻塞态,调度器可以切换到其他任务执行,保证所有任务都有运行机会:

  • 普通任务里的HAL_Delay(10000)改为osDelay(10000)
  • 低优先级任务里的HAL_Delay(500)改为osDelay(500)

3. 调整逻辑给低优先级任务留执行机会

如果要让低优先级任务能拿到信号量,需要让高优先级任务在释放信号量后主动让出CPU,比如在释放后加个短延迟:

osSemaphoreRelease(BinSemHandle);
osDelay(1); // 让出CPU,让低优先级任务有机会被调度

4. 检查信号量创建参数

确保你创建的是二进制信号量,初始值设为1,创建代码示例:

BinSemHandle = osSemaphoreNew(1, 1, NULL);

如果初始值大于1,信号量会变成计数型,不符合你的预期逻辑。

关键提醒

  • 二进制信号量必须严格遵循“获取-释放”的配对逻辑,少任何一步都会导致整个同步流程崩溃;
  • FreeRTOS中高优先级任务会无条件抢占低优先级任务,要让低优先级任务执行,必须给高优先级任务设置阻塞时机,让调度器有机会切换任务。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 02:44:54