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

ESP32抽离PubSubClient连接AWS IoT Core工具函数后崩溃排查

问题

我需要实现一个基于PubSubClient和WiFiClientSecure连接AWS MQTT代理的函数,并将其定义在独立文件中以实现复用,但ESP32每次运行代码时都会崩溃。原教程中的函数在主文件定义时运行正常,但抽离到iot_utils.cpp后出现崩溃。

原教程工作代码(主文件中)

WiFiClientSecure net = WiFiClientSecure();
PubSubClient client(net);
 
void connectAWS()
{
    WiFi.mode(WIFI_STA);
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
    Serial.println("Connecting to Wi-Fi");
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    // Configure WiFiClientSecure to use the AWS IoT device credentials
    net.setCACert(AWS_CERT_CA);
    net.setCertificate(AWS_CERT_CRT);
    net.setPrivateKey(AWS_CERT_PRIVATE);
    // Connect to the MQTT broker on the AWS endpoint we defined earlier
    client.setServer(AWS_IOT_ENDPOINT, 8883);
    // Create a message handler
    client.setCallback(messageHandler);
    Serial.println("Connecting to AWS IOT");
    while (!client.connect(THINGNAME)) {
        Serial.print(".");
        delay(100);
    }
    if (!client.connected()) {
        Serial.println("AWS IoT Timeout!");
        return;
    }
    // Subscribe to a topic
    client.subscribe(AWS_IOT_SUBSCRIBE_TOPIC);
    Serial.println("AWS IoT Connected!");
}

抽离后的代码

iot_utils.cpp中的函数:

void connectAWS(WiFiClientSecure& net, PubSubClient& client, const char* topic) {
   // 此处为原函数逻辑代码
}

主文件调用:

WiFiClientSecure net = WiFiClientSecure();
PubSubClient client(net);

void setup() {
   connectAWS(net, client, "esp32/pub");
}

崩溃信息

ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:1184
load:0x40078000,len:13132
load:0x40080400,len:3036
entry 0x400805e4
Connecting to Wi-Fi
.Connecting to AWS IOT
Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.

Core  1 register dump:
PC      : 0x4015b50c  PS      : 0x00060f30  A0      : 0x800d3bba  A1      : 0x3ffb26f0  
A2      : 0x3ffc2c74  A3      : 0x3f4050f9  A4      : 0x00000015  A5      : 0x0000ff00  
A6      : 0x00ff0000  A7      : 0xff000000  A8      : 0x800d78a6  A9      : 0x3ffb2700  
A10     : 0x000003e8  A11     : 0x3f4050f9  A12     : 0x00000002  A13     : 0x0000ff00  
A14     : 0x00ff0000  A15     : 0xff000000  SAR     : 0x00000017  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x000003e8  LBEG    : 0x40089729  LEND    : 0x40089739  LCOUNT  : 0xfffffffa  


Backtrace:0x4015b509:0x3ffb26f00x400d3bb7:0x3ffb2710 0x400d3de2:0x3ffb2750 0x400d3915:0x3ffb2780 0x400d3819:0x3ffb27a0 0x400d877e:0x3ffb2820 

解决方案

崩溃核心原因是:抽离后的connectAWS函数依赖原主文件中的全局常量(如证书、端点地址)和回调函数,但独立文件iot_utils.cpp无法访问这些未声明的外部符号,导致非法内存访问(LoadProhibited错误通常对应访问无效内存地址)。

修正步骤

  1. 创建头文件iot_utils.h,规范函数声明并引入必要依赖:
#ifndef IOT_UTILS_H
#define IOT_UTILS_H

#include <WiFiClientSecure.h>
#include <PubSubClient.h>

void connectAWS(WiFiClientSecure& net, 
                PubSubClient& client, 
                const char* thingName, 
                const char* awsEndpoint,
                const char* caCert,
                const char* clientCert,
                const char* privateKey,
                const char* subscribeTopic,
                const char* wifiSsid,
                const char* wifiPassword,
                MQTT_CALLBACK_SIGNATURE);

#endif // IOT_UTILS_H
  1. 修改iot_utils.cpp,完全使用传入参数替代全局依赖:
#include "iot_utils.h"
#include <WiFi.h>
#include <HardwareSerial.h>

void connectAWS(WiFiClientSecure& net, 
                PubSubClient& client, 
                const char* thingName, 
                const char* awsEndpoint,
                const char* caCert,
                const char* clientCert,
                const char* privateKey,
                const char* subscribeTopic,
                const char* wifiSsid,
                const char* wifiPassword,
                MQTT_CALLBACK_SIGNATURE) {
    
    WiFi.mode(WIFI_STA);
    WiFi.begin(wifiSsid, wifiPassword);
    Serial.println("Connecting to Wi-Fi");
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }

    // 使用传入的证书配置TLS
    net.setCACert(caCert);
    net.setCertificate(clientCert);
    net.setPrivateKey(privateKey);

    client.setServer(awsEndpoint, 8883);
    client.setCallback(callback); // 绑定传入的回调函数

    Serial.println("\nConnecting to AWS IOT");
    while (!client.connect(thingName)) {
        Serial.print(".");
        delay(100);
    }

    if (!client.connected()) {
        Serial.println("\nAWS IoT Timeout!");
        return;
    }

    client.subscribe(subscribeTopic);
    Serial.println("\nAWS IoT Connected!");
}
  1. 主文件中调用时传递所有必要参数:
#include "iot_utils.h"

// 定义你的设备常量和回调函数
const char* WIFI_SSID = "your_wifi_ssid";
const char* WIFI_PASSWORD = "your_wifi_password";
const char* THINGNAME = "your_thing_name";
const char* AWS_IOT_ENDPOINT = "your_aws_endpoint";
const char AWS_CERT_CA[] = "..."; // 你的CA证书内容
const char AWS_CERT_CRT[] = "..."; // 客户端证书内容
const char AWS_CERT_PRIVATE[] = "..."; // 私钥内容
const char* SUBSCRIBE_TOPIC = "esp32/pub";

// MQTT消息回调函数
void messageHandler(char* topic, byte* payload, unsigned int length) {
    // 处理收到的消息逻辑
    Serial.print("Received message on topic: ");
    Serial.println(topic);
}

WiFiClientSecure net;
PubSubClient client(net);

void setup() {
    Serial.begin(115200);
    connectAWS(net, 
               client, 
               THINGNAME, 
               AWS_IOT_ENDPOINT,
               AWS_CERT_CA,
               AWS_CERT_CRT,
               AWS_CERT_PRIVATE,
               SUBSCRIBE_TOPIC,
               WIFI_SSID,
               WIFI_PASSWORD,
               messageHandler);
}

void loop() {
    if (!client.connected()) {
        // 可选:添加重连逻辑
    }
    client.loop();
}

额外注意事项

  • 证书需以const char[]形式定义,避免使用const char*,确保多行字符串能被正确存储。
  • 主文件中的WiFiClientSecure和PubSubClient对象需定义为全局变量,保证生命周期覆盖整个程序运行过程。
  • 如果需要进一步封装,可以把相关参数封装成结构体,减少函数参数数量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 14:05:40