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

ESP32 Task Watchdog触发报错:loopTask未及时重置看门狗求助

Task Watchdog触发问题排查

报错信息

task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (25603) task_wdt: - loopTask (CPU 1)
E (25603) task_wdt: Tasks currently running:
E (25603) task_wdt: CPU 0: Task1
E (25603) task_wdt: CPU 1: loopTask
E (25603) task_wdt: Aborting.

abort() was called at PC 0x400dfab9 on core 0

Backtrace: 0x400836ad:0x3ffbec3c |<-CORRUPTED

ELF file SHA256: fde7bf06d933983a

Rebooting...

相关代码

#include <Arduino.h>
#include <esp_task_wdt.h>

#include <RfidManager.h>
#include <DisplayManager.h>
#include <EspNowSender.h>
#include <BLESlave.h>

// const uint8_t receiverAddress[] = {0x88, 0x13, 0xBF, 0x24, 0xBD, 0x98};

RfidManager rfidManager;
DisplayManager displayManager;
EspNowSender espSender;
BLESlave bleSlave;

WiFiMulti wifiMulti;

uint8_t broadcastAddress[] = {0x88, 0x13, 0xBF, 0x24, 0xDB, 0x98};

typedef struct struct_pilot {
    int id;
    int x;
    int y;
} struct_pilot;

struct_pilot myPilot;
esp_now_peer_info_t peerInfo;

void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("\r\nLast Packet Send Status:\t");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}

void sendDataTask(void *parameter) {
  for (;;) {
    myPilot.id = 2;
    if(digitalRead(15) == 0){
        myPilot.x = 0;
    }
    if(digitalRead(4) == 0){
        myPilot.x = 0;
    }
    if(digitalRead(13) == 0){
        myPilot.x = 0;
    }
    if(digitalRead(12) == 0){
        myPilot.x = 1;
    }
    if(digitalRead(14) == 0){
        myPilot.x = 1;
    }
    myPilot.y = random(0,50);

    esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myPilot, sizeof(myPilot));
    if (result == ESP_OK) {
      Serial.println("Sent with success");
    } else {
      Serial.println("Error sending the data");
    }

    vTaskDelay(pdMS_TO_TICKS(2000)); // Delay for 2 seconds
  }
}
void Task1(void *pvParameters);// This rfid task
void Task2(void *pvParameters);// This display task


void setup() {
    Serial.begin(9600);
    wifiMulti.addAP("Nang Luong Xanh", "nangluongxanh360");
    Serial.println("Connecting to WiFi...");
    while (wifiMulti.run() != WL_CONNECTED) {
        Serial.print(".");
        delay(100);
    }
    Serial.println("\nConnected to WiFi");

    WiFi.mode(WIFI_STA);

    // Initialize ESP-NOW
    if (esp_now_init() != ESP_OK) {
        Serial.println("Error initializing ESP-NOW");
        return;
    }

    esp_now_register_send_cb(OnDataSent);

    memcpy(peerInfo.peer_addr, broadcastAddress, 6);
    peerInfo.channel = 0;
    peerInfo.encrypt = false;

    if (esp_now_add_peer(&peerInfo) != ESP_OK) {
        Serial.println("Failed to add peer");
        return;
    }


    esp_task_wdt_init(15, true); // 将超时时间设置为15秒
    esp_task_wdt_add(NULL); // 将当前任务(main task)添加到WDT

    xTaskCreatePinnedToCore(
      Task1, "Task1", 2048, NULL, 2, NULL, 0); // RFID任务
    xTaskCreatePinnedToCore(
      Task2, "Task2", 2048, NULL, 1, NULL, 1);; // 显示任务
    xTaskCreate(sendDataTask, "Send Data Task", 2048, NULL, 1, NULL);
}

void loop() {
  
}


void Task1(void *pvParameters)  // RFID任务
{
    rfidManager.RfidManagerSetup();
    esp_task_wdt_add(NULL); // 将Task1添加到WDT
    for(;;)
    {
        rfidManager.RfidManagerloop();
        esp_task_wdt_reset(); // 重置看门狗
        vTaskDelay(100 / portTICK_PERIOD_MS); // 缩短延迟时间
    }
}


void Task2(void *pvParameters)  // 显示任务
{
    displayManager.DisplayManagerSetup();
    esp_task_wdt_add(NULL); // 将Task2添加到WDT

    for(;;)
    {
        displayManager.DisplayManagerloop();

        
        esp_task_wdt_reset(); // 重置看门狗
        vTaskDelay(500 / portTICK_PERIOD_MS); // 缩短延迟时间
    }
}

问题分析与解决方法

核心原因

报错明确指向CPU1上的loopTask未及时重置看门狗。ESP32 Arduino框架默认会将运行loop()函数的loopTask加入看门狗监控,但你的loop()函数为空,且未添加看门狗重置逻辑,导致系统判定该任务超时。

另外需要排查同CPU(CPU1)上的Task2是否存在长时间阻塞代码:Task2与loopTask优先级相同(均为1),若DisplayManagerloop()包含无延迟死循环、未超时的阻塞操作,会抢占CPU时间,导致loopTask无法执行看门狗重置。

解决方案

方案1:给loop()添加看门狗重置逻辑

修改空的loop()函数,定期重置看门狗并释放CPU:

void loop() {
    esp_task_wdt_reset();
    vTaskDelay(pdMS_TO_TICKS(100)); // 给任务调度器留出切换时间
}

方案2:移除loopTask的看门狗监控

在setup()函数末尾添加代码,将loopTask从看门狗监控中移除:

// 获取loopTask句柄并取消看门狗监控
TaskHandle_t loopTaskHandle = xTaskGetHandle("loopTask");
if (loopTaskHandle != NULL) {
    esp_task_wdt_delete(loopTaskHandle);
}

方案3:检查自定义任务的阻塞逻辑

排查RfidManagerloop()和DisplayManagerloop()的实现,确保不存在长时间阻塞操作:

  • 替换无超时的while循环为非阻塞逻辑
  • 确保所有耗时操作都设置合理超时时间
  • 保留vTaskDelay或taskYIELD()调用,让任务能周期性释放CPU

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 11:45:53