公司动态

在Fedora 12老旧系统上搭建RT-Thread嵌入式开发环境实战

📅 2026/8/19 13:44:56
在Fedora 12老旧系统上搭建RT-Thread嵌入式开发环境实战
1. 项目缘起一次老系统上的嵌入式探索最近整理旧设备翻出来一台还在跑Fedora 12的老笔记本。这系统现在看绝对是古董级的了内核版本我记得还是2.6.31GCC工具链也停留在4.4.x的时代。按理说这种环境早该淘汰了但手头正好有个小需求想在一个资源极其有限的ARM Cortex-M3开发板上跑点轻量级任务第一时间就想到了RT-Thread这个国产的实时操作系统。它的可裁剪性和丰富的组件生态很吸引人但官方文档和社区讨论大多基于Ubuntu 18.04/20.04或者更新的Fedora版本。一个念头冒出来能不能就在这台老Fedora 12上把RT-Thread的编译和调试环境给搭起来这不仅仅是为了“怀旧”或者挑战。在实际的嵌入式开发尤其是面向工业、车载等长生命周期领域时你经常会遇到一种情况项目所用的编译服务器或开发机其操作系统因为稳定性、兼容性或历史原因被“锁定”在某个较旧的版本轻易不能升级。这时你需要的不是最新最炫的工具而是在给定约束条件下找到一条切实可行的路。在Fedora 12上搞RT-Thread本质上就是一次在“受限环境”下的标准开发流程实践其中遇到的包依赖、工具链版本、调试器兼容性问题具有相当的普适性。如果你手头也有类似的老系统或者需要在特定版本Linux上构建嵌入式开发环境那这次折腾的过程或许能给你一些参考。2. 环境评估与基础准备认清现实打好地基在Fedora 12上干活第一步不是急着下载代码而是先搞清楚这个“战场”的现状。通过uname -a和cat /etc/fedora-release确认了系统信息后我意识到几个核心挑战软件源失效Fedora 12的官方源早就停止维护了yum命令基本报废。这是最大的拦路虎。工具链陈旧系统自带的GCC是4.4.4对于编译一些较新的代码特别是C11以后特性的可能力不从心。虽然RT-Thread内核主要用C语言但其构建系统scons基于Python且一些BSP板级支持包或组件可能对编译器有要求。依赖库缺失编译所需的开发库如libncurses-devel,python-devel等版本老旧甚至缺失。我的策略是不尝试升级系统或替换关键系统组件如GCC以免引发不可预知的系统崩溃。转而采用“局部修补”和“源码编译”的方式在用户空间内构建一个相对独立的开发环境。具体操作如下2.1 解决软件源问题启用老版本存档源虽然官方源停了但我们可以使用Fedora的存档仓库。编辑/etc/yum.repos.d/目录下的文件如果没有就新建一个比如fedora-archive.repo添加以下内容[fedora-archive] nameFedora 12 archive baseurlhttp://archives.fedoraproject.org/pub/archive/fedora/linux/releases/12/Everything/$basearch/os/ enabled1 gpgcheck0 [fedora-archive-updates] nameFedora 12 archive updates baseurlhttp://archives.fedoraproject.org/pub/archive/fedora/linux/updates/12/$basearch/ enabled1 gpgcheck0注意这里将gpgcheck设为0是因为存档源的GPG密钥可能已过期或无法验证在已知源安全的前提下可以这样处理。设置好后运行yum makecache测试一下应该能正常更新软件包列表了。2.2 安装基础开发工具和依赖接下来安装编译和调试所需的最基础包。有些包名在老的Fedora上可能和现在不同。yum install -y gcc gcc-c make automake autoconf yum install -y ncurses-devel # 用于menuconfig配置界面 yum install -y git wget patch yum install -y texinfo # 某些工具链编译需要 yum install -y python-devel # 编译scons或某些Python模块可能需要2.3 准备Python和SCons环境RT-Thread使用SCons作为构建工具。Fedora 12自带的Python是2.6.xSCons版本也很老。稳妥起见我选择从源码编译安装一个较新的Python 2.7因为一些老工具链脚本可能对Python 3兼容不好并为其安装SCons。# 下载Python 2.7.18源码 (这是2.7的最后一个版本兼容性好) wget https://www.python.org/ftp/python/2.7.18/Python-2.7.18.tgz tar xzf Python-2.7.18.tgz cd Python-2.7.18 ./configure --prefix/usr/local/python2.7 --enable-optimizations make -j$(nproc) sudo make altinstall # 使用altinstall避免替换系统python # 将新安装的python2.7加入PATH或创建软链接 ln -sf /usr/local/python2.7/bin/python2.7 /usr/local/bin/python2.7 ln -sf /usr/local/python2.7/bin/pip2.7 /usr/local/bin/pip2.7 # 使用pip安装scons /usr/local/python2.7/bin/pip2.7 install scons ln -sf /usr/local/python2.7/bin/scons /usr/local/bin/scons注意这里使用altinstall是为了防止覆盖系统自带的python命令很多系统工具依赖它。我们后续明确使用python2.7和scons命令。至此一个可用的基础编译环境就准备好了。虽然系统GCC旧但我们主要用它来编译一些本地工具。真正的ARM交叉编译工具链我们需要单独准备。3. 交叉编译工具链的选型与部署对于ARM Cortex-M3常见的工具链有arm-none-eabi-gcc。在老旧系统上直接下载预编译的工具链二进制包是最省事、最不容易出问题的方法。我选择了GNU Arm Embedded Toolchain的较旧版本比如9-2019-q4-major因为新版本可能依赖更高的GLIBC库在Fedora 12上无法运行。3.1 下载与安装# 在用户目录下操作 cd ~ wget https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2019q4/gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2 tar xjf gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2 mv gcc-arm-none-eabi-9-2019-q4-major ~/gcc-arm-embedded3.2 验证工具链兼容性这是关键一步。解压后不要急着加到PATH先检查其动态库依赖是否满足。cd ~/gcc-arm-embedded/bin ldd arm-none-eabi-gcc重点关注输出中libc.so.6和ld-linux-x86-64.so.2对应的GLIBC版本。例如它可能要求GLIBC_2.14而Fedora 12的GLIBC版本可能只有2.11。如果出现not found或版本不满足这个二进制文件就无法直接运行。3.3 应对GLIBC版本过低的问题如果遇到上述问题有几种应对策略寻找更旧的工具链版本尝试下载7-2018q2或更早的版本其对GLIBC的要求可能更低。从源码编译工具链这是最彻底但最复杂的方法。你需要下载binutils,gcc,newlib的源码并针对arm-none-eabi目标进行编译。这个过程非常耗时且可能遇到各种依赖问题。在Fedora 12上你需要确保有足够新的gmp,mpfr,mpc等库可能也需要从源码编译它们。使用Crosstool-NG这是一个自动化编译工具链的工具。但在老系统上编译Crosstool-NG本身也可能有依赖问题。我这次比较幸运找到的9-2019-q4版本依赖的GLIBC是2.15而通过ldd --version查看发现Fedora 12的GLIBC是2.11确实不满足。于是我退而求其次找到了一个gcc-arm-none-eabi-7-2018-q2-update版本经检查其依赖的GLIBC为2.7完全兼容。3.4 配置环境变量将可用的工具链路径加入用户的.bashrc文件中。echo export PATH$PATH:~/gcc-arm-embedded/bin ~/.bashrc echo export RTT_EXEC_PATH~/gcc-arm-embedded/bin ~/.bashrc # RT-Thread构建系统可能用到 source ~/.bashrc然后验证工具链是否可用arm-none-eabi-gcc --version如果成功输出版本信息那么最艰难的一关就算过了。4. 获取RT-Thread源码与基础编译环境准备好后就可以开始接触RT-Thread本身了。4.1 克隆源码RT-Thread的代码托管在Gitee上使用git克隆。cd ~ git clone https://gitee.com/rtthread/rt-thread.git cd rt-thread4.2 选择BSP板级支持包RT-Thread采用BSP结构你需要选择一个与你目标硬件或模拟环境最接近的BSP进行开发。对于初次编译测试我建议选择qemu-vexpress-a9这个BSP它可以在QEMU模拟器上运行无需真实硬件。cd bsp/qemu-vexpress-a94.3 使用menuconfig配置内核RT-Thread提供了类似Linux的menuconfig配置界面可以方便地裁剪内核、选择组件。scons --menuconfig如果执行成功会弹出一个图形化配置界面。这里有个坑Fedora 12自带的ncurses库可能版本太低导致menuconfig界面显示异常如字符错乱。如果遇到这种情况可以尝试从源码编译安装新版的ncurses或者直接手动编辑配置文件。更简单的方法是暂时跳过这一步使用BSP的默认配置。4.4 执行编译在BSP目录下直接运行scons命令即可开始编译。scons编译过程会调用我们之前设置的交叉编译工具链arm-none-eabi-gcc。如果一切顺利你会在当前目录下看到生成的rtthread.elf、rtthread.bin等文件。4.5 首次编译可能遇到的问题与解决问题1scons: command not found解决确认/usr/local/bin是否在PATH中并且scons软链接存在。或者直接使用绝对路径/usr/local/python2.7/bin/scons。问题2编译错误提示arm-none-eabi-gcc: command not found解决检查环境变量RTT_EXEC_PATH是否设置正确并确保arm-none-eabi-gcc所在路径已加入PATH。可以在BSP目录下执行echo $RTT_EXEC_PATH和which arm-none-eabi-gcc来验证。问题3头文件找不到如#include rtthread.h报错解决这通常是因为scons脚本没有正确找到RT-Thread的根目录。确保你在BSP目录如bsp/qemu-vexpress-a9下执行scons它会自动向上搜索rt-thread根目录。不要直接在根目录执行scons。问题4链接阶段报错关于_sbrk,_write等系统调用未定义解决这是工具链的newlib库与BSP的对接问题。需要检查BSP目录下的board.c文件是否实现了这些底层接口通常叫做“桩函数”。对于qemu-vexpress-a9这个BSP这些已经实现好了。如果用的是其他BSP可能需要根据具体硬件实现这些函数。错误信息会明确告诉你缺少哪个符号。第一次看到scons成功编译生成rtthread.elf文件时感觉就像在老旧的收音机上收到了清晰的信号证明我们搭建的这套“老破小”环境是work的。5. 在QEMU中运行与调试有了可执行文件下一步就是让它跑起来。对于qemu-vexpress-a9这个BSP我们需要安装QEMU模拟器。5.1 安装QEMUFedora 12的仓库里可能有很老的qemu我们同样从源码编译一个能用的版本。这里选择较旧的QEMU 2.12.0兼容性更好。cd ~ wget https://download.qemu.org/qemu-2.12.0.tar.xz tar xJf qemu-2.12.0.tar.xz cd qemu-2.12.0 # 配置时只编译我们需要的system-arm模式节省时间和依赖 ./configure --target-listarm-softmmu --audio-drv-list --disable-bluez --disable-brlapi --disable-curses --disable-curl --disable-fdt --disable-gnutls --disable-gtk --disable-libiscsi --disable-libnfs --disable-libssh2 --disable-linux-aio --disable-lzo --disable-opengl --disable-rbd --disable-rdma --disable-sdl --disable-seccomp --disable-snappy --disable-spice --disable-tpm --disable-vde --disable-vhost-net --disable-virtfs --disable-vnc --disable-vte --disable-xen --disable-xen-pci-passthrough make -j$(nproc) sudo make install编译配置中禁用了大量不必要的前端和功能主要是为了减少在老系统上解决依赖的麻烦。我们只需要它能模拟ARM Versatile Express开发板并运行我们的固件即可。5.2 运行RT-Thread回到BSP目录使用以下命令启动QEMUqemu-system-arm -M vexpress-a9 -kernel rtthread.elf -serial stdio -nographic-M vexpress-a9指定机器类型为vexpress-a9与BSP对应。-kernel rtthread.elf指定要加载的内核镜像。-serial stdio -nographic将串口输出重定向到当前终端并以非图形化模式运行。如果成功你应该能看到RT-Thread的启动LOGO并进入shell命令行可以尝试输入list_thread等命令查看线程信息。5.3 配置GDB调试在开发中调试是必不可少的。我们需要使用GDB进行远程调试。首先确保你的工具链里包含arm-none-eabi-gdb。然后在编译RT-Thread时需要生成包含调试信息的ELF文件默认scons命令就会生成。5.3.1 启动QEMU的GDB调试服务端在另一个终端运行QEMU并开启GDB调试端口例如1234qemu-system-arm -M vexpress-a9 -kernel rtthread.elf -serial stdio -nographic -S -s-S表示启动后暂停CPU等待GDB连接。-s是-gdb tcp::1234的简写在TCP的1234端口开启GDB服务器。5.3.2 启动GDB客户端并连接在原来的终端启动GDB并加载调试文件arm-none-eabi-gdb rtthread.elf在GDB命令行中连接QEMU(gdb) target remote localhost:1234连接成功后GDB会提示当前暂停的位置。此时你可以设置断点、单步执行、查看变量等。(gdb) b main # 在main函数设置断点 (gdb) c # 继续运行当程序运行到main函数时就会暂停。你可以使用list查看代码next单步print查看变量值。5.4 调试中的常见问题GDB连接被拒绝检查QEMU是否正确使用了-s参数以及端口1234是否被占用。GDB提示Remote g packet reply is too long这是一个比较经典的问题多见于64位主机调试32位目标时。解决方法是在GDB中连接后执行以下命令(gdb) set architecture arm (gdb) disconnect (gdb) target remote localhost:1234或者更一劳永逸的方法是在连接前就指定架构arm-none-eabi-gdb -ex set architecture arm rtthread.elf。符号表找不到或地址不对确保GDB加载的rtthread.elf文件与QEMU运行的rtthread.elf是同一个文件并且是带调试信息的编译产物。6. 向真实硬件迁移的注意事项在QEMU上跑通只是万里长征第一步。最终代码是要烧录到真实的Cortex-M3芯片里的。这个过程在Fedora 12上又会遇到一些特有的挑战。6.1 烧录工具的选择与编译常见的烧录工具如openocd、pyocd、stlink工具等。同样面临依赖库版本问题。OpenOCD这是一个功能强大的开源调试和烧录工具。我们可以尝试从源码编译一个旧版本比如0.10.0。编译前需要安装libusb-1.0-devel,libftdi-devel等开发包。在老系统上这些包的版本可能也不够有时需要从源码编译这些依赖库形成一个“套娃”式的编译过程极其繁琐。ST-LINK CLI工具如果你使用的是ST的芯片可以尝试直接使用ST官方提供的Linux版命令行工具。有时静态编译的版本依赖较少在老系统上可能直接能运行。可以去ST官网寻找历史版本。J-Link工具SEGGER提供的J-Link工具链通常提供静态链接的二进制文件对系统库依赖极少在老旧系统上兼容性最好。如果有J-Link调试器这是首选。6.2 编译配置的调整从QEMU的vexpress-a9ARM-A系列切换到真实的Cortex-M3ARM-M系列需要更换BSP。RT-Thread提供了大量MCU的BSP例如stm32f103-blue-pill就是一个基于Cortex-M3的流行BSP。切换BSP目录cd bsp/stm32f103-blue-pill。修改编译脚本检查BSP目录下的rtconfig.py文件确保交叉编译工具链前缀EXEC_PATH和PREFIX设置正确指向我们的arm-none-eabi-工具链。调整链接脚本M3的链接脚本通常是.lds或.ld文件与A9的完全不同它定义了内存布局Flash起始地址、大小RAM起始地址、大小。必须根据你手中开发板的芯片手册进行修改。这是最容易出错的地方之一地址设错直接导致程序无法运行。实现板级初始化检查board.c文件确保时钟初始化SystemInit、堆栈初始化、以及之前提到的_sbrk、_write等桩函数都正确实现并且是针对M3核心的。6.3 调试器的连接与配置如果使用OpenOCD你需要编写对应的配置文件.cfg文件指定调试器类型如stlink-v2, jlink和目标芯片型号。在Fedora 12上运行OpenOCD时可能会因为USB驱动权限问题无法访问调试器需要将用户加入plugdev组或者创建udev规则。一个简单的OpenOCD启动命令示例openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg然后在另一个终端用GDB连接OpenOCD的3333端口进行调试arm-none-eabi-gdb rtthread.elf (gdb) target remote localhost:33337. 总结与经验之谈在Fedora 12这样陈旧的系统上完成RT-Thread的编译和调试环境搭建更像是一次“生存训练”。整个过程的核心矛盾在于现代开源软件工具链、构建工具的生态往往基于较新的库而老旧系统无法提供。我的策略总结起来就是“对外隔离对内升级”。软件源是生命线首先要解决yum可用的问题存档源是关键。这比一个个去手动找rpm包要高效得多。工具链优先选择静态或低依赖版本对于交叉编译工具链优先寻找官方提供的、GLIBC要求低的预编译版本或者静态链接的版本。从源码编译工具链是最后的手段因为其依赖树可能非常深。Python环境局部构建不要动系统的Python。在用户目录下从源码编译一个较新的Python 2.7并用altinstall安装专供scons等构建工具使用这是最干净、最安全的方式。QEMU是快速验证的利器在拿到真实硬件前利用QEMU BSP可以快速验证编译工具链、RT-Thread内核配置是否正常极大提高了开发效率。调试工具的选择在老旧系统上J-Link的静态二进制工具链通常是兼容性最好的选择。如果只能用OpenOCD要有心理准备应对其复杂的依赖编译。耐心阅读错误信息老系统上的错误信息往往更“原始”但也更直接。编译错误、链接错误、动态库错误都要仔细阅读它们通常指明了缺失的库、不兼容的版本或未定义的符号。善用ldd、objdump、readelf等工具进行分析。最后这次实践也让我反思对于有条件的团队使用Docker等容器技术将开发环境标准化、版本化是多么重要的一件事。它可以彻底消除“在我机器上是好的”这类问题。但对于那些必须面对历史遗留系统的开发者而言掌握这种在“荒原”上搭建开发环境的能力依然是一项宝贵的技能。每一次解决依赖冲突、版本不匹配的过程都是对系统底层理解的一次加深。当你最终看到那个小小的RT-Thread内核在QEMU或真实硬件上成功启动并打印出熟悉的LOGO时那种成就感或许就是驱动我们不断折腾的动力吧。