15 分钟上手:把 RT-Thread 跑进 ESP32-C3(BSP 移植完整指南)
【免费下载链接】rt-threadRT-Thread is an open source IoT Real-Time Operating System (RTOS). https://rt-thread.github.io/rt-thread/项目地址: https://gitcode.com/gh_mirrors/rt/rt-thread
想让 RT-Thread 跑在 ESP32-C3 上,却不想从驱动层开始啃?别急,RT-Thread 官方仓库已经准备好了bsp/ESP/ESP32_C3板级支持包,本文按"选板 → 搭环境 → 编译 → 烧录 → 验证 → 扩展"的动手顺序带你一次走通。
3 分钟看懂 RT-Thread ESP32-C3 BSP 的设计思路
内核是 RT-Thread,底层复用乐鑫 ESP-IDF——这是该 BSP 的核心思路。构建脚本 rtconfig.py 声明ARCH='risc-v',编译使用乐鑫的 RISC-V GCC 工具链(前缀riscv32-esp-elf-);BSP 内的idf_port/目录则提供 FreeRTOS 兼容头文件、链接脚本与 port 实现,让 ESP-IDF 的驱动层"以为自己在跑 FreeRTOS",RT-Thread 内核就坐落在它之上。GPIO、UART、I2C、SPI 等外设驱动统一放在共享目录 bsp/ESP/libraries/drivers/ 中,由 Kconfig 开关决定是否参与编译。
分工明确带来的好处是:你不需要自己写任何底层 ROM 调用和外设驱动,环境配好就能直接出包。
menuconfig 里 30 秒选对你的开发板
该 BSP 实测跑通两块 C3 板子,而两块板的 LED 引脚不同,所以必须在 menuconfig 中选对板子,否则灯不闪:
| 开发板 | Kconfig 选项 | LED 默认引脚 | UART TX/RX 默认引脚 |
|---|---|---|---|
| LUATOS_ESP32C3(合宙) | BSP_BOARD_LUATOS_ESP32C3(默认) | IO12 | IO21 / IO20 |
| HX-DK-商(红旭) | BSP_BOARD_HX_EXP32C3 | IO8 | 无板级默认值,需手动设置 |
选板入口是 bsp/ESP/libraries/drivers/Kconfig 中的choice BSP_BOARD_SEL组。选中后,RT_BSP_LED_PIN、RT_BSP_UART_TX_PIN、RT_BSP_UART_RX_PIN、RT_BSP_SPI_CS_PIN(LUATOS 板默认 IO10)等选项的默认值会自动跟随切换——换板只改选项,不用碰一行代码。
以 LUATOS_ESP32C3 为例:主控为 ESP32-C3(160MHz,BSP 文档给出的跑分为 407.22 CoreMark / 2.55 CoreMark/MHz),芯片内置 384KB ROM + 400KB SRAM;板上有 2 颗红色 LED(D4=IO12、D5=IO13)、K1(BOOT)与 K2(RST)两个按键,以及 4MB SPI Flash。
注意:LUATOS 板的调试串口 UART0_TX / UART0_RX 需要外接 CP2102 之类的串口转 USB 芯片才能收到日志。
搭好编译环境:Docker 快通道与原生环境两条路 🔧
路线 A:Docker 一键(轻度尝鲜推荐)
BSP 自带 docker/Dockerfile:基于 Ubuntu 22.04,装好 scons、minicom、esptool,把 RISC-V 工具链放到/opt,克隆主线仓库并安装 env 工具、预拉软件包。你只需两步:
cd bsp/ESP/ESP32_C3/docker sudo docker build --build-arg HTTP_PROXY=http://ip:port --build-arg HTTPS_PROXY=http://ip:port -t image_name . sudo docker run -it --device=/dev/ttyUSB* image_name其中ip:port换成你的代理地址,否则容器内拉仓库可能失败;--device把宿主机串口透传进来,供烧录与调试使用(端口号可在宿主机ls /dev/ttyUSB*查看)。也可以直接拉预构建镜像1078249029/rtthread_esp32c3:latest(时效性不保证),run 时把镜像名替换掉即可。
路线 B:原生环境(长期开发推荐)
先下载乐鑫 crosstool-NG 发布的 RISC-V 工具链并解压(与当前仓库匹配的版本是 esp-15.2.0_20251204),再让构建系统找到它,两种方式任选其一:
- 修改 rtconfig.py 里的
EXEC_PATH变量,默认值是~/.espressif/tools/riscv32-esp-elf/esp-15.2.0_20251204/riscv32-esp-elf/bin; - 或者用环境变量覆盖,优先级更高、更省事:
export RTT_EXEC_PATH=/opt/riscv32-esp-elf/bin第一次编译:从 menuconfig 到 scons 出可烧录的 rtthread.bin
进入 BSP 目录依次执行(首跑scons --menuconfig会自动把 env 脚本下载到~/.env):
cd bsp/ESP/ESP32_C3 scons --menuconfig source ~/.env/env.sh pkgs --update sconspkgs --update会拉取ESP-IDF-latest与FreeRTOS-Wrapper两个软件包——这正是"复用 ESP-IDF"思路的落地来源。编译成功后生成两个文件:rtthread.elf是未打包的链接产物;rtthread.bin则是 SConstruct 在链接后挂的钩子调用 esptool 的ELFFile/CHIP_DEFS接口打出的应用镜像(DIO 模式、4MB Flash、80MHz 频率),直接烧进 0x10000 就能启动。
menuconfig 里第一次只需要关心三处:
Hardware Drivers Config→Select BSP board:选自己的板子;- GPIO、UART 默认已开,其余外设按后文的开关表按需勾;
- 想抓异常现场,勾上
BSP_ENABLE_GDBSTUB。
烧录 ESP32-C3:Windows 与 Linux 两条线、三个固定地址 🚀
无论哪条线,烧录布局都是同样的三个文件、三个偏移:
| 文件 | 偏移地址 | 来源 |
|---|---|---|
| bootloader.bin | 0x0 | bsp/ESP/ESP32_C3/builtin_imgs/ |
| partition-table.bin | 0x8000 | 同上 |
| rtthread.bin | 0x10000 | scons 编译产物 |
Windows 线:BSP 实测使用乐鑫 Flash Download Tools 3.9.4 无误。芯片型号选ESP32-C3,按上表填好文件与地址后点 START 即可。
Linux 线:esptool 一条命令搞定(pip install esptool装过就能用):
esptool.py -b 115200 --before default_reset --after hard_reset write_flash \ --flash_mode dio --flash_size detect --flash_freq 80m \ 0x0 bootloader.bin 0x08000 partition-table.bin 0x010000 rtthread.bin参数拆解:-b 115200是串口波特率;--before default_reset/--after hard_reset决定烧录前后的自动复位策略;--flash_mode dio必须与打包时的 DIO 模式保持一致;detect自动识别 Flash 容量;80m为 Flash 工作频率。多块板同插时用-p指定端口;烧录失败先查当前用户有没有串口访问权限。
验证烧录结果,再用 GDBStub 抓崩溃现场
最快的验证是 LED:main/main.c 的默认程序先打印一句 Hello RT-Thread 问候,然后把RT_BSP_LED_PIN上的灯每秒翻转一次——看到灯规律呼吸,说明从 bootloader 到内核的链路全部打通。
看串口日志:Linux 下用 minicom 盯住板子串口(Docker 容器里同样可用):
sudo minicom -c on -D /dev/ttyUSB*GDBStub 抓现场:编译时开了BSP_ENABLE_GDBSTUB的话,芯片跑飞出错会自行停住进入 GDB 模式,方便定位异常现场。PC 端起 GDB 后加载 BSP 目录下的调试脚本 esp32c3.gpb(脚本里已预设好各内存区域、115200 波特率、连接/dev/ttyACM0以及加载./rtthread.elf):
sudo riscv32-esp-elf-gdb (gdb) source esp32c3.gpb通过 USB 与 PC 相连的开发板即可按此方式调试。
外设开关对照表,以及 Wi-Fi / BLE 的坑位
各外设在On-chip Peripheral Drivers菜单中的开关与默认状态如下:
| 外设 | 开关 | 默认 | 备注 |
|---|---|---|---|
| GPIO | BSP_USING_GPIO | y | 自动启用RT_USING_PIN |
| UART | BSP_USING_UART | y | 端口号RT_BSP_UART_PORT默认 0 |
| I2C | BSP_USING_I2C | n | 下设BSP_USING_HW_I2C/BSP_USING_SOFT_I2C |
| SPI | BSP_USING_SPI | n | 子开关BSP_USING_SPI2,片选RT_BSP_SPI_CS_PIN |
| ADC | BSP_USING_ADC | n | 子开关BSP_USING_ADC1 |
| PWM | BSP_USING_PWM | n | 子开关BSP_USING_PWM0,6 路 LEDC 引脚默认 12/6/2/10/8/18 |
| 时钟定时器 | BSP_USING_CLOCK_TIMER | n | 子开关BSP_USING_TIMER0 |
| Wi-Fi | BSP_USING_WIFI | n | — |
| BLE | BSP_USING_BLE | n | — |
| GDBStub | BSP_ENABLE_GDBSTUB | n | — |
坑位 1:硬件 I2C 通路不可靠。官方文档明确说硬件总线会出现传输错误,建议走软件 I2C(BSP_USING_SOFT_I2C→BSP_USING_SOFT_I2C0,SCL 默认 IO19、SDA 默认 IO18,均可改);代价是它要占用一个硬件通用定时器。
坑位 2:Wi-Fi 与 BLE 互斥。BLE 驱动只支持 NimBLE(由 esp-idf 的 bluetooth 组件提供),启用前务必在 menuconfig 里关掉RT_USING_WIFI和LWIP。
坑位 3:用 NimBLE 前必须先初始化时钟。调任何 NimBLE 接口之前要先执行esp_timer_init();可直接参考packages/ESP-IDF-latest/examples/bluetooth/nimble(pkgs --update后生成)下的样例,把它并入 scons 编译——main.c已预留"先 esp_timer_init()、再进 app_main() 样例入口"的调用位置;Wi-Fi 侧同样预留好了 STA + AP 双模式的配置代码。
注意:Wi-Fi 与 BLE 目前均标注为"部分支持"——Wi-Fi 存在 ISR 里不能用rt_mq_recive之类的已知问题,NimBLE 则可能运行一段时间后报错。日常外设开发不受影响,但涉及无线业务上生产前请先评估边界。
维护者与社区
该 BSP 由 supperthomas、tangzz98、wumingzi 三位维护,其中 wumingzi 同时维护 Docker 镜像;RISC-V 部分最初由 chenyingchun0312 提供支持。遇到问题可通过公众号「Thomas的小火车」与维护者交流。
推荐的上手顺序
- 先走 Docker 快通道(或配好
RTT_EXEC_PATH原生环境),确认riscv32-esp-elf-gcc可用; scons --menuconfig选对板子 →pkgs --update→scons,核对产物里有rtthread.bin;- 用 esptool(或 Windows 烧录工具)写入 0x0 / 0x8000 / 0x10000,看到 LED 按秒闪、串口出现 Hello RT-Thread 即算打通;
- 之后开
BSP_ENABLE_GDBSTUB熟悉抓现场,再逐项启用 I2C、SPI、ADC 扩展自己的应用,Wi-Fi/BLE 最后按需评估。
【免费下载链接】rt-threadRT-Thread is an open source IoT Real-Time Operating System (RTOS). https://rt-thread.github.io/rt-thread/项目地址: https://gitcode.com/gh_mirrors/rt/rt-thread
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考