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
相关产品推荐
相关产品推荐

