STM32 RT-Thread多任务同步与调度调试 - 第1节
1.1 RT-Thread 到底是什么?
先聊聊 RT-Thread 的背景。我最早接触它是在 2017 年,当时项目里需要一个轻量级 RTOS,又不想用 FreeRTOS 那种纯 C 风格——说实话,FreeRTOS 的 API 设计有点「原始」。RT-Thread 给我的第一印象是:它更像一个「小而全」的物联网操作系统,而不只是调度器。
它的内核架构,说白了就三层:
- 底层:硬件抽象层(HAL),负责屏蔽芯片差异
- 中间层:内核对象管理、调度器、IPC 通信
- 上层:组件层(文件系统、网络协议栈、设备框架)
我习惯把 RT-Thread 比作「乐高积木」——你可以只拿内核跑裸机任务,也可以把文件系统、网络、GUI 全堆上去。嗯,这跟 Linux 的思路有点像,但资源开销小得多。
核心特点:
- 支持多线程抢占式调度,优先级 256 级
- 对象化设计:线程、信号量、互斥锁、事件、邮箱、消息队列都是对象
- 组件丰富:DFS(虚拟文件系统)、LwIP、Finsh 控制台
- 标准版 + Nano 版双线并行,Nano 版最小 ROM 仅 3KB
应用场景?我见过有人拿它做智能门锁、工业采集器、无人机飞控。说白了,只要你的 MCU 有 64KB Flash 以上,RT-Thread 就能跑得很舒服。
1.2 内核架构速览
RT-Thread 的内核不是「大而全」的宏内核,而是微内核风格。我画了张图帮你快速理解:
你看,从下往上依次是:硬件抽象层 → 内核层 → 组件层 → 应用层。每一层都只依赖下层,不跨层调用。这种设计的好处是——你换芯片时,只需要改 BSP 和 HAL,上层代码基本不动。
我的经验: 刚开始学 RT-Thread 时,别急着研究组件层。先把内核层的线程、信号量、消息队列玩熟,后面加组件就是「搭积木」的事。
1.3 开发环境搭建
1.3.1 工具链选择
RT-Thread 官方推荐两套工具链:
| 工具 | 适用场景 | 我的建议 |
|---|---|---|
| Keil MDK | STM32 系列,调试方便,IDE 集成度高 | 新手首选,上手快 |
| Env + GCC | 跨平台,命令行操作,适合 CI/CD | 我习惯用这个,灵活 |
| RT-Thread Studio | 官方 IDE,集成 Env + 调试器 | 适合不想折腾的人 |
我个人习惯用 Keil MDK + Env 的组合。Keil 负责编译调试,Env 负责包管理和配置。为什么这么搭?因为 Env 的 menuconfig 能帮你自动生成工程,省去手动添加文件的麻烦。
1.3.2 安装步骤
- 安装 Keil MDK:去 ARM 官网下载 MDK-ARM,版本 5.27 以上。注意要装好对应芯片的 Pack(比如 STM32F4xx_DFP)。
- 安装 Env 工具:从 RT-Thread 官网下载 Env 压缩包,解压到无中文路径。双击
env.exe启动。 - 配置环境变量:Env 会自动配置 Python、scons、gcc 路径。如果报错,检查一下系统 PATH 里有没有冲突。
- 验证安装:在 Env 终端输入
scons --version,看到版本号就说明成功了。
避坑指南: 我曾经在 Win10 上装 Env 时,因为 Python 3.9 版本太高,导致 scons 报错。后来换成 Python 3.8 就好了。建议用 Env 自带的 Python,别自己装。
1.4 创建第一个 RT-Thread 工程
好,环境搭好了,咱们动手创建一个工程。以 STM32F407ZGT6 为例。
1.4.1 使用 Env 生成工程
打开 Env 终端,cd 到你的工作目录,执行:
mkdir my_first_rtthread
cd my_first_rtthread
scons --dist
这个命令会从 RT-Thread 源码仓库拉取最新代码,并生成一个 dist 目录。里面包含了完整的工程模板。
然后进入 dist 目录,找到 bsp/stm32f407-atk-explorer(根据你的板子选对应的 BSP)。执行:
menuconfig
你会看到一个图形化配置界面。这里可以开关组件、配置内核参数。第一次用,保持默认就行。按 Esc 退出并保存。
最后执行:
scons --target=mdk5
这会在 BSP 目录下生成 Keil 工程文件 project.uvprojx。
1.4.2 在 Keil 中编译与下载
双击打开 project.uvprojx,你会看到工程里已经包含了 RT-Thread 内核源码、BSP 驱动、启动文件。直接点 Build(F7),应该能零错误编译通过。
然后连接 ST-Link,点 Download(F8),把固件烧进板子。打开串口助手(波特率 115200),按复位键,你会看到 RT-Thread 的启动 Logo:
\ | /
- RT - Thread Operating System
/ | \ 4.0.3 build Mar 10 2023
2006 - 2022 Copyright by RT-Thread team
msh >
看到 msh > 提示符了吗?恭喜,你的第一个 RT-Thread 系统跑起来了!
1.4.3 写一个简单的线程
咱们来写个线程,让 LED 闪烁。在 applications/main.c 中添加:
#include <rtthread.h>
#include <board.h>
#define LED_PIN GET_PIN(F, 9) // 根据你的板子改引脚
static void led_thread_entry(void *parameter)
{
while (1)
{
rt_pin_write(LED_PIN, PIN_HIGH);
rt_thread_mdelay(500);
rt_pin_write(LED_PIN, PIN_LOW);
rt_thread_mdelay(500);
}
}
int main(void)
{
rt_thread_t led_thread = rt_thread_create("led",
led_thread_entry,
RT_NULL,
1024,
20,
10);
if (led_thread != RT_NULL)
rt_thread_startup(led_thread);
return 0;
}
编译下载后,LED 应该以 1Hz 频率闪烁。嗯,这里要注意:rt_thread_mdelay 是毫秒级延时,它会主动让出 CPU,不会阻塞其他线程。
我的经验: 刚开始写线程时,栈大小(第三个参数)别给太小。我见过有人给 256 字节,结果线程一跑就崩。STM32 上建议至少 1024 字节起步。
1.5 本章小结
这一章我们干了三件事:
- 理解了 RT-Thread 的「三层架构」——硬件抽象、内核、组件
- 搭好了 Keil + Env 的开发环境
- 跑通了第一个多线程程序(LED 闪烁)
说白了,RT-Thread 没那么神秘。它就是一个帮你管理 CPU 时间的「管家」。你只需要告诉它:什么时候该做什么事,剩下的调度、同步、通信,它都帮你搞定。