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

ESP32 Guru Meditation Error(CPU1中断看门狗超时)修复求助

问题分析与修复方案

核心原因

你的ESP32触发Interrupt wdt timeout的直接原因是:

  • ISR(中断服务程序)执行时间过长,超出了ESP32中断看门狗的默认阈值(通常在几毫秒级别)
  • 临界区包含了大量非必要逻辑(16个outlet的循环判断),进一步拉长了中断执行时间
  • ISR中调用Serial打印是雪上加霜:串行输出是阻塞操作,会大幅增加ISR执行时长

修复步骤

1. 压缩临界区到最小范围

临界区仅用于保护共享变量的原子操作,只保留时间计数器的更新与重置逻辑:

void IRAM_ATTR on_min(){
  portENTER_CRITICAL_ISR(&timerMux);
  mins_counter++;
  if (mins_counter == 10){
    tens_counter++;
    on_or_off[8] = !on_or_off[8]; // 简化toggle逻辑,替代重复判断
    mins_counter = 0;
  }
  if (tens_counter == 6){
    hour_counter++;
    tens_counter = 0;
  }
  if (hour_counter == 24){
    day_counter++;
    hour_counter = 0;
  }
  if (day_counter == 7){
    mins_counter = 0;
    tens_counter = 0;
    hour_counter = 0;
    day_counter = 0;
  }
  portEXIT_CRITICAL_ISR(&timerMux);
  
  // 通知任务处理后续逻辑,触发任务切换(如果需要)
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  xSemaphoreGiveFromISR(timerSemaphore, &xHigherPriorityTaskWoken);
  portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

2. 将业务逻辑移到FreeRTOS任务中

把原来ISR里的outlet模式判断、状态更新、Serial打印全部放到独立任务里,由ISR通过信号量触发执行:

void timerTask(void *parameter){
  for(;;){
    // 等待ISR的信号量
    if(xSemaphoreTake(timerSemaphore, portMAX_DELAY) == pdTRUE){
      // 处理所有outlet的模式逻辑
      for (int i = 0; i < 16; i++) {
        int mode = outlet_mode[i];
        switch(mode){
          case 0:
            break;

          case 1: // 时间循环模式
            if (cyc_cnts[i] == 0){
              cyc_cnts[i] = duration[i] - 1;
              on_or_off[i] = !on_or_off[i];
            } else {
              cyc_cnts[i]--;
            }
            break;

          case 2: // 每日重复模式
            int current_time = tens_counter + 6 * hour_counter;
            if (current_time < on_time[i]){
              on_or_off[i] = 0;
            } else if (current_time < (on_time[i] + duration[i])){
              on_or_off[i] = 1;
            } else {
              on_or_off[i] = 0;
            }
            break;

          case 3: // 永久状态模式
            break;
        }
      }

      // 打印当前时间(仅在任务中执行,避免阻塞ISR)
      Serial.print("Current Time: ");
      Serial.print(hour_counter);
      Serial.print(":");
      Serial.print(tens_counter);
      Serial.print(mins_counter);
      Serial.println();
    }
  }
}

3. 初始化任务

在setup()中创建处理任务,分配足够的栈空间:

void setup(){
  // 其他初始化代码...
  timerSemaphore = xSemaphoreCreateBinary();
  xTaskCreate(timerTask, "TimerTask", 2048, NULL, 1, NULL);
  // 定时器初始化代码...
}

额外优化建议

  • 对于单个变量的递增/修改,优先使用portATOMIC_INCREMENT、portATOMIC_DECREMENT等原子操作函数,替代临界区,进一步减少执行时间
  • 确保所有共享变量(如mins_counter、on_or_off)的访问都被正确保护,避免多任务/中断冲突
  • 严格禁止在ISR中执行任何阻塞或耗时操作,比如Serial打印、复杂计算

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 03:17:04