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

ESP32-S2发送大WebSocket数据时随机崩溃问题求助

ESP32-S2发送大WebSocket数据时随机LoadProhibited崩溃原因分析

从你提供的崩溃日志和代码来看,问题的核心原因是中断上下文与异步WebSocket库的线程安全冲突,具体分析如下:

关键崩溃信息解析

  • 崩溃类型LoadProhibited表示CPU尝试访问了非法的内存地址(日志中EXCVADDR: 0xa941d542,该地址不属于ESP32-S2的有效RAM/Flash范围)。
  • 回溯栈显示崩溃发生在AsyncWebSocket::_cleanBuffers()方法中,调用链起点是Ticker定时器的回调函数captureMeasurements(),最终触发ws.binaryAll()。

根本原因

你使用Ticker周期性触发WebSocket数据发送,但Ticker的回调是在中断上下文中执行的,而ESP Async WebServer库的AsyncWebSocket组件并非中断安全:

  1. 当中断触发ws.binaryAll()时,AsyncWebSocket内部会复制数据到发送缓冲区,并在后台任务中处理发送逻辑。
  2. 同时,库的后台线程可能正在执行_cleanBuffers()清理旧缓冲区,此时中断上下文的操作可能篡改了库内部的内存指针或状态,导致后续访问非法内存地址,引发崩溃。
  3. 你的buffer是全局静态数组,本身内存无问题,但异步库的内部状态在中断干扰下出现异常。

验证与解决方法

核心修复:避免在中断上下文调用异步WebSocket操作

将Ticker回调改为仅设置一个触发标志,在主循环loop()中检查标志并执行发送操作,确保WebSocket操作在主任务上下文执行:

bool shouldSendMeasurements = false;

// Ticker回调仅设置标志
void captureMeasurements() {
  shouldSendMeasurements = true;
}

void sendMeasurements_Bin(){
  Serial.print("sending----");
  ws.binaryAll((uint8_t*)buffer, sizeof(buffer));
  Serial.println("sent");
}

void loop() {
  // 检查发送标志并执行
  if (shouldSendMeasurements) {
    sendMeasurements_Bin();
    shouldSendMeasurements = false;
  }
  
  // 其他原有loop逻辑
}

额外优化建议

  • 检查AsyncWebSocket的缓冲区配置:可以通过ws.setMaxMessageSize()和ws.setMaxFragmentSize()调整最大消息/分片大小,确保能容纳你的2200字节数据(默认配置通常足够,但可以显式设置)。
  • 避免高频连续发送:如果发送周期过短,可能导致库内部缓冲区积压,可适当调整Ticker的触发间隔。

内容的提问来源于stack exchange,提问作者Vojta Degeš

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 14:56:01