ESP32在ISR执行期间触发LoadProhibited报错的解决方法咨询
问题根源
你出现崩溃的核心原因不是命令耗时太长,中断服务程序(ISR)上下文不允许调用任何非ISR安全的函数,你用到的Serial.println、LVGL相关操作、显示驱动接口、电源管理类函数大部分都不是ISR安全的,这些函数内部会调用FreeRTOS系统调用、持有互斥锁,在中断上下文运行会直接触发异常,也就是你看到的Guru Meditation报错。
原来的示例代码耗电高的原因是loop()里固定执行delay(1000),即使没有中断事件,CPU也会定时唤醒空转,白白消耗电量。
解决方案
不要尝试把业务逻辑放到ISR中执行,仅需修改loop的轮询逻辑,让CPU在没有事件的时候处于休眠状态即可,功耗可以降到你预期的水平,操作步骤如下:
- 保留ISR仅做事件标记的逻辑,标记事件的布尔变量必须加
volatile修饰:
volatile bool axpIrq = false; // 其余全局变量保持不变
- ISR里只做标记,不要添加任何业务逻辑:
attachInterrupt(AXP202_INT, [] { axpIrq = true; }, FALLING);
- 把原来
loop()里的delay(1000)替换为休眠等待逻辑,没有事件的时候CPU直接进入轻量睡眠,几乎不消耗电量,只有中断触发才会唤醒执行逻辑:
void loop() { if (axpIrq) { axpIrq = false; ttgo->power->readIRQ(); // 所有业务逻辑都放在这里,包括Serial打印、调用low_energy()、显示操作等 if (ttgo->power->isPEKShortPressIRQ()) { Serial.println("button pressed"); low_energy(); } // 其余IRQ事件判断逻辑保持不变 ttgo->power->clearIRQ(); } // 替换原来的delay(1000),无事件时核心休眠 esp_light_sleep_start(); }
如果你需要同时处理定时任务,比如每秒更新时间,可以搭配esp_sleep_enable_timer_wakeup设置定时唤醒,比如设置1秒定时唤醒,既可以处理定时任务,无事件时核心也处于休眠状态,功耗比原来空转delay低90%以上:
void loop() { // 你的事件处理逻辑保持不变 // 单位为微秒,1000000对应1秒,可按需调整时长 esp_sleep_enable_timer_wakeup(1000000); esp_light_sleep_start(); }
双核方案补充说明
ESP32确实搭载两个核心,但不建议把中断处理逻辑绑定到第二核心运行,上述中断标记+休眠等待的方案已经可以实现最低功耗,完全满足智能手表的使用需求,实现逻辑也更简单,不需要额外处理多核同步问题。
内容的提问来源于stack exchange,提问作者Παναγιώτης Θ
相关产品推荐
相关产品推荐

