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

ESP32双核任务并行异常:vTaskCreatePinnedToCore未达预期

问题分析与解答

本质原因:任务逻辑的GPIO竞争 + 无阻塞死循环的调度特性

你看到的LED闪烁并非任务串行执行,而是两个并行任务在高频修改相同GPIO引脚,同时无阻塞死循环导致调度异常,具体分解如下:

1. 任务逻辑的GPIO竞争问题

你的两个任务同时操作相同的两个GPIO引脚:

  • sensorsTask 循环将引脚2置1、引脚4置0
  • storageTask 循环将引脚4置1、引脚2置0

当两个任务在双核上并行运行时,两个核心会同时对这两个引脚进行写操作:

  • 引脚2会被核心0快速置1,紧接着被核心1置0,如此反复
  • 引脚4会被核心1快速置1,紧接着被核心0置0,如此反复
    这种高频电平切换远超过人眼的分辨能力,最终呈现为LED闪烁,而非你预期的稳定点亮。

2. 无阻塞死循环对调度的影响

你的任务是没有任何阻塞点的死循环,这会导致:

  • 每个核心的FreeRTOS调度器无法切换到其他系统任务(比如ESP-IDF的后台服务、定时器任务等),长期运行会触发看门狗复位
  • 任务会持续占用核心CPU时间,没有任何机会让其他任务(包括系统任务)执行

3. 添加vTaskDelay(1)后正常的原因

加入vTaskDelay(1)后,任务会主动放弃CPU控制权,进入阻塞状态:

  • 调度器可以正常调度其他系统任务,保证系统稳定运行
  • 更关键的是,任务的GPIO操作频率被降低到每1ms执行一次,此时引脚电平的切换速度变慢,人眼可以看到稳定的电平状态;同时,在延迟期间,另一个任务设置的电平会保持足够长的时间,不会被立刻覆盖。

正确的任务设计方式

如果要让两个LED稳定点亮,应该让每个任务只负责自己的LED,避免GPIO竞争:

void storageTask(void *arg){
    for(;;){
        gpio_set_level(4, 1); // 仅控制引脚4的LED
        vTaskDelay(pdMS_TO_TICKS(10)); // 使用标准延迟宏适配不同时钟
    }
}

void sensorsTask(void *arg){
    for(;;){
        gpio_set_level(2, 1); // 仅控制引脚2的LED
        vTaskDelay(pdMS_TO_TICKS(10));
    }
}

这种情况下,即使去掉延迟,LED也会稳定点亮——因为任务只是重复设置相同的电平,不会互相干扰;而保留延迟则是为了给系统任务留出执行时间,避免系统异常。

内容的提问来源于stack exchange,提问作者Muhammad Hammad Umer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 10:08:14