线程及线程消息通信
多线程软件架构
Solution 基于 RT-Thread + LVGL 构建,主要的线程如下:
Task |
Priority |
Stack size |
Purpose Description |
依赖的宏 |
---|---|---|---|---|
timer |
4 |
1536 |
rt_timer_create创建的定时器超时处理 |
|
usbd |
8 |
4096 |
RT USING USB DEVICE消息处理 |
RT USING USB DEVICE |
KE_EVT3 |
10 |
1024 |
HCI message 高优先级接受及分发(KE_MEM足够) |
|
tbread |
10 |
1024 |
touch 触摸处理 |
|
tcpip |
10 |
4096 |
LWIP TCP/IP MSG处理 |
RT USING LWIP |
bt_downvoice |
11 |
2000 |
蓝牙通话下行 |
RT USING BT |
audiovs |
11 |
9216 |
audio server |
AUDIO |
sensor_data |
12 |
2048 |
sensor数据处理 |
双核架构运行在LCPU上 |
bts |
12 |
3072 |
BT 应用消息处理 |
RT USING BT |
KE_EVT2 |
12 |
4096 |
HCI message 低优先级接受及分发(KE_MEM不够), |
|
lcd_task |
12 |
2048 |
LCD msg处理 |
|
displayback_th |
12 |
2048 |
A2DP 解码 |
|
bt_wq |
12 |
3072 |
BT 工作队列 |
RT USING BT |
alarmsvc |
12 |
1024 |
闹钟 |
|
etx |
12 |
1024 |
LWIP 网卡处理 |
RT USING LWIP |
erx |
12 |
1024 |
LWIP 网卡处理 |
RT USING LWIP |
battery_charger_task |
12 |
1536 |
电池检测 |
|
ds_mb |
13 |
1024 |
data service(IPC)通信的mailbox处理 |
双核架构使用,52不使用 |
ds_proc |
14 |
4096 |
data service(IPC)业务处理线程 |
|
epic_task |
15 |
4096 |
渲染及推屏 |
|
lcpu_thread |
19 |
4096 |
sensor timer及算法处理&&hcpu–>lcpu msg处理 |
双核架构运行在LCPU上 |
gui_thread |
19 |
6144 |
UI/VLG及应用相关处理 |
|
tf_task |
20 |
4096 |
TF卡热插拔检测 |
USING_TF_CARD |
tf_thread_task |
22 |
4096 |
TF卡OTA |
USING_TF_CARD |
sys_work |
23 |
4096 |
系统工作队列 |
|
ntp_sync |
25 |
1536 |
ntc 时间同步处理 |
RTC_SYNC USING_NTP |
KE_EVT0 |
25 |
1024 |
HCI |
|
bg_thread |
29 |
4096 |
flash write task |
|
tidle |
31 |
2560 |
IDLE |
Solution 开机后创建的核心线程如下:
GUI 线程(gui_thread):负责 LVGL 界面刷新及所有 GUI 相关逻辑处理。
BG 线程(bg_thread):处理低优先级耗时任务(如 Flash 写入),避免阻塞高优先级线程。
LCPU 线程(lcpu_thread):负责低功耗低功耗相关逻辑与算法。若芯片芯片含物理 LCPU,线程运行于 LCPU;否则运行于 HCPU。
Sensor 数据读取线程(sensor_data):负责 sensor 数据的读取,读完之后发送到 lcpu_thread 处理。
Solution 也使用以下临时线程处理任务:
power_on_thread:仅在开关机动画播放时创建,动画结束后自动销毁。
weather_thread:仅在
PKG_USING_WEBCLIENT
开启且且通过 Internet 获取天气应用时创建,退出后删除。temp_thread:接收到 finsh 命令时创建,处理完成后自动销毁。
vid_dec:ffmpeg(如 H264)解码线程。进入视频播放应用时创建,退出后删除。
ffmpeg_read:ffmpeg(如 H264)从 Flash 读帧线程。进入视频播放应用时创建,退出后删除。
注意: 多线程需通过互斥机制保护共享变量,避免数据竞争导致异常。

线程间通信机制
线程间通过 消息队列 实现通信,流程如下:
发送方:通过专用接口发送消息(包含数据、回调函数等);
接收方:从消息队列中获取消息,调用绑定的回调函数处理;
自动释放:处理完成后,消息资源自动释放,无需手动管理。

线程消息发送接口
发送消息到GUI线程
函数: send_msg_to_gui_thread
作用: 向 GUI 线程发送消息,支持唤醒休眠中的 GUI。
rt_err_t send_msg_to_gui_thread(
void *data, // 待发送的数据
uint32_t len, // 数据长度
void *cb, // 消息处理回调函数(GUI线程中执行)
uint32_t user_data, // 自定义参数(回调中可用)
wakeup_ui_t wakeup // 是否唤醒GUI(NEED_WAKEUP_UI/NO_WAKEUP_UI)
);
说明:
消息调用
service_msg_fill
封装为comm_msg_t
结构,发送至 GUI 线程队列,接收线程处理完成后通过service_msg_rel
进行释放若wakeup =
NEED_WAKEUP_UI
,会先唤醒休眠的 GUI,再处理消息;否则,直接调用处理该消息函数提供了user_data给用户,用户可以在回调函数cb中使用该参数
示例: 传感器检测到事件时,发送事件消息至 GUI 线程并唤醒界面:
// 传感器事件处理回调(转发至GUI线程)
int sensors_msg_process_in_gui_thread_cb(comm_msg_t *msg)
{
uint16_t msg_id = (uint16_t) msg->user_data;
if (SENSOR_APP_EVENT_ID_BEGIN < msg_id && msg_id < SENSOR_APP_EVENT_ID_END)
{
#if defined(APP_POPUP_USED)
popup_run("remind", (void *)msg->data);
#endif
}
return 0;
}
// 发送消息到GUI线程,唤醒界面并指定处理回调
send_msg_to_gui_thread(data, data_len, sensors_msg_process_in_gui_thread_cb, msg_id, NEED_WAKEUP_UI);
发送消息到 BG 线程
函数: send_msg_to_bg_thread
作用: 向 BG 线程发送低优先级任务(如硬件控制、Flash 操作)。
rt_err_t send_msg_to_bg_thread(
void *data, // 待发送的数据
uint32_t len, // 数据长度
void *cb, // 消息处理回调函数(BG线程中执行)
uint32_t user_data // 自定义参数(回调中可用)
);
示例: 控制电机开关(低优先级任务,由 BG 线程处理):
// 电机控制回调(BG线程中执行)
static int motor_control_on_cb(comm_msg_t *msg)
{
app_motor_control_t *motor = msg->data;
if (motor->on)
{
motor_power_on(1);
motor_start();
}
else
{
motor_stop();
motor_power_on(0);
}
return 0;
}
// 发送电机控制消息到BG线程
void app_motor_control(bool on, int16_t times)
{
app_motor_control_t motor_control;
if (motor_times > 0 && times > 0) return;
motor_control.on = on;
motor_times = times;
send_msg_to_bg_thread(&motor_control, sizeof(motor_control), motor_control_on_cb, 0);
}
发送消息到 LCPU 线程
函数: send_msg_to_lcpu_thread
作用: 向 LCPU 线程发送低功耗相关任务(如传感器算法调度)。
rt_err_t send_msg_to_lcpu_thread(
void *data, // 待发送的数据
uint32_t len, // 数据长度
void *cb, // 消息处理回调函数(LCPU线程中执行)
uint32_t user_data // 自定义参数(回调中可用)
);
示例: 调度传感器算法(低功耗任务,由 LCPU 线程处理):
// 传感器调度回调(LCPU线程中执行)
static int sensor_timeout_cb(comm_msg_t *msg)
{
uint32_t period = * ((uint32_t *) msg->data);
gsensor_algo_scheduler(period);
return 0;
}
// 发送调度消息到LCPU线程
void sensor_timer_handle(void *param)
{
rt_err_t ret = send_msg_to_lcpu_thread(&sensor_time, sizeof(sensor_time), sensor_timeout_cb, 0);
}
如何新增一个线程
新增线程用于独立处理特定任务,建议参考lcpu_thread.c实现,核心步骤:
定义线程入口函数:初始化消息队列,循环接收并处理消息。
创建消息处理机制:封装
comm_msg_t
消息结构,绑定回调函数。设置线程属性:合理配置优先级(避免过高影响系统响应,或过低导致任务延迟)。
定义通信接口:提供类似
send_msg_to_xxx_thread
的专用发送函数,方便其他线程调用。确保线程退出时释放资源(如消息队列、动态内存),避免内存泄漏。