2301_76720794 2024-07-31 10:21
浏览 124
已结题

求回复解答LVGL页面多线程问题

指导一下LVGL多线程导致卡死的情况,我用的是LVGL8.2版本,下面两个子线程是接收串口数据和更新下拉列表,在主线程中是创建了文本框组件和下拉列表组件,并且是绑定按钮事件点击创建文本框和下拉列表所在的页面和删除,两个组件分别在不同的页面中;现在的问题有两个,第一个问题就是把更新下拉列表的子线程代码暂时屏蔽掉,运行程序代码后,现象就是只有当文本框组件页面打开,接收串口助手的数据就正常,退出文本框显示其他屏幕时,当接收串口数据,屏幕就卡死了,我尝试加互斥锁好像没有什么用;第二个问题就是把两个子线程都打开,这个更新下拉列表选项的线程从串口接收数据的线程获取数据去更新选项文本,我烧录到触摸屏上现象就是文本框里会接收串口的数据,但是一旦进去页面去点击按钮更新选项文本就卡死了,好像两个问题都是内存卡死的情况。

#if 1
// 线程函数,用于接收串口数据并更新LVGL文本框
void *thread_function(void *arg) {
    while (1) {
        serial_recv();  // 调用串口接收函数
        char * data = get_received_data();
        //char *data[] = {"ABC"};
        //LV_LOG_USER(data[0]);
        pthread_mutex_lock(&mutex);  // 加锁,保护全局数据访问
        if (data != NULL && strlen(data) > 0) {
            lv_textarea_add_text(textarea, data);  // 更新LVGL文本框内容
            memset(data, 0, sizeof(data)); //用于将一块内存区域的内容设置为指定的值
            #if 0
            pthread_mutex_lock(&mutex_1);  // 第二个线程的互斥锁,保护对新选项数据的访问
            free(new_data);  // 释放之前分配的新选项数据内存
            new_data = strdup(data);  // 分配内存并复制数据
            pthread_mutex_unlock(&mutex_1);  // 解锁第二个线程的互斥锁
            #endif
        }
        pthread_mutex_unlock(&mutex);  // 解锁
        usleep(1000);  // 添加适当的延迟以防止CPU占用过高
    }
    return NULL; 
}
#endif

#if 1
// 线程函数,用于将接收到的数据设置为下拉列表的选项
void * update_dropdown_thread(void *arg) { 
    //char options[] = "ABC\n123\nA2C\0";  // 模拟生成选项文本
    int i=0;                                                       
    while (1) {
        i++;
        pthread_mutex_lock(&mutex_1);  // 加锁,保护全局数据访问

        #if 0
        char *options[100] = {0};
        sprintf(options, "ABC\n123\n%d\0", i);
        free(new_data);  // 使用完毕后释放内存
        new_data = strdup(options);  // 复制选项文本
        //LV_LOG_USER("update_dropdown_thread: Generating new options.");
        #endif

        /*if (dropdown123 == NULL)
            LV_LOG_USER("下拉列表为空");
        else
            LV_LOG_USER("下拉列表不为空");*/

        if (dropdown123 != NULL && new_data != NULL) {
            lv_dropdown_clear_options(dropdown123);// 在更新下拉列表之前先清除旧选项
            lv_dropdown_set_options_static(dropdown123, new_data);  // 将接收到的数据设置为选项
            //lv_dropdown_set_options(dropdown123, new_data);  // 将接收到的数据设置为选项
            LV_LOG_USER("update_dropdown_thread: 下拉列表更新成功");
        }
        pthread_mutex_unlock(&mutex_1);  // 解锁
        usleep(50*1000);  // 添加适当的延迟以防止CPU占用过高
    }
    return NULL;
}
#endif

// 初始化函数,用于创建线程和初始化其他必要资源
void initialize_serial_thread() {
    pthread_mutex_init(&mutex, NULL);  // 初始化互斥锁

    #if 1
    // 创建线程
    if (pthread_create(&thread_id, NULL, thread_function, NULL) != 0)  /*pthread_create用于创建一个新的线程, 函数返回一个整数值,如果成功创建线程,则返回0;如果失败,则返回一个非零值,不设置优先级等属性也不传参创建线程*/
    {
        perror("Failed to create thread");
        // 处理线程创建失败的情况
        // 可以选择退出程序或者采取其他错误处理措施
    }
    #endif

    #if 1
    if (pthread_create(&update_thread_id, NULL, update_dropdown_thread, NULL) != 0)  /*pthread_create用于创建一个新的线程, 函数返回一个整数值,如果成功创建线程,则返回0;如果失败,则返回一个非零值*/
    {
        perror("Failed to create thread");
        // 处理线程创建失败的情况
        // 可以选择退出程序或者采取其他错误处理措施
    }
    #endif
}
#endif

下面这段代码是创建的串口文件,接收发送数据接口

/ 获取接收到的数据的函数
char* get_received_data() /*返回全局数组的地址*/
{
    return received_data;
}

void *serial_recv(void)
{
    serial_status_t status = SERIAL_SUCCESS;

    status = serial_handler->frame_recv(serial_handler);
    if (status == SERIAL_SUCCESS)
    {
        printf("recv len = %d,recv=", serial_handler->serial_frame_length);
        for (int i = 0; i < serial_handler->serial_frame_length; i++)
        {
            printf("%c", serial_handler->serial_frame_buff[i]);  //打印接收到的数据
        }
        printf("\n");  // 添加换行符方便阅读输出
        memcpy(received_data, serial_handler->serial_frame_buff, serial_handler->serial_frame_length); // 将接收到的数据复制到全局变量中
        received_data[serial_handler->serial_frame_length] = '\0';  // 确保字符串以空字符结尾
    }
}

下面这段代码是main.c主函数中 lv_timer_handler();函数加相同的互斥锁

pthread_mutex_t mutex_1;
int main(int argc, char **argv)
{
  (void)argc;
  (void)argv; 


  lv_init();

  hal_init();

  // 初始化互斥锁
  pthread_mutex_init(&mutex_1, NULL);
  
  create_layout(); 
  /* 初始化并创建串口接收线程 */
  initialize_serial_thread();
 
  while (1)
  {
    pthread_mutex_lock(&mutex_1);  // 加锁,保护全局数据访问
    lv_timer_handler();
    pthread_mutex_unlock(&mutex_1);  // 解锁
    usleep(5 * 1000); //5ms
  }

  return 0;
}

这是什么问题啊,是因为两个子线程的线程锁不同,还是什么原因,LVGL默认是支持单线程,没有怎么接触过LVGL多线程,琢磨了好长时间都没有排查出来问题在哪。

  • 写回答

0条回答 默认 最新

    报告相同问题?

    问题事件

    • 系统已结题 8月8日
    • 创建了问题 7月31日