免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

Win10下FMT飞控编译环境搭建:交叉编译工具链与RT-Thread env实战

Win10下FMT飞控编译环境搭建:交叉编译工具链与RT-Thread env实战 1. 项目概述先说结论FMTFly Mission Toolkit基于RT-Thread实时操作系统的开源飞控系统在Win10下的编译环境搭建本质上就是三件事——装好交叉编译工具链、配好依赖环境、跑通构建脚本。这三件事做完你就能把FMT的固件从源码变成能烧进飞控板子的bin文件。FMT是啥简单说它是一套把RT-Thread这种实时操作系统和飞控算法深度融合的开源方案。和传统的裸机飞控不同FMT把系统内核、驱动层、飞行控制算法做成了模块化架构开发者可以直接在RT-Thread的生态里做二次开发。这几年玩开源飞控的朋友应该都听过它因为它在代码结构清晰度、文档完整度和社区活跃度上确实比不少老牌飞控项目做得更好。这篇文章就是写给想在Windows下折腾FMT编译的开发者看的。无论你是刚接触RT-Thread生态的新手还是从PX4、ArduPilot转过来的老手只要你需要在Win10上把FMT源码变成可烧录的固件这篇实操笔记就能派上用场。我会把从零开始的环境配置、编译流程、常见报错和排查思路全部捋一遍尽量少废话直接给你能照做的步骤。2. 整体设计思路为什么在Win10下编译FMT会让人头疼2.1 交叉编译的本质你的电脑和目标板不是一回事先搞清楚一个基本概念FMT的飞控固件跑在ARM Cortex-M系列芯片上比如STM32F4、STM32F7而你用的是x86架构的Windows电脑。你的电脑没法直接运行ARM指令集的程序所以需要一套工具链——交叉编译器——在x86上生成ARM能跑的机器码。这个交叉编译的过程就是整个环境搭建最核心的部分。很多新手卡住就是因为没理解编译和普通软件开发的区别。你在Win10上装个Visual Studio编译Windows程序那是本机编译但FMT固件是在你的电脑上编译出目标飞控硬件能执行的代码这个代码没法在你的电脑上跑只能烧到飞控板上跑。FMT官方其实提供了比较完善的构建工具它基于RT-Thread的env环境也就是RT-Thread官方推荐的命令行构建环境配合arm-none-eabi-gcc编译器还有python脚本做自动化和配置生成。这套东西在Linux下比较顺畅但在Windows下会有不少隐形坑——路径分隔符、环境变量、依赖下载工具的兼容性处处都可能出问题。2.2 为什么选择RT-Thread env而不是其他方案FMT选择基于RT-Thread构建意味着编译环境也天然倾向于RT-Thread的整套工具链。RT-Thread官方为Windows开发者提供了一套叫env的环境它本质上是一个预先配置好的命令行环境里面集成了Python用于运行构建脚本和配置工具SConsRT-Thread的默认构建系统一些辅助工具比如Git、编译器调用接口等为什么不用Makefile或CMake因为RT-Thread的构建系统是SCons它用Python脚本描述构建规则配置机制非常灵活适合嵌入式这种需要频繁裁剪组件和配置宏的玩法。FMT的项目你把源码下下来目录里会有SConscript这类文件就是给SCons用的。需要强调的是env环境本身不算一个编译器它只是把编译器、脚本工具、依赖打包到了一个隔离的Shell里。真正的编译动作最后还是要落到arm-none-eabi-gcc这棵树上。这就是为什么你在安装env之后还得手动添加交叉编译器路径或者把它放到env能识别的位置。2.3 Win10特有的坑安全中心和路径问题在Linux下装环境最多就是缺什么装什么在Win10下很多时候是明明按步骤做了依然莫名报错。我总结了两类高频干扰源第一类Windows Defender实时保护。交叉编译工具链里的很多可执行文件比如make、python.exe、arm-none-eabi-gcc.exe会被Defender误报尤其在解压工具链和运行构建脚本时动辄被隔离。这是最坑的环节之一很多人编译到一半突然报找不到xxx.exe十有八九就是被杀毒软件隔离了。第二类中文路径和空格。如果你把FMT源码解压到C:\Users\张三\Desktop\FMT代码\这种带中文和空格的路径下SCons在解析路径时就会出各种莫名其妙的错。我记得早期版本还会在生成链接脚本时直接崩溃。所以第一课就是装到一个纯英文、不带空格的路径下。3. 核心细节解析编译前的准备工作3.1 Windows 10系统的环境要求与配置先说系统本身。就我的实测经验Win10的版本其实没有太多硬性要求1809以上的长期支持版基本都没问题。但有几个系统级配置还是建议先做好关闭实时病毒防护至少在你编译的那几个小时内。不是让你永久关闭安全中心而是把项目目录、工具链目录加入排除项或者临时关闭实时保护。关于具体在哪里加白名单后面问题排查部分我会详细讲。开启开发者模式。在设置→更新和安全→开发者选项里打开它。这个操作会允许本地安装未签名的应用包并且避免一些Windows对符号链接、命令行工具的限制。确保Windows PowerShell执行策略允许运行脚本。因为env环境里很多脚本是.bat或.ps1默认策略太严格会导致脚本无法执行。把执行策略设为RemoteSigned一键搞定。这些看起来和专业编译无关但它们是Win10上环境不稳定或者说反人类的根源。不少人在第一步就放弃了不是技术门槛而是这些细碎的系统设置没搞定。3.2 工具链整体选型与版本匹配FMT官方文档推荐的编译工具链核心是arm-none-eabi-gcc。但这里有个非常关键的点版本不能乱选。如果你用的FMT版本比较新比如FMT 5.x以上建议直接使用FMT官方预置的编译器版本。FMT在构建时会对编译器版本做检查版本过于老旧会报错。反过来说太新的编译器也可能遇到兼容性问题比如早期FMT不支持arm-none-eabi-gcc 10以上的默认链接选项。我在实际编译时用的组合是arm-none-eabi-gcc 9.3.1GNU Arm Embedded ToolchainPython 3.8env环境内置的一般是这个版本SCons 3.xRT-Thread env自带Git for Windows用于拉取子模块这个组合在FMT 5.3和FMT 6.0上都验证过稳定不折腾。3.3 下载FMT源码并拉取子模块FMT项目不是一个单仓库它依赖大量子模块也就是第三方库比如FMT-Firmware主仓库一堆驱动库和算法库如果你只git clone主仓库不拉子模块编译时肯定报头文件缺失。这是最常见的初始报错。正确姿势是git clone --recursive https://github.com/Firmament-Autopilot/FMT-Firmware.git如果你已经克隆了仓库但没带--recursive进到仓库根目录后执行git submodule update --init --recursive这一步能不能顺利跑通取决于你的网络环境。GitHub在国内的访问速度有时候很不稳定子模块如果超过几十个就很容易中断。我的经验是如果网络不好可以给Git配置代理注意是正常合规的网络优化手段或者多试几次。子模块拉取中断后再次执行git submodule update --init --recursive即可断点续传不会从头再来。3.4 RT-Thread env环境的安装步骤RT-Thread env是一个绿色软件下载后解压就行不需要安装。它的目录结构大致是env.bat启动环境的总入口tools/内含python、git等工具packages/RT-Thread的包管理器目录你把FMT源码准备好之后进入FMT-Firmware根目录在文件管理器地址栏输入cmd回车打开命令行然后执行env环境的启动脚本通常是把env.bat所在的路径加到PATH里或者直接把env.bat拖进cmd窗口运行。更省事的方式是进入env目录双击set_env.bat或env.bat弹出的命令行窗口就自带环境变量了。启动后用cd命令切换到FMT源码目录。不要用Windows资源管理器拖拽的方式切目录因为cmd对拖拽路径的转义有时会出问题。此时输入scons --version如果显示出版本号说明构建系统已生效。4. 实操过程从零编译FMT固件4.1 目标板与编译目标的确认FMT支持很多飞控硬件平台比如Pixhawk系列、CUAV系列、以及部分自研板子。编译前你需要知道自己要编译哪个目标target这直接决定了构建脚本会选哪份链接脚本和板级配置。以Pixhawk 4FMUv5为例一般在FMT源码里会有target或board相关的目录FMT提供的编译命令通常是这样的形式scons -j8 --targetfmu-v5或者在某些版本中是先通过menuconfig选择再用特定命令编译。具体命令可以看项目README或Makefile里写的示例。有个小建议第一次编译建议用单线程或双线程-j2跑目的是看清整个构建过程中有没有报错。全速编译比如-j8在出错时瞬间刷屏新手根本来不及判断是哪个环节崩了。确认无误后再开多线程提速。4.2 编译命令与常见参数说明编译的参数拆解一下其实很好理解scons调用构建系统执行构建-j8启用8个并行编译任务能显著缩短编译时间当然前提是CPU够强--targetfmu-v5指定目标硬件配置FMT还支持一些辅助参数比如生成编译数据库、开启调试信息等但新手阶段不要动这些先编译出默认固件。我第一次编译Pixhawk 4的目标时总耗时大概在15到20分钟i7-10750H处理器16GB内存机械硬盘。如果换成SSD编译时间还能再缩短一些。这个速度在嵌入式项目里算中等因为要编译RT-Thread内核、设备驱动框架、飞控算法、Mavlink通信库等加起来是相当可观的代码量。4.3 编译过程中的正常现象与危险信号编译过程中会产生大量输出关键要看两类信号正常现象Compiling xxx.c ...大量源文件依次编译。Generating xxx.h说明有头文件在构建过程中自动生成FMT的配置系统会生成一些配置文件。Linking最后的链接环节时间往往较长是CPU高负载阶段。危险信号error: xxx.h: No such file or directory头文件缺失通常是子模块问题。undefined reference to xxx链接期错误一般是库没编进去或编译宏配置不一致。Permission denied文件被占用或权限不足在Win10下多见于杀毒软件锁文件。4.4 第一次编译失败后的日志分析方法万变不离其宗编译失败先看第一条真正的error:不要看warning不要看中间段的重复提示。很多人一看到屏幕上飘着一堆warning就开始慌其实warning大部分不影响编译结果顶多意味着一处不规范代码。找到第一条error后把报错信息复制出来搜索大概率能找到对应的Issue讨论。FMT的GitHub Issue区和RT-Thread社区是首选。当场搜索比你盲改代码靠谱一万倍。4.5 编译产出物bin文件和elf文件在哪里编译成功后输出文件一般在build目录下具体路径看FMT版本的目录设计。通常会有.elf文件带调试信息的可执行文件用于调试器连接查看源码。.bin文件纯二进制固件用于烧录。去飞控地面站比如QGC里刷固件选的是bin文件。如果要用J-Link或ST-Link在线调试加载的是elf文件。我把FMT的编译产出物搞清楚之后后续烧录就顺利多了。之前总是担心编译成功了但文件不对其实名目就那么几个弄清楚自己去哪取文件就行。5. 常见问题与排查技巧实录5.1 编译时提示找不到scons或不是内部或外部命令这个报错基本可以断定是env环境没有正确启动或者env的tools目录没加入PATH。排查思路确认你是在env环境启动后的cmd窗口里执行的命令。手动试一下python --version如果连python都不是内部命令说明环境变量没加载成功需要重新执行env的启动脚本。有杀毒软件的情况下也有可能python相关文件被隔离导致命令名存在但实际执行文件已被移走。这类问题我遇到过好几次最后基本都是杀毒软件误杀。把整个env目录和FMT源码目录加入Defender排除列表一劳永逸。5.2 Win10安全中心误删编译器文件如何正确添加排除项这是我说的Win10编译最大的坑之一。症状非常典型编译到中途提示找不到某个编译器内部可执行文件去工具链目录一看某些exe文件真的不见了——就是被实时保护当成威胁删掉的。解决办法不是关闭Defender虽然临时关也行但不彻底、不推荐而是添加排除项。具体路径是打开Windows安全中心进入病毒和威胁防护点击管理设置滚动到排除项点击添加或删除排除项把FMT源码目录、env工具目录、交叉编译器目录都加进去。顺手把build输出目录也加上因为编译产生的临时文件有时也会被扫描拖慢速度。添加排除项后再重新解压一份工具链如果你之前发现文件被删了一定要重新解压因为被删除的文件不会自己恢复。5.3 子模块拉取失败导致的头文件缺失表现就是编译时报出一堆No such file or directory尤其是rtthread.h这类RT-Thread相关的头文件找不到。这种情况大部分是git submodule update没有成功完成或者网络中断了几次很多依赖库压根就没拉下来。排查方法git submodule status这个命令会列出所有子模块的当前状态。正常的子模块前面是一个号显示一个commit哈希如果某一行前面出现了-号未初始化或者号后是零串读取失败那对应的子模块就有问题。修复手段是重新执行git submodule update --init --recursive必要时先清掉未初始化的子模块再重拉git submodule deinit -f --all git submodule update --init --recursive这个命令组合会把子模块彻底重置重新拉取。代价是要重新下载一遍但状态会干净得多。5.4 编译超时或系统卡死的资源占用问题如果你用-j8或者更高的并行度在配置较弱的电脑上编译可能会出现内存吃满、编译器进程被系统杀掉甚至整个Windows卡到鼠标都动不了的现象。这不算FMT的bug纯粹是资源问题。解决思路很简单降低并行度。改成-j2或者-j4虽然时间长一点但进度可控。另外编译时关掉Chrome这类占用内存大户尤其是开着几十个网页标签的情况内存很容易爆。我个人的建议是8GB内存的机器老老实实用-j416GB内存可以尝试-j8低于8GB内存-j2最稳。5.5 编译报错提示Python版本不兼容FMT的构建脚本对Python版本其实有一定要求。如果env自带的Python和你系统里自己装的Python冲突比如PATH里系统Python优先级更高导致scons调用了一个过高版本的Python就会报出各种莫名其妙的语法错误或依赖缺失。处理办法在env环境下先看python --version确认版本是3.8左右具体看FMT文档要求。如果版本不对把env/bin或tools目录放到系统PATH最前面确保它优先于系统Python。干脆卸载系统里多余的非必要Python版本减少干扰。说到底就是让整个构建环境保持封闭和一致不要混着用。5.6 编译成功后无法烧录的排查方向编译生成了bin文件但烧录到飞控板后无法启动或行为异常——这种现象其实不完全是编译环境的问题但也值得展开说一下排查思路。先确认你烧录的bin文件和你选的目标板是否匹配。Pixhawk 4的固件烧到Pixhawk 6上肯定跑不起来设备的存储映射都不一样启动过程直接卡住算轻的严重情况可能影响硬件。飞控端的bootloader是否正常、bootloader与app的匹配性也是重点由于bootloader版本过老、不认识新格式的app导致启动不成功的情况也很常见。如果你只是想快速验证固件有没有编译对可以先用QGC地面站刷官方对应版本的固件确认板子本身没问题再刷自己编译的固件。把硬件问题和编译问题分离能省掉很多无效的排查时间。6. 编译速度优化与进阶玩法6.1 增量编译的要点改一处代码后如何快速重新编译嵌入式项目第一次编译慢这没办法但后续改动后的编译完全可以快很多。关键是要理解SCons的增量编译机制。SCons会对源文件和依赖关系做状态跟踪。你在改完代码后直接在同样的命令下再跑一次scons它只会重新编译受影响的部分。这个机制默认开启不用额外配置。但有个坑如果你改了某个被大量文件引用的头文件比如全局的配置头文件那所有引用它的源文件都要重新编译速度还是会慢下来。这是正常的依赖传导没什么好办法只能耐心等。另一个拖慢增量编译的隐患是杀毒软件实时扫描会在每次构建时重新检查所有中间文件导致增量编译被拖成接近全量编译的速度。这就是为什么前面强调要把构建目录加入排除项——它对编译速度的影响比你想象的大得多。6.2 使用ccache加速重复编译如果你要频繁进行全量编译比如改了构建配置、清理后再编每次十分钟起步确实很烦。Linux下常用的ccache工具在Windows下也有对应版本它能把编译过的对象文件缓存起来下次全量编译时只要缓存没失效就直接从缓存读取而不是重新跑编译器。配置方法不复杂下载Windows版ccache网上有release包。把ccache路径加入PATH。找到FMT构建配置中编译器入口的位置用ccache包一层ccache arm-none-eabi-gcc。实际上RT-Thread env的SCons配置里就有ccache的开启选项只需要在构建命令中加入相应参数或者修改配置脚本就能启用。启用后第一次全量编译不会变快因为缓存是空的但第二次及以后无论clean多少次再全量编速度都可能快30%到50%具体取决于CPU和磁盘的差异。6.3 从Flash烧录到在线调试环境搭建的额外收益一旦编译环境跑通你其实就等于拥有了一个完整的嵌入式开发工作台。配合ST-Link或J-Link调试器你可以在VS Code或者Keil里直接加载编译生成的elf文件进行源码级调试实时查看RT-Thread的任务调度状态、变量值、栈使用情况等。FMT基于RT-Thread这意味着你在调试时可以在VS Code中打断点观察线程间调度逻辑。查看RT-Thread的list_thread输出确认各任务的栈使用率。配合FMT的日志系统把飞控状态数据导出来分析。这个工作流的搭建本质上就是交叉编译工具链调试器驱动的整合。没有编译环境后面这些调试玩法都无从谈起。7. 实战建议给不同基础的开发者7.1 嵌入式新手如何快速迈过编译这道坎如果你是第一次接触嵌入式开发甚至第一次接触Linux命令行风格的操作我的建议很简单只按官方文档的步骤来不要擅自修改任何配置。你可能觉得很厉害的操作往往会给环境带来一堆不必要的变数。遇到报错就搜索报错信息搜不到就先静下心看有没有更早的error。不要一报错就去重装整个环境那是最低效的解决方式。多数编译环境的报错本质上是路径没配对、依赖没拉全、编译器版本不对翻来覆去就那么几个原因。另外强烈建议装一个Everything文件搜索工具或者Windows自带搜索跑一遍磁盘索引。排查头文件缺失问题时你需要快速确认某个头文件到底在不在工具链的某个目录下这种搜索可以说是救命级的效率提升。7.2 有Linux经验的开发者如何更快适应Win10环境你可能有在Ubuntu上编译FMT的经验转战Win10后发现有些地方很反直觉。这里有几个具体的调整点换行符。Git在Windows下会把LF自动转成CRLF某些脚本文件在CRLF下可能行为异常。FMT仓库里通常有.gitattributes来控制换行符处理但保险起见建议在克隆仓库前设置git config --global core.autocrlf input保持LF格式。路径分隔符。SCons在Windows下通常能自动处理/和\但某些第三方工具可能只认识一种。遇到路径相关的诡异报错时检查一下配置脚本里有没有硬编码的路径分隔符。命令行行为。cmd和PowerShell在处理特殊字符、转义符上素有差异。建议全程用env自带的cmd窗口不要在PowerShell里折腾省得被PowerShell的$和引号规则误伤。7.3 从Keil和IAR转过来的开发者需要调整的思维很多人飞控开发的起点是Keil或IAR这两个IDE的编译过程和命令行构建差别很大。你要是习惯在IDE里点一个Build按钮就完事来用FMT这种命令行式构建最需要适应的就是一切不可见。在IDE里编译器路径、头文件搜索路径、宏定义都由IDE帮你管理你不需要关心。但在FMT的命令行构建中这些全部由SCons脚本和配置文件决定你必须建立构建脚本决定一切的认知。出了问题要学会看脚本、查变量而不是只盯着报错面板。好消息是RT-Thread env环境也提供基于menuconfig的可视化配置方式类似于内核配置界面在里面你可以直观地开关组件、调整参数选中和取消选中就用空格切换配置完成后保存然后回到命令行执行构建。这种配置界面命令行构建的组合实际上是比Keil的项目管理更灵活的方案——因为任何改动都可以通过版本控制管理团队协作时不会被IDE的工程文件格式绑架。8. 扩展思考FMT编译环境的价值不止于固件编译当你把Win10下的FMT编译环境搭建完成你收获的不仅仅是能编译固件这一个能力。更重要的是你打通了一套完整的嵌入式开发工具链——从源码管理、子模块更新、配置裁剪、编译构建到产出物管理和后续调试烧录一整条链路都是通的。基于这套环境你可以深度定制FMT功能。修改飞控算法、增加传感器驱动、变更系统组件裁剪策略这些都需要重新编译固件。把自己的板子适配进FMT生态。FMT的架构允许加入新的板级配置通过修改板级目录下的配置文件和链接脚本就能让FMT跑在自己的硬件上。这一步的前提条件就是你有一个能正常工作的编译环境。和企业级的CI/CD接轨。编译环境可以搬到GitHub Actions或自建的持续集成服务器上每次推送代码自动编译、自动产出固件人工只负责烧录验证。我个人在这套环境上做过的最大改动是把FMT移植到一块自研的STM32H750板子上整个适配过程不过两三天。如果没有顺手好用的编译环境光是反复全量编译验证就得耗掉大量时间。环境这东西润物细无声打好基础之后后续所有开发都顺了。最后再分享一个小经验环境搭建的过程中记录你自己执行过的每一步命令和当时的报错情况。不要觉得麻烦这些记录在后续升级FMT版本、迁移电脑、换工具链版本时价值巨大。我在重装系统后重建编译环境时靠的就是自己之前记录的笔记半小时就复原了一下完整可用的编译链而第一次搭时我折腾了整整一天半。这就是做笔记的复利效应。
返回列表