硬汉嵌入式论坛

 找回密码
 立即注册
查看: 330|回复: 8
收起左侧

[LVGL] LVGL求助,ESP32S3开发LVGL应用,提过MQTT收信来显示/隐藏控件,运行一段时间后必定卡住

[复制链接]

1

主题

4

回帖

7

积分

新手上路

积分
7
发表于 2025-11-25 10:28:05 | 显示全部楼层 |阅读模式
如题,不知有无大佬可以帮忙看看什么问题,实在是找不到原因,内存监控看下来空闲还非常多或者需要确认其他部分我再添上来:
MQTT回调部分:


[C] 纯文本查看 复制代码
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
    ESP_LOGD(MQTT_TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id);
    esp_mqtt_event_handle_t event = event_data;
    esp_mqtt_client_handle_t client = event->client;
    switch ((esp_mqtt_event_id_t)event_id)
    {
    case MQTT_EVENT_CONNECTED:
        ESP_LOGI(MQTT_TAG, "MQTT_EVENT_CONNECTED");
        esp_mqtt_client_subscribe(client, "E/ERR", 0);
        esp_mqtt_client_subscribe(client, "E/DEL", 0);
break;
    case MQTT_EVENT_DISCONNECTED:
        ESP_LOGI(MQTT_TAG, "MQTT_EVENT_DISCONNECTED");
        break;
    case MQTT_EVENT_SUBSCRIBED:
        ESP_LOGI(MQTT_TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_UNSUBSCRIBED:
        ESP_LOGI(MQTT_TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_PUBLISHED:
        ESP_LOGI(MQTT_TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_DATA:
        ESP_LOGI(MQTT_TAG, "MQTT_EVENT_DATA");
        char topic[128] = {0};
        int topic_len = event->topic_len;
        if (topic_len > sizeof(topic) - 1)
        {
            topic_len = sizeof(topic) - 1;
        }
        strncpy(topic, event->topic, topic_len);
        topic[topic_len] = '\0';

        ESP_LOGI(MQTT_TAG, "Received from topic: %s", topic);

        if (strcmp(topic, "E/ERR") == 0)
        {
            cJSON *msg_recv = cJSON_Parse(event->data);
            if (msg_recv == NULL)
            {
                ESP_LOGE("MQTT_Json", "Json error");
                return;
            }

            const char *id = cJSON_GetStringValue(cJSON_GetObjectItem(msg_recv, "clientID"));

            if (strcmp(id, WATCH_ID) != 0)
            {
                ESP_LOGI("MQTT_Filter", "ID mismatch (expected:%s, actual:%s)", WATCH_ID, id);
                cJSON_Delete(msg_recv); 
                return; 
            }

            int msg_id_val = cJSON_GetNumberValue(cJSON_GetObjectItem(msg_recv, "msg_id"));
            const char *deviceno_val = cJSON_GetStringValue(cJSON_GetObjectItem(msg_recv, "deviceno"));
            const char *content_val = cJSON_GetStringValue(cJSON_GetObjectItem(msg_recv, "content"));
            const char *color_val = cJSON_GetStringValue(cJSON_GetObjectItem(msg_recv, "color"));
            int priority_val = cJSON_GetNumberValue(cJSON_GetObjectItem(msg_recv, "priority"));

panel_add_obj_args_t *args = (panel_add_obj_args_t *)calloc(1, sizeof(*args));
            if (!args)
            {
return;
            }
            args->msg_id = msg_id_val;
            args->priority = priority_val;

if (deviceno_val)
            {
                args->deviceno = strdup(deviceno_val);
            }
            else
            {
                args->deviceno = strdup("");
            }
            if (content_val)
            {
                args->content = strdup(content_val);
            }
            else
            {
                args->content = strdup("");
            }
            if (color_val)
            {
                args->color = strdup(color_val);
            }
            else
            {
                args->color = strdup("");
            }
            if (!args->deviceno || !args->content || !args->color)
            {
if (args->deviceno)
                    free(args->deviceno);
                if (args->content)
                    free(args->content);
                if (args->color)
                    free(args->color);
                free(args);
                return;
            }

            cJSON_Delete(msg_recv);

            if (lv_async_call(panel_add_obj_async_cb, args) != LV_RES_OK)
            {
free(args->deviceno);
                free(args->content);
                free(args->color);
                free(args);
            }
}
        else if (strcmp(topic, "E/DEL") == 0)
        {
            cJSON *msg_recv = cJSON_Parse(event->data);
            if (msg_recv == NULL)
            {
                ESP_LOGE("MQTT_Json", "Json error");
                return;
            }
            int msg_id_val = cJSON_GetNumberValue(cJSON_GetObjectItem(msg_recv, "msg_id"));
            cJSON_Delete(msg_recv);

            panel_del_args_t *args = (panel_del_args_t *)malloc(sizeof(panel_del_args_t));
            if (!args)
                return;
            args->msg_id = msg_id_val;

            if (lv_async_call(panel_del_obj_async_cb, args) != LV_RES_OK)
            {
                free(args);
            }
        }
        break;
    case MQTT_EVENT_ERROR:
        ESP_LOGI(MQTT_TAG, "MQTT_EVENT_ERROR");
        if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT)
        {
            log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
            log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
            log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno);
            ESP_LOGI(MQTT_TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
        }
        break;
    default:
        ESP_LOGI(MQTT_TAG, "Other event id:%d", event->event_id);
        break;
    }
}

异步回调:
[C] 纯文本查看 复制代码
static void panel_add_obj_async_cb(void *user_data)
{
    panel_add_obj_args_t *args = (panel_add_obj_args_t *)user_data;

    panel_add_obj(args->msg_id,
                  args->deviceno,
                  args->content,
                  args->color,
                  args->priority);

    if (args->deviceno)
        free(args->deviceno);
    if (args->content)
        free(args->content);
    if (args->color)
        free(args->color);
    free(args);
}

static void panel_del_obj_async_cb(void *user_data)
{
    if (!user_data)
        return;
    panel_del_args_t *args = (panel_del_args_t *)user_data;
    panel_del_obj(args->msg_id);
    free(args);
}

实际操作LVGL部分:
[C] 纯文本查看 复制代码
void panel_add_obj(int msg_id, const char *deviceno, const char *content, const char *color, int priority)
{
    Button_Data *Data = new Button_Data();
    Data->msg_id = msg_id;
    strlcpy(Data->color, color, sizeof(Data->color));
    Data->priority = priority;
    strlcpy(Data->deviceno, deviceno, sizeof(Data->deviceno));
    strlcpy(Data->content, content, sizeof(Data->content));
    char buffer[256];
    snprintf(buffer, sizeof(buffer), "%s\n%s", deviceno, content);
    if (strcmp(color, "red") == 0)
    {
        lv_label_set_text(lv_obj_get_child(msg_objR, 0), buffer);
        lv_obj_set_user_data(msg_objR, Data);
        if (lv_obj_has_flag(msg_objR, LV_OBJ_FLAG_HIDDEN))
        {
            lv_obj_clear_flag(msg_objR, LV_OBJ_FLAG_HIDDEN);
        }
    }
    else if (strcmp(color, "orange") == 0)
    {
        lv_label_set_text(lv_obj_get_child(msg_objY, 0), buffer);
        lv_obj_set_user_data(msg_objY, Data);
        if (lv_obj_has_flag(msg_objY, LV_OBJ_FLAG_HIDDEN))
        {
            lv_obj_clear_flag(msg_objY, LV_OBJ_FLAG_HIDDEN);
        }
    }
}

void panel_del_obj(int msg_id)
{
    uint32_t cnt = lv_obj_get_child_cnt(msg_panel);
    for (uint32_t i = 0; i < cnt; i++)
    {
        lv_obj_t *msg_obj = lv_obj_get_child(msg_panel, i);
        if (!msg_obj)
            continue;

        Button_Data *Data = (Button_Data *)lv_obj_get_user_data(msg_obj);
        if (!Data)
        {
            ESP_LOGW("PANEL", "Found obj with NULL user_data");
            continue;
        }
        if (Data->msg_id == msg_id)
        {
            lv_obj_add_flag(msg_obj, LV_OBJ_FLAG_HIDDEN);
            return;
        }
    }
}


回复

使用道具 举报

0

主题

306

回帖

306

积分

高级会员

积分
306
发表于 2025-11-25 11:10:52 | 显示全部楼层
不要在其他线程中直接修改lvgl数据,在lvgl刷新线程中修改。
回复

使用道具 举报

9

主题

102

回帖

129

积分

初级会员

积分
129
发表于 2025-11-25 11:21:43 | 显示全部楼层
能用coredump去查找问题吗?是出现hardfault吗?
回复

使用道具 举报

9

主题

102

回帖

129

积分

初级会员

积分
129
发表于 2025-11-25 11:29:34 | 显示全部楼层
本帖最后由 lizhaoming 于 2025-11-25 11:35 编辑

在删除对象的时候,再加个lv_obj_is_vaild去判断是否存活,删除完记得把obj = NULL, 另外你的lv_obj_del呢?我好像没看到
回复

使用道具 举报

1

主题

4

回帖

7

积分

新手上路

积分
7
 楼主| 发表于 2025-11-25 11:47:50 | 显示全部楼层
regbbs 发表于 2025-11-25 11:10
不要在其他线程中直接修改lvgl数据,在lvgl刷新线程中修改。

感谢大佬回复,代码中使用了lv_async_call这个方法,我来切换成队列试一试
回复

使用道具 举报

1

主题

4

回帖

7

积分

新手上路

积分
7
 楼主| 发表于 2025-11-25 11:50:01 | 显示全部楼层
lizhaoming 发表于 2025-11-25 11:29
在删除对象的时候,再加个lv_obj_is_vaild去判断是否存活,删除完记得把obj = NULL, 另外你的lv_obj_del呢 ...

感谢大佬回复,我的del功能不是真的del,因为消息频度不低,查了些资料后,现在的代码中是通过给obj添加/清除LV_OBJ_FLAG_HIDDEN来实现显示和删除的
回复

使用道具 举报

4

主题

153

回帖

165

积分

初级会员

积分
165
发表于 2025-11-25 12:12:07 | 显示全部楼层
本帖最后由 turnip 于 2025-11-25 12:13 编辑

你这个MQTT和LVGL是同一个线程?还是不同线程?对于LVGL 9来说,使用Observer进行跨线程通信;LVGL 8则使用Messaging(https://docs.lvgl.io/8.3/others/msg.html)进行跨线程通信。
回复

使用道具 举报

1

主题

4

回帖

7

积分

新手上路

积分
7
 楼主| 发表于 2025-11-25 12:41:52 | 显示全部楼层
turnip 发表于 2025-11-25 12:12
你这个MQTT和LVGL是同一个线程?还是不同线程?对于LVGL 9来说,使用Observer进行跨线程通信;LVGL 8则使用 ...

是不同线程,我来研究一下messaging
回复

使用道具 举报

1

主题

4

回帖

7

积分

新手上路

积分
7
 楼主| 发表于 2025-11-25 14:56:20 | 显示全部楼层
补充下崩溃的日志:
Guru Meditation Error: Core  / panic'ed (Cache error).
MMU entry fault error

Core  0 register dump:
PC      : 0x4037bf8a  PS      : 0x00060e34  A0      : 0x820e1cd5  A1      : 0x3fcae300
--- 0x4037bf8a: esp_cpu_wait_for_intr at C:/Users/Giaosan/esp/v5.5.1/esp-idf/components/esp_hw_support/cpu.c:64
A2      : 0x00060e23  A3      : 0x00000000  A4      : 0x00060e20  A5      : 0x3fce3190
A6      : 0x00060023  A7      : 0x3fcacd30  A8      : 0x803778dd  A9      : 0x3fcae2e0
A10     : 0x3fcacd30  A11     : 0x00000000  A12     : 0x00000000  A13     : 0x00000000
A14     : 0x3fca0440  A15     : 0x00000003  SAR     : 0x0000001d  EXCCAUSE: 0x00000007
EXCVADDR: 0x00000000  LBEG    : 0x00000000  LEND    : 0x00000000  LCOUNT  : 0x00000000


Backtrace: 0x4037bf87:0x3fcae300 0x420e1cd2:0x3fcae320 0x420e1d28:0x3fcae340 0x403826c5:0x3fcae360 0x40381521:0x3fcae380
--- 0x4037bf87: xt_utils_wait_for_intr at C:/Users/Giaosan/esp/v5.5.1/esp-idf/components/xtensa/include/xt_utils.h:82
--- (inlined by) esp_cpu_wait_for_intr at C:/Users/Giaosan/esp/v5.5.1/esp-idf/components/esp_hw_support/cpu.c:55
--- 0x420e1cd2: esp_pm_impl_waiti at C:/Users/Giaosan/esp/v5.5.1/esp-idf/components/esp_pm/pm_impl.c:1051
--- 0x420e1d28: esp_vApplicationIdleHook at C:/Users/Giaosan/esp/v5.5.1/esp-idf/components/esp_system/freertos_hooks.c:56
--- 0x403826c5: prvIdleTask at C:/Users/Giaosan/esp/v5.5.1/esp-idf/components/freertos/FreeRTOS-Kernel/tasks.c:4350
--- 0x40381521: vPortTaskWrapper at C:/Users/Giaosan/esp/v5.5.1/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:139      


Core  1 register dump:
PC      : 0x40374340  PS      : 0x00060d34  A0      : 0x8202708c  A1      : 0x3fcb65b0
--- 0x40374340: _UserExceptionVector at C:/Users/Giaosan/esp/v5.5.1/esp-idf/components/xtensa/xtensa_vectors.S:621
A2      : 0x3fcad178  A3      : 0xffffffff  A4      : 0x03ca0440  A5      : 0x00060b23
A6      : 0x3fca0440  A7      : 0x3fcad168  A8      : 0x82025dc7  A9      : 0x3fca6194
A10     : 0x3fcaa3cc  A11     : 0x00000000  A12     : 0x00060b20  A13     : 0x00060b23
A14     : 0x3fca0440  A15     : 0x0000abab  SAR     : 0x0000001d  EXCCAUSE: 0x00000007
EXCVADDR: 0x3fcaa3cc  LBEG    : 0x400556d5  LEND    : 0x400556e5  LCOUNT  : 0xfffffffe
--- 0x400556d5: strlen in ROM
--- 0x400556e5: strlen in ROM


Backtrace: 0x4037433d:0x3fcb65b0 0x42027089:0x3fcb65d0 0x42027136:0x3fcb65f0 0x4200c318:0x3fcb6610 0x40381521:0x3fcb6630
--- 0x4037433d: _KernelExceptionVector at ??:?
--- 0x42027089: lv_timer_exec at C:/esp_projects/waveshare-1.8/components/lvgl__lvgl/src/misc/lv_timer.c:313
--- 0x42027136: lv_timer_handler at C:/esp_projects/waveshare-1.8/components/lvgl__lvgl/src/misc/lv_timer.c:109
--- 0x4200c318: lvgl_port_task at C:/esp_projects/waveshare-1.8/components/waveshare_display_lvgl_driver/waveshare_display_lvgl_driver.c:202
--- 0x40381521: vPortTaskWrapper at C:/Users/Giaosan/esp/v5.5.1/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:139      




ELF file SHA256: 245fef1d0

Rebooting...
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2026-1-11 17:12 , Processed in 0.055565 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表