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

ESP32集成esp-matter后属性更新触发LoadProhibited崩溃求助

ESP32集成esp-matter后触发红外指令发送时LoadProhibited崩溃问题排查

问题概述

基于ESP32和红外发射器实现空调控制器,未集成esp-matter时所有功能正常;集成esp-matter后,通过控制器APP触发空调状态变更以发送红外指令时,系统出现LoadProhibited错误并崩溃,问题已定位至红外指令发送阶段,但根因不明。

实现逻辑说明

  • 自定义IRTransceiver类:负责初始化RMT驱动,实现红外指令发送逻辑
  • 自定义AirConditioner类:存储控制器APP选择的空调状态,state为占位符(代码中未修改),仅在power属性变更时触发sendState发送指令
  • 将IRTransceiver实例传入AirConditioner对象,由后者调用红外发送接口

日志异常表现

初始化时state数据正常

I (934) AirConditioner: State is init here, contents:
I (944) AirConditioner: ==========================
I (944) AirConditioner: ==========================
I (954) AirConditioner: ==========================
I (954) AirConditioner: ========= STATE ==========
I (964) AirConditioner: 131 
I (964) AirConditioner: 6 
I (974) AirConditioner: 4 
I (974) AirConditioner: 114 
I (974) AirConditioner: 0 
I (984) AirConditioner: 0 
I (984) AirConditioner: 148 
I (984) AirConditioner: 56 
I (994) AirConditioner: 0 
I (994) AirConditioner: 0 
I (994) AirConditioner: 0 
I (1004) AirConditioner: 128 
I (1004) AirConditioner: 25 
I (1004) AirConditioner: 67 
I (1014) AirConditioner: 0 
I (1014) AirConditioner: 1 
I (1014) AirConditioner: 0 
I (1024) AirConditioner: 0 
I (1024) AirConditioner: 0 
I (1024) AirConditioner: 0 
I (1034) AirConditioner: 1 
I (1034) AirConditioner: ======= END STATE ========
I (1044) AirConditioner: ==========================
I (1044) AirConditioner: ==========================
I (1054) AirConditioner: ==========================

Matter回调触发sendState时state数据异常

I (13244) AirConditioner: SetPower called
I (13244) AirConditioner: Setting new power value
I (13254) AirConditioner: Sending new state...
I (13254) AirConditioner: passing state for sending.
I (13264) AirConditioner: ==========================
I (13264) AirConditioner: ==========================
I (13274) AirConditioner: ==========================
I (13274) AirConditioner: ========= STATE ==========
I (13274) AirConditioner: 0 
I (13294) AirConditioner: 0 
I (13294) AirConditioner: 0 
I (13294) AirConditioner: 0 
I (13304) AirConditioner: 0 
I (13304) AirConditioner: 0 
I (13304) AirConditioner: 0 
I (13304) AirConditioner: 0 
I (13314) AirConditioner: 0 
I (13314) AirConditioner: 60 
I (13314) AirConditioner: 55 
I (13314) AirConditioner: 64 
I (13324) AirConditioner: 63 
I (13334) AirConditioner: 48 
I (13334) AirConditioner: 188 
I (13334) AirConditioner: 251 
I (13344) AirConditioner: 63 
I (13344) AirConditioner: 16 
I (13344) AirConditioner: 188 
I (13354) AirConditioner: 251 
I (13354) AirConditioner: 63 
I (13354) AirConditioner: ======= END STATE ========
I (13374) AirConditioner: ==========================
I (13374) AirConditioner: ==========================
I (13374) AirConditioner: ==========================

关键代码问题分析

Matter初始化函数的内存生命周期问题

当前matterDriverInit函数参数为传值方式,导致函数内的ac是局部拷贝对象:

esp_err_t matterDriverInit(AirConditioner ac) {
    node::config_t nodeConfig;
    node_t *node = node::create(&nodeConfig, handleAttributeUpdate, handleIdentification);

    on_off_plugin_unit::config_t acConfig;
    acConfig.on_off.on_off = false;

    endpoint_t *endpoint = on_off_plugin_unit::create(node, &acConfig, ENDPOINT_FLAG_NONE, &ac);

//other stuff

}

函数执行完毕后,局部拷贝ac会被销毁,但Matter endpoint的priv_data保存的是该局部对象的指针。后续回调触发时,该指针已指向已释放的内存区域,属于野指针,访问this->state会导致内存数据篡改、LoadProhibited崩溃。

Matter属性更新回调的野指针访问

回调中强转priv_data为AirConditioner*并调用方法,此时指针已失效:

esp_err_t handleAttributeUpdate(attribute::callback_type_t type, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val, void *priv_data) {
    
    esp_err_t err = ESP_OK;
    if(endpoint_id == acEndpointId) {
        AirConditioner* ac = (AirConditioner*)priv_data;
        if (cluster_id == OnOff::Id) {
            if(attribute_id == OnOff::Attributes::OnOff::Id) {
                ac->setPower(val->val.b); // 此时ac为野指针,访问成员会触发异常
            }
        }
    }     
    return err;
}

验证:app_main中调用正常的原因

app_main中直接创建AirConditioner对象,其生命周期覆盖整个程序运行阶段,不存在内存提前释放问题,因此调用setPower和sendState均正常:

extern "C" void app_main() {

    std::string protocol = "KELON168";
    
    IRTransceiver transceiver(IR_TX_PIN,protocol);

    esp_err_t res = transceiver.enableTx();

    AirConditioner ac(25,1,1,false,transceiver);

    ESP_LOGI("DEBUG_IR", "Updating power to true");
    ac.setPower(true);
    ESP_LOGI("DEBUG_IR", "Updating power to false");
    ac.setPower(false);
    ESP_LOGI("DEBUG_IR", "did not crash :o");
    
}

解决方案

  1. 修正Matter初始化函数的参数传递方式
    将参数改为引用传递,确保传入的是原始对象的指针,而非局部拷贝:

    esp_err_t matterDriverInit(AirConditioner &ac) {
        // ... 原有逻辑
        endpoint_t *endpoint = on_off_plugin_unit::create(node, &acConfig, ENDPOINT_FLAG_NONE, &ac);
        // ...
    }
    

    同时确保AirConditioner对象的生命周期覆盖Matter回调的整个触发周期(比如定义为全局变量,或在app_main中创建后保持存活)。

  2. 检查红外发送的线程安全性
    esp-matter回调运行在专属任务上下文,需确认IRTransceiver的sendIRCommand/sendDefaultState方法是否线程安全。若RMT驱动调用存在竞态,需添加互斥锁保护:

    // 在IRTransceiver类中添加互斥锁
    class IRTransceiver {
    private:
        SemaphoreHandle_t tx_mutex;
    public:
        IRTransceiver(...) {
            tx_mutex = xSemaphoreCreateMutex();
        }
    
        void sendIRCommand(...) {
            xSemaphoreTake(tx_mutex, portMAX_DELAY);
            // RMT发送逻辑
            xSemaphoreGive(tx_mutex);
        }
    };
    
  3. 排查内存溢出问题
    若state数组长度定义不足(当前遍历21个元素),需确认数组实际大小是否匹配,避免越界访问导致内存篡改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 14:12:03