在Ubuntu 16.04 32位系统上搭建RT-Thread嵌入式开发环境全攻略
1. 项目概述与核心价值最近在整理一个老旧的嵌入式项目目标板是一块基于ARM Cortex-M3的工控板资源相当有限。客户要求必须使用RT-Thread这个国产的实时操作系统而开发环境则被限定在了一台老旧的工控机上系统是Ubuntu 16.04 LTS 32位英文版。这个组合听起来就有点“复古”对吧但恰恰是这种看似边缘的场景最能考验一个开发环境搭建流程的健壮性和通用性。很多教程都基于最新的Ubuntu 22.04或者Windows下的图形化工具对于这种特定版本、特定架构的老系统往往一笔带过或者直接建议“升级系统”。然而在工业现场、遗留项目维护或者特定硬件限制下我们没得选。因此今天我就来详细拆解一遍如何在Ubuntu 16.04 LTS 32bit英文版这个“经典”环境中从零开始搭建一套完整、可用的RT-Thread开发环境。这个过程不仅适用于RT-Thread其思路和方法对于在老旧Linux系统上搭建任何嵌入式开发工具链都有很高的参考价值。2. 环境准备与系统基础配置在开始安装任何开发工具之前我们必须先让这个“年迈”的Ubuntu系统本身处于一个健康且可用的状态。Ubuntu 16.04 Xenial Xerus发布于2016年其官方的软件源早已停止维护直接使用默认源会导致apt-get update失败这是我们需要解决的第一个拦路虎。2.1 解决老旧系统软件源失效问题Ubuntu官方为EOL生命周期结束的系统提供了旧版本归档源我们需要将系统的软件源指向old-releases.ubuntu.com。这是整个搭建过程的基石这一步错了后面全都无法进行。首先备份原有的源列表文件是一个好习惯sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup接下来编辑源列表文件。这里有一个关键点Ubuntu 16.04 32位系统。我们必须确保源中的架构是i386而不是amd64。使用sudo vim /etc/apt/sources.list或sudo nano /etc/apt/sources.list将文件内容替换为以下内容deb http://old-releases.ubuntu.com/ubuntu/ xenial main restricted universe multiverse deb http://old-releases.ubuntu.com/ubuntu/ xenial-updates main restricted universe multiverse deb http://old-releases.ubuntu.com/ubuntu/ xenial-security main restricted universe multiverse替换完成后执行更新sudo apt-get update如果遇到某些GPG密钥错误可以暂时忽略或者使用sudo apt-get update --allow-insecure-repositories。更新成功后建议先升级一下已有的软件包sudo apt-get upgrade -y。注意old-releases源的速度可能较慢且不保证所有软件包都完整无缺。如果遇到某个特定包无法下载可能需要单独寻找替代方案这是使用老旧系统无法避免的挑战。2.2 安装基础编译与开发工具RT-Thread的开发特别是基于scons的构建系统需要一系列基础编译工具和Python环境。在Ubuntu 16.04上Python 2.7是系统默认版本而scons需要Python 2.7或3.x。我们选择同时安装Python 2.7和3.516.04仓库中的版本并安装必要工具。执行以下命令安装基础套件sudo apt-get install -y build-essential # 包含gcc, g, make等 sudo apt-get install -y git wget curl # 版本管理和下载工具 sudo apt-get install -y python python3 python3-pip python-pip sudo apt-get install -y libncurses5-dev # menuconfig图形配置界面依赖 sudo apt-get install -y device-tree-compiler # 某些BSP需要设备树编译工具安装完成后验证关键工具版本gcc --version # 应显示gcc 5.x python --version # 应显示Python 2.7.x python3 --version # 应显示Python 3.5.x这些版本虽然不算新但对于RT-Thread开发已经完全足够。3. 交叉编译工具链的安装与配置嵌入式开发的核心是交叉编译工具链。我们的目标板是ARM Cortex-M3因此需要ARM-none-eabi-gcc工具链。在32位系统上我们必须寻找预编译的32位版本工具链或者从源码编译。这里强烈推荐使用GNU Arm Embedded Toolchain的预编译版本并手动下载配置。3.1 选择与下载适配32位系统的工具链访问ARM官方开发者网站或国内镜像站寻找历史版本。对于32位主机系统我们需要寻找文件名中包含linux-i686或linux-i386的tar包。例如一个较旧但稳定的版本是gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2。我们可以使用wget下载cd ~ wget https://developer.arm.com/-/media/Files/downloads/gnu-rm/7-2018q2/gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2如果官方链接失效可以在搜索引擎中搜索“gcc-arm-none-eabi-7-2018-q2-update-linux-i686”寻找国内高校或社区的镜像资源。3.2 安装与全局配置工具链下载完成后解压并安装到/opt目录下这是一个存放第三方软件的标准位置sudo tar -xjf gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2 -C /opt解压后工具链的路径通常是/opt/gcc-arm-none-eabi-7-2018-q2-update。为了让系统任何地方都能使用这个工具链我们需要将其bin目录添加到系统的PATH环境变量中。编辑当前用户的profile文件例如~/.bashrcecho export PATH$PATH:/opt/gcc-arm-none-eabi-7-2018-q2-update/bin ~/.bashrc source ~/.bashrc验证安装是否成功arm-none-eabi-gcc --version如果成功将输出GCC的版本信息如“gcc version 7.3.1 20180622 (release) [ARM/embedded-7-branch revision 261907]”。这一步的成功标志着我们具备了编译ARM裸机或RTOS程序的能力。实操心得在32位系统上切勿尝试安装太新的工具链如10.x以上其依赖的glibc库版本可能过高导致无法运行。选择7.x或8.x的版本最为稳妥。如果遇到“No such file or directory”错误通常是因为该二进制文件是64位的使用file命令检查一下确认下载的是32位版本。4. RT-Thread源码获取与ENV工具搭建有了交叉编译工具链接下来就需要RT-Thread操作系统本身的源码以及一个强大的辅助配置和构建工具RT-Thread Env工具以下简称env。4.1 获取RT-Thread源码RT-Thread的源码托管在GitHub和Gitee上。考虑到国内网络环境从Gitee克隆速度更快。我们克隆长期支持LTS版本它更稳定。cd ~ git clone https://gitee.com/rtthread/rt-thread.git cd rt-thread git checkout lts-v3.1.x # 切换到3.1.x LTS分支这是一个非常稳定的版本源码目录rt-thread包含了操作系统的内核、组件、驱动框架以及众多芯片厂商的BSP板级支持包。BSP是我们开发具体板卡的起点。4.2 安装与配置ENV工具Env工具是RT-Thread的“命令行中心”它集成了scons构建系统、menuconfig图形化配置、pkgs包管理器等功能。在Linux下我们需要下载并运行其安装脚本。首先确保安装了git和python前面已安装。然后通过git克隆env仓库并安装cd ~ git clone https://gitee.com/rtthread/env.git rt-thread-env cd rt-thread-env在rt-thread-env目录下你会看到针对不同系统的脚本。对于Linux我们关心的是env.sh。这个脚本主要功能是设置一些环境变量并将工具目录添加到PATH。我们通常不直接运行它而是将其配置到shell的启动文件中。将env工具路径添加到~/.bashrcecho export RTT_ROOT~/rt-thread ~/.bashrc echo export PATH$PATH:~/rt-thread-env/tools ~/.bashrc source ~/.bashrc这里RTT_ROOT环境变量非常重要它告诉env工具RT-Thread源码的根目录在哪里。接下来安装env工具依赖的Python包。env工具的核心是scons和kconfiglib用于menuconfig。由于系统Python包可能较旧我们使用pip安装指定版本pip install --user scons3.1.2 pip3 install --user kconfiglib14.1.0注意事项务必使用--user参数在当前用户目录下安装避免与系统Python包冲突。在Ubuntu 16.04上直接使用sudo pip install可能会破坏系统Python环境。如果提示pip命令找不到请使用python -m pip install --user。安装完成后在终端任意位置输入scons --version和menuconfig如果提示命令未找到尝试新开一个终端应该能看到相应版本信息和一个基于ncurses的配置界面。至此RT-Thread的开发“脚手架”已经搭建完毕。5. 构建第一个示例工程以STM32 BSP为例理论准备就绪现在进入实战环节。我们以RT-Thread源码中自带的bsp/stm32/stm32f103-blue-pill这个BSP为例它对应着市面上极其常见的“蓝色药丸”STM32F103C8T6最小系统板成本低廉非常适合学习和验证。5.1 进入BSP目录与工程配置cd ~/rt-thread/bsp/stm32/stm32f103-blue-pill ls -la你会看到目录下有一些关键文件rtconfig.py工程构建配置、SConstructscons构建脚本、board目录板级硬件相关文件以及librariesHAL库。首先我们需要通过menuconfig来配置工程。这是RT-Thread强大和灵活性的体现。menuconfig一个蓝色的文本图形界面会出现。在这个界面中我们可以使用上下箭头键移动。使用左右箭头键选择底部的Select, Exit , Help , Save , Load 。使用空格键勾选或取消选项[*]表示已编译进内核[M]表示编译为模块[ ]表示不启用。对于第一次尝试我们进行一个最小化配置进入RT-Thread Kernel ---确保内核定时器、线程调度器、信号量、互斥锁等基础功能是开启的默认就是。进入Hardware Drivers Config ----On-chip Peripheral Drivers ----Enable UART确保至少一个串口如USART1是开启的用于后续打印信息。进入RT-Thread Components ----Device Drivers确保Using serial device drivers已开启。按左右箭头键选择 Save 回车使用默认配置文件路径.config再次回车保存。选择 Exit 退出menuconfig。5.2 使用scons构建工程配置保存后生成rtconfig.h头文件该文件由.config自动生成包含了所有宏定义。现在开始编译sconsscons会读取SConstruct和rtconfig.py开始编译整个工程。你会看到大量的编译命令滚动。第一次编译时间会稍长因为它需要编译RT-Thread内核、设备驱动、C库以及BSP相关的启动文件和HAL库。编译成功的标志是在最后看到类似下面的输出LINK rtthread.elf arm-none-eabi-objcopy -O binary rtthread.elf rtthread.bin arm-none-eabi-size rtthread.elf text data bss dec hex filename XXXXX XXXX XXXX XXXXX XXXXX rtthread.elf scons: done building targets.rtthread.elf是生成的调试文件rtthread.bin是纯二进制镜像文件可以直接烧录。arm-none-eabi-size显示的信息告诉我们固件占用了多少Flashtextdata和RAMdatabss。5.3 生成工程文件与烧录虽然可以直接使用bin文件但有时我们希望在IDE中查看和调试代码。Env工具支持生成多种IDE的工程。例如生成Makefile项目适用于任何支持Makefile的编辑器或命令行scons --targetmakefile生成后可以直接使用make命令来编译效果与scons相同。对于STM32最常用的烧录方式是使用ST-Link调试器。我们可以使用OpenOCD开源片上调试器进行烧录。首先安装OpenOCDsudo apt-get install -y openocd然后编写一个简单的OpenOCD配置文件例如stlink.cfg或者使用BSP目录下可能自带的脚本。一个最基础的烧录命令如下假设ST-Link已连接且是V2版本openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c program rtthread.bin 0x08000000 verify reset exit这条命令的含义是使用ST-Link V2接口连接STM32F1系列目标将rtthread.bin文件烧录到Flash起始地址0x08000000并进行校验完成后复位芯片并退出。常见问题排查scons编译报错提示arm-none-eabi-gcc: not found说明工具链路径未正确添加到PATH。请检查~/.bashrc中的export语句并执行source ~/.bashrc或重新打开终端。menuconfig无法打开提示缺少_curses模块这是因为Python的curses模块未安装或有问题。尝试安装sudo apt-get install libncurses5-dev python-dev然后重新安装kconfiglib。编译时提示某个头文件找不到如#include rtthread.h这通常是因为RTT_ROOT环境变量设置错误导致scons找不到源码根目录。请检查echo $RTT_ROOT输出是否正确。OpenOCD连接失败检查ST-Link是否被系统识别lsusb查看是否有ST-Link设备检查接线SWDIO SWCLK GND 3.3V并尝试使用sudo权限运行OpenOCD。6. 串口调试与系统功能验证固件烧录成功后最后一步就是验证系统是否正常运行。串口是最基本、最重要的调试手段。6.1 连接串口与查看输出将STM32板子的串口1通常是PA9/PA10通过USB转TTL模块连接到电脑的USB口。在Ubuntu下该串口会表现为/dev/ttyUSB0或/dev/ttyACM0。安装一个串口终端工具如minicom或picocomsudo apt-get install -y minicom配置minicom以ttyUSB0为例波特率115200sudo minicom -s在配置界面中选择“Serial port setup”设置Serial Device:/dev/ttyUSB0Bps/Par/Bits: 115200 8N1Hardware Flow Control: NoSoftware Flow Control: No然后选择“Save setup as dfl”保存为默认配置最后选择“Exit”。给板子上电如果RT-Thread系统成功启动你将在minicom中看到RT-Thread的Logo和命令提示符\ | / - RT - Thread Operating System / | \ 3.1.3 build May 10 2024 2006 - 2022 Copyright by RT-Thread team msh /msh是RT-Thread的微型Shell你可以在这里输入命令与系统交互。6.2 基础功能测试与组件使用在msh中尝试一些内置命令验证系统基本功能list_thread查看当前系统中所有线程的状态、优先级和堆栈使用情况。这是分析系统负载和调试线程问题的首要命令。free查看系统内存堆的剩余情况。对于资源紧张的MCU时刻关注内存使用至关重要。ps或ps -l类似于Linux的ps命令也是查看线程信息。如果你在menuconfig中开启了更多的组件例如文件系统FATFS、网络协议栈lwIP或设备驱动框架就可以进行更复杂的测试。例如挂载一个SD卡或者连接一个以太网模块。实操心得调试信息分级管理在menuconfig的Kernel配置中可以调整日志级别如RT_DEBUG和RT_DEBUG_LOG。在开发初期可以将级别调高如RT_DEBUG_LOG以便看到更详细的初始化信息和运行日志。在产品发布前务必将其关闭或调至最低以减小代码体积并提升性能。通过ulog组件可以更灵活地控制不同模块的日志输出这是RT-Thread一个非常实用的功能。7. 进阶配置使用包管理器与软件包生态RT-Thread的强大之处在于其丰富的软件包生态。通过Env工具中的pkgs命令可以像Linux的包管理器一样在线下载、添加和管理数百个中间件、协议栈、驱动和工具软件包。7.1 更新与使用包管理器首先进入你的BSP目录更新软件包索引cd ~/rt-thread/bsp/stm32/stm32f103-blue-pill pkgs --update这个命令会从RT-Thread的包仓库拉取最新的包列表。然后我们可以搜索需要的包。例如想找一个JSON解析库pkgs --search json它会列出所有包含“json”关键词的软件包如cJSON。7.2 添加一个软件包到工程假设我们想添加cJSON库到当前工程pkgs --add cJSON这个命令会做两件事1. 在rt-thread根目录的packages文件夹下下载cJSON软件包源码。2. 在当前BSP目录下的packages文件夹中创建一个指向该软件包的Kconfig文件和一个SConscript构建脚本的链接或生成相应配置。接下来需要再次运行menuconfig在配置界面中你会发现在RT-Thread online packages菜单下多出了一个miscellaneous packages或者tools packages之类的子菜单里面就有cJSON的选项。进入后可以将其启用按空格键选择[*]。保存配置退出后重新执行scons编译工程。scons会自动将cJSON包的源代码加入到编译列表中。编译成功后你就可以在应用程序中#include cJSON.h并使用其API了。注意事项软件包管理是RT-Thread开发中提升效率的利器但需要注意版本兼容性。某些较新的软件包可能依赖更高版本的RT-Thread内核特性在LTS版本上可能无法直接使用。添加包后如果编译出错可以查看该软件包目录下的README.md确认其依赖的RT-Thread版本。必要时可以回退到软件包的某个历史提交版本。8. 开发工作流总结与个性化优化至此一个完整的、在Ubuntu 16.04 32位系统上的RT-Thread开发环境已经搭建并验证成功。回顾整个流程我们可以梳理出一个清晰的工作流环境初始化解决软件源问题安装系统级基础工具git, python, build-essential。工具链部署获取并安装32位主机兼容的ARM GCC工具链并配置全局环境变量。源码与工具获取克隆RT-Thread LTS版本源码和Env工具配置RTT_ROOT和PATH。Python依赖安装使用pip --user安装scons和kconfiglib。工程开发循环cd到目标BSP目录。menuconfig配置内核和组件。scons编译生成固件。使用OpenOCD/J-Link等工具烧录。通过串口终端minicom验证和调试。为了让这个环境用起来更顺手可以进行一些个性化优化别名Alias在~/.bashrc中添加一些别名提高效率。alias mcmenuconfig alias scscons alias sc-cscons -c # 清理编译产物串口终端快速启动写一个脚本自动启动minicom并连接到指定串口。版本控制将你修改过的BSP目录特别是board目录下的驱动和链接脚本纳入git管理但注意忽略build编译输出文件夹和.config文件可以保存为.config.default作为默认配置。这套环境虽然建立在“老旧”的系统之上但其工具链和方法论是经久不衰的。它剥离了花哨的图形界面迫使开发者更深入地理解构建过程的每一个环节从交叉编译的原理到操作系统的配置裁剪这种理解对于嵌入式开发者的成长至关重要。当你能在这个环境中游刃有余时切换到更新的系统或更复杂的IDE将会感到轻而易举。