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

ESP8266连接AWS MQTT服务器崩溃问题排查求助

问题

在Arduino IDE中开发ESP8266项目,使用PubSubClient库连接AWS MQTT服务器。执行pubsubClient.connect(config.mqtt.id, config.mqtt.username, config.mqtt.password)后设备崩溃,崩溃日志如下:

:ref 1

_iobuf_in:       0x3fff5ebc
_iobuf_out:      0x3fff3f94
_iobuf_in_size:  16709
_iobuf_out_size: 597
--------------- CUT HERE FOR EXCEPTION DECODER ---------------
Exception (28):
epc1=0x4021f88f epc2=0x00000000 epc3=0x00000000 excvaddr=0x00003a98 depc=0x00000000

>>>stack>>>

ctx: cont
sp: 3fff0bc0 end: 3fff0fd0 offset: 0150
3fff0d10:  00000000 2c9f0300 4000050c 3fffc278  
3fff0d20:  00000000 00000000 00000022 40234a30  
...

已设置最高日志级别开启调试,但调试串口未捕获到额外信息。Exception decoder解码结果如下:

Exception 9: LoadStoreAlignmentCause: Load or store to an unaligned address
PC: 0x4024232d: br_x509_minimal_run at src/x509\x509_minimal.c:1203
EXCVADDR: 0x0000252d

Decoding stack results
0x4023cdb4: br_ssl_hs_client_run at src/ssl\ssl_hs_client.c:1877
0x4023af50: jump_handshake at src\inner.h:2211
0x4023b33d: br_ssl_engine_sendrec_ack at src/ssl\ssl_engine.c:1168
0x4021552e:  is in BearSSL::WiFiClientSecureCtx::_run_until(unsigned int, bool) (C:\Users\g\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266WiFi\src\WiFiClientSecureBearSSL.cpp:586).
0x4023af50: jump_handshake at src\inner.h:2211
0x4023c0a8: br_ssl_hs_client_run at src/ssl\ssl_hs_client.c:960
0x40215588: BearSSL::WiFiClientSecureCtx::_wait_for_handshake() at C:\Users\g\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266WiFi\src\WiFiClientSecureBearSSL.cpp:609
0x4021585b:  is in BearSSL::WiFiClientSecureCtx::_connectSSL(char const*) (C:\Users\g\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266WiFi\src\WiFiClientSecureBearSSL.cpp:1194).
0x40101218: umm_malloc(size_t) at C:\Users\g\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\umm_malloc\umm_malloc.cpp:912
0x402354e8: ip4_output_if_opt at core/ipv4\ip4.c:1572
0x4022cd75: mem_malloc at core\mem.c:210
0x4023550e: ip4_output_if at core/ipv4\ip4.c:1549
0x40236467: ip_chksum_pseudo at core\inet_chksum.c:392
0x4021d70c: __esp_suspend() at C:\Users\g\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_features.h:64
0x4021d85d:  is in __esp_delay(unsigned long) (C:\Users\g\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp:161).
0x4021d8d2:  is in esp_try_delay(unsigned int, unsigned int, unsigned int) (C:\Users\g\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp:182).
0x4021d8d2:  is in esp_try_delay(unsigned int, unsigned int, unsigned int) (C:\Users\g\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp:182).
0x40214306:  is in WiFiClient::connect(IPAddress, unsigned short) (C:\Users\g\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266/coredecls.h:69).
0x402354b2: ip4_output_if_src at core/ipv4\ip4.c:1589
0x4021593b:  is in BearSSL::WiFiClientSecureCtx::connect(char const*, unsigned short) (C:\Users\g\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266WiFi\src\WiFiClientSecureBearSSL.cpp:228).
0x40218a84:  is in PubSubClient::connect(char const*, char const*, char const*, char const*, unsigned char, bool, char const*, bool) (c:\ArduinoTest\libraries\PubSubClient\src\PubSubClient.cpp:196).
0x40231bd8: udp_sendto_if at core\udp.c:692
0x4021d7ba: __yield() at C:\Users\g\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_features.h:64
0x40218c6c:  is in PubSubClient::connect(char const*, char const*, char const*) (c:\ArduinoTest\libraries\PubSubClient\src\PubSubClient.cpp:170).
0x40206ef1:  is in sendMQTT(unsigned long, String, String) (C:\ArduinoTest\vtsistema/vtsistema.ino:172).
0x4021c375:  is in String::copy(char const*, unsigned int) (C:\Users\g\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\WString.cpp:274).
0x402084ff: loop() at C:\ArduinoTest\vtsistema\vtsistema.ino:599
0x402177c0: fs::FS::_defaultTimeCB() at C:\Users\g\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\FS.h:260
0x401011d6: umm_free(void*) at C:\Users\g\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\umm_malloc\umm_malloc.cpp:688
0x402177c0: fs::FS::_defaultTimeCB() at C:\Users\g\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\FS.h:260
0x4021d944: loop_wrapper() at C:\Users\g\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp:258

排查步骤

从解码日志看,崩溃是Exception 9: LoadStoreAlignmentCause(加载/存储未对齐地址),发生在BearSSL的x509证书解析阶段,按以下步骤排查:

  1. 检查证书/密钥的格式与内存对齐

    • AWS MQTT连接需要根CA证书、设备证书和私钥,确保这些文件内容无格式错误,比如多余空格、换行,或复制时遗漏-----BEGIN CERTIFICATE-----/-----END CERTIFICATE-----头尾部。
    • 避免直接将证书内容作为字符串常量硬编码,尤其是字符串长度非4的倍数时,易引发内存未对齐。建议用PROGMEM存储证书,或把证书文件放入SPIFFS读取,保证内存地址对齐。
  2. 升级ESP8266核心库版本
    当前使用的ESP8266核心版本为3.1.2,该版本的BearSSL实现可能存在未对齐内存访问的bug。升级到最新稳定版(如3.1.3及以上),新版本通常会修复这类底层内存问题。

  3. 检查PubSubClient与WiFiClientSecure的配置

    • 确保PubSubClient使用WiFiClientSecure实例而非普通WiFiClient,AWS MQTT要求SSL/TLS连接。
    • 手动设置WiFiClientSecure的CA证书,不要依赖自动加载:
      WiFiClientSecure espClient;
      void setup() {
        // 加载根CA证书
        espClient.setCACert(rootCA);
        PubSubClient client(espClient);
        client.setServer(MQTT_SERVER, 8883);
      }
      
    • 验证MQTT连接参数:clientId、username、password是否正确,AWS IoT的username通常为空,password是签名后的令牌,不要传入错误格式的字符串。
  4. 排查内存分配问题
    日志中出现umm_malloc/umm_free调用,说明可能存在内存碎片化或分配失败:

    • 减少全局变量使用,尤其是大字符串(如证书)。
    • 连接MQTT前,调用ESP.getFreeHeap()打印剩余内存,若剩余内存不足5KB,可能导致内存分配错误,进而引发未对齐访问。
    • 避免频繁创建String对象,改用char[]数组,减少内存碎片。
  5. 测试最小化连接代码
    编写仅包含WiFi连接、MQTT连接的最小测试程序,排除其他代码干扰:

    #include <ESP8266WiFi.h>
    #include <PubSubClient.h>
    
    const char* ssid = "YOUR_SSID";
    const char* password = "YOUR_WIFI_PASS";
    const char* mqttServer = "AWS_MQTT_ENDPOINT";
    const int mqttPort = 8883;
    const char* mqttClientId = "YOUR_CLIENT_ID";
    const char* mqttUsername = ""; // AWS IoT通常留空
    const char* mqttPassword = "YOUR_SIGNED_TOKEN";
    const char* rootCA = "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----";
    
    WiFiClientSecure espClient;
    PubSubClient client(espClient);
    
    void setup() {
      Serial.begin(115200);
      WiFi.begin(ssid, password);
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
      Serial.println("WiFi connected");
    
      espClient.setCACert(rootCA);
      client.setServer(mqttServer, mqttPort);
    
      if (client.connect(mqttClientId, mqttUsername, mqttPassword)) {
        Serial.println("MQTT connected");
      } else {
        Serial.print("MQTT connect failed, rc=");
        Serial.println(client.state());
      }
    }
    
    void loop() {
      client.loop();
    }
    

    如果这个最小程序能正常连接,说明问题出在原项目的其他代码中,逐步添加原代码模块排查。

  6. 检查编译器优化选项
    Arduino IDE中,ESP8266的编译器优化等级如果设置过高(如-O2),可能导致内存对齐问题。尝试将优化等级改为“-Os”(默认)或“-O1”,可在IDE的编译选项菜单调整,或修改ESP8266核心的platform.txt文件。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 00:19:49