飞控计算机的代码到底跑在什么操作系统上,这个问题几乎每次和团队讨论新机型都会被翻出来。说实话,如果你只做一个玩具级的自稳小飞机,裸机主循环也不是不能用;一旦飞行器要同时处理 IMU 采样、多传感器融合、控制律解算、执行机构刷新、遥控链路回传和故障保护,没有一个能明确调度顺序、拥有时间确定性的硬实时操作系统,代码迟早会因为抢资源而乱掉。这篇内容会围绕飞控计算机常用的几款硬实时操作系统展开,包括它们各自的市场定位、调度机制差异、任务划分思路、调试跑飞和抖动的实际手段,最后再给一份选型建议。适合正在选型、刚接手飞控软件开发,或者被调度抖动折磨过一段时间的嵌入式工程师参考。
先说一个总的判断:飞控行业的技术栈看起来百花齐放,但底层逻辑其实非常统一,大家都想让关键的姿态控制路径在任何情况下都能在固定时间内完成。谁在这个目标上掉链子,谁就会被团队换掉。下面我就从需求侧开始,一层层把这件事讲透。
1. 飞控对实时性的真实需求:硬实时到底硬在哪
1.1 硬实时和软实时根本不是同一件事
很多刚接触飞控的人会把“实时”理解为“反应快”,这其实是理解上的偏差。实时系统追求的核心指标是“在确定的时间之前完成”,而不是“尽快完成”。普通电脑上的操作系统追求平均性能,偶尔卡一下,视频软件缓冲一下,用户最多觉得体验不好,这叫软实时。飞控不一样,姿态控制任务如果没在采样周期内算出新输出,飞行器姿态就会继续按旧输出飞行,一个周期还好,连续几个周期超时,姿态就会发散到不可收拾。
硬实时系统最严格的定义,是每次任务执行都必须满足截止时间,不能拿“大概率满足”来凑合。这也是飞控和高端机器人、工业运动控制最像的地方。你去看很多飞控团队的任务清单,第一行永远是传感器采集,第二行永远是姿态解算与控制律输出,后面才轮到导航、遥测、日志。这种优先级排列不是习惯问题,而是时间约束决定的。控制任务的截止时间和它的运行周期相同,5ms 的周期,就要求在 5ms 内完成,哪怕 0.5ms 的滞后都会影响控制相位,多次滞后就会变成可观测的振荡。
打个比方,硬实时就像食堂大师傅必须在每个窗口期结束前把菜端出来,来晚的学生没饭吃;软实时就像外卖平台,送晚十分钟可以赔券,但饭还是会送到。飞控是前者,错过一个节拍,不是赔钱能解决的。
1.2 飞控任务链的时序预算:谁在占用你的毫秒
我们以典型的全自主飞行器为例,拆一下飞控内部的时序预算。姿态和位置控制要求最高,通常按 250Hz 到 1000Hz 的速率跑;IMU 和气压、磁力计等传感器的读取频率更高,原始数据往往到 1kHz 以上;执行机构输出刷新也基本跟着控制率走,GPU 电机、舵机、倾转机构全部要吃这个节奏。再往下,导航滤波、路径规划、任务管理通常在 50Hz 到 100Hz 的量级,通信链路、日志存储、地面站心跳这类任务分布在 1Hz 到 50Hz。这些任务共享同一个 CPU,没有一个可抢占的调度的正循环,任何一个中速任务卡住,都可能在关键时间段内把高速任务饿死。
飞控设计里有个概念叫“时序预算”,意思是任务频繁发生的卡顿不能超过总 CPU 时间的某个比例。经验上控制环路的 CPU 占用率最好控制在 40% 到 50% 以下,剩下的资源要留给中断、随机突发和高峰期的调度开销。你可以在任务里加一个实时时钟时间戳,把每个任务的“最坏执行时间”记录下来,连续跑几十个小时再统计,一旦发现某个控制任务的最大执行时间超过周期的一半,就得警惕了。这个统计不是靠肉眼观察,而是要从代码层面把关键节点打上时间戳。
2. 主流硬实时操作系统盘点:从商业到开源的取舍
2.1 有认证底子的商业内核:VxWorks 这类系统为何长盛不衰
说飞控操作系统,必须先说商业市场的老将 VxWorks。它在航空电子、导弹、运载火箭这些安全关键场景里有非常深的积累,很多有人驾驶飞机和大型无人机飞控都跑在它上面。VxWorks 的硬实时能力来自抢占式优先级调度、确定性的内核响应时间、以及完善的异常隔离机制。它还支持内存管理单元 MMU,可以让不同任务运行在不同地址空间,一个任务崩溃不至于把整个飞控拖走。这个特性在大型系统里非常重要,因为飞控软件越写越大,团队协作越频繁,代码错误越难通过静态检查完全排除。
VxWorks 的价值不只在内核本身,更在于它配套的开发工具链和认证证据。飞控行业如果要走适航审定,需要操作系统供应商提供生命周期数据、测试报告、覆盖率分析这类东西,这些很难靠开源代码临时拼出来。商业内核价格不低,学习周期也长,但对产品要面向安全级运行场景的团队来说,省下来的认证时间和排错成本往往比授权费更有价值。很多团队的做法是先用开源系统把算法验证透,产品阶段再迁移到商业认证内核上。
2.2 开源轻量派:FreeRTOS 和 µC/OS 为什么适合小型飞控
开源阵营里,FreeRTOS 的覆盖率最高,几乎所有主流的 MCU 都有移植支持。它内核精简,核心调度机制就是一个优先级抢占 + 时间片轮转,队列、信号量、事件组、软件定时器都有,API 简单,学习成本低。飞控小团队用 FreeRTOS 做原型验证,优点非常明显:代码量少、占 RAM 小、开发者很容易在几天内上手,而且问题代码在社区里一搜就有大量讨论。
µC/OS 是另一条稳健路线,尤其在 µC/OS-III 之后,它引入了可剥夺型的内核锁、任务级时间戳和内核对象可视化。很多人觉得 µC/OS 和 FreeRTOS 功能高度重叠,但对老工程师来说,µC/OS 的代码结构更规整,教学文档详细,调试手段也更成熟。它的授权模式早期偏商业,后来对很多教学和评估场景开放,这也让它在航空航天、医疗器械领域积累了不少案例。选择 FreeRTOS 还是 µC/OS,通常不是性能差异决定的,而是团队习惯和已有代码库决定的。
这两个系统本身都不带 MMU,一般没有进程级保护,所以任务与任务之间的隔离性弱。换句话说,任何一个任务写越界,都可能把另一个任务的数据改坏。飞控里解决这个问题主要靠在工程层面加看门狗、静态分析、栈监测和代码审查,而不是指望内核替你兜底。小飞控任务少还好说,一旦任务数量上到二十个以上,隔离性问题会被放大,这也是很多产品级团队后来转向带空间隔离系统的重要原因。
2.3 航天基因浓厚的 RTEMS
RTEMS 是一个老牌开源实时内核,最早脱胎于导弹和航天领域的需求,所以它的设计目标一上来就是硬实时、可裁剪、支持多处理器和丰富的外设驱动框架。它的 API 比 FreeRTOS 更复杂,提供经典的 POSIX 线程接口也有自己的经典 RTEMS 接口。很多人第一次看 RTEMS,会觉得文档和代码风格非常“老派”,但它长期经受太空高可靠场景的检验,稳定性和调度确定性在开源内核里是第一梯队。
RTEMS 的优势还在于它支持多核,并且有一部分内核对象具备多核一致性处理能力。飞行控制这种既要求实时性又要长期无人值守的场景,和 RTEMS 的气质天然匹配。它的问题在于社区规模不如 FreeRTOS 大,驱动移植需要更多自己动手,年轻工程师上手慢。如果你的团队有驱动开发能力,并且希望开源路线也能支撑高可靠需求,RTEMS 值得认真评估。
2.4 NuttX:被飞控社区“顺手”选中的 POSIX 风格 RTOS
说飞控操作系统,不能不提 NuttX。很多开源飞控平台跑的就是 NuttX,它在飞控圈的热度并不比 FreeRTOS 低。NuttX 最吸引人的地方是 POSIX 兼容性,pthread、文件系统、网络协议栈、标准设备驱动模型全都以类 Linux 方式提供。这意味着飞控上层控制算法在 NuttX 上写完后,未来想移植到 Linux 地面站、仿真机或者更大的嵌入式 Linux 板卡上,代码改动成本极低。
NuttX 的调度也是基于优先级的抢占式调度,定时器精度可以配置,飞控需要的亚毫秒级周期控制完全能跑起来。它还提供比较完整的任务栈检查、消息队列、命名信号量等机制,非常贴近传统嵌入式系统工程师的使用习惯。老实说,很多飞控团队选择 NuttX 不一定因为它比 FreeRTOS“更实时”,而是因为它生态里已经有飞控的设备驱动、外设抽象和大量现成算法模块,直接复用比自己重新造轮子效率高得多。工程选型很多时候不是选最优,而是选阻力最小。
2.5 裸机主循环到底算不算 RTOS
答案是不算。裸机主循环加上定时器中断,能实现非常轻量的任务调度,但这种机制没有完整的任务管理、优先级抢占、同步原语和内核管理能力。它本质上是一个协作式调度器,最典型的结构是 while(1) 里顺序执行几个函数,配合中断标志位。对极其简单的自稳飞行器,裸机方案确实够用,任务少、逻辑短、外设单,中断延迟也可以控制在很低的水平。
但一旦任务数量增多,裸机方案的时间确定性会迅速恶化。某个任务里写了个等待标志的死循环,或者某个中断服务函数里做了耗时操作,其他任务全部受影响,这种系统根本没有“优先级”的概念,高优先级的控制逻辑也被迫等着低优先级任务完成。现代飞控,哪怕是低成本竞速无人机,也越来越多地引入 FreeRTOS 或类似内核,原因就是想在源头上把任务调度秩序建立起来。
3. 硬实时内核背后的调度机制与避坑要点
3.1 抢占式调度与中断响应:确定性从哪里来
硬实时内核最核心的能力是抢占式调度。系统中每个任务有固定优先级,内核保证任何时刻,CPU 分配给定就绪队列里最高优先级的任务。当高优先级任务就绪时,即使低优先级任务正在执行,内核也会立刻打断它,保存现场,切至高优先级任务。这个过程看似简单,但背后的中断响应和上下文切换时间必须是可预测的。
中断响应链路是:外设触发中断到进入中断服务函数需要若干时钟周期,中断服务函数处理完以后再判断是否唤醒内核对任务进行调度。优秀飞控系统的设计会把最关键的控制算法放到最高优先级任务或定时器中断里,而把数据记录、网络通信放到较低优先级。这样即使遥测任务发生异常超时,也不会影响控制环的周期。
不过要提醒一句,抢占式调度只有在所有任务都遵守同一套“优先级纪律”时才有意义。如果某个低优先级任务在临界区里关了中断,或者手持一个高优先级任务需要的互斥锁不放,那高优先级任务照样会等它。真正的硬实时保证,需要内核的调度机制和任务代码的运行纪律共同完成,缺一个都不行。
3.2 优先级反转、继承与天花板协议:抖动排查绕不开的坎
优先级反转是飞控调试里最常见的隐形杀手,也是很多“任务超时但CPU占用不高”问题的真正源头。经典场景是:低优先级任务 A 拿到了一个互斥锁,正在访问共享传感器数据,高优先级任务 C 来了,需要同一个锁,只能阻塞等待;此时优先级中等的任务 B 被唤醒,抢占掉任务 A,CPU 跑到 B 上去。结果就是,C 明明优先级最高,却要等到 A 和 B 都运行完才能继续。C 是姿态控制任务的话,这种等待会导致明显的控制抖动。
解决优先级反转有两条路:优先级继承和优先级天花板协议。优先级继承是指当高优先级任务等待低优先级任务持有的锁时,内核临时把低优先级任务的优先级抬到与高优先级任务相同,从而避免中等优先级任务插队。优先级天花板协议则是规定每个互斥锁都有一个“天花板优先级”,任何任务持有该锁时,优先级都临时提高到天花板级别。这两种方法各有取舍,但都比“裸互斥锁”靠谱得多。
飞控里的大坑在于,共享资源往往不止一个锁,而是分布在多个模块里。比如姿态控制任务访问 IMU 原始缓冲,导航任务也在读同一块内存,日志任务偶尔也在拷贝,三个锁层层嵌套,规则稍微乱一点就会死锁。建议在系统设计早期就画一张共享资源矩阵,明确每个互斥量保护哪些数据,谁可以嵌套加锁,谁必须用无锁拷贝,这比后来反复看 trace 有用得多。
3.3 时间确定性怎么量化:WCRT、中断延迟与抖动测量
量化实时性,不能只靠感觉。硬实时系统里有几个关键指标需要经常测量:最坏情况响应时间、中断延迟、调度切换抖动和执行时间分布。最坏情况响应时间不只是任务代码本身,还包括就绪等待、锁等待、内核调度延迟和中断抢占。在飞控领域,我们更关心的是最大抖动,因为平均延迟低但偶尔一次“尖峰”就可能让控制输出跳变。
测量方法有很多,最简单的做法是在每个任务入口和出口翻转一个 GPIO。这个 GPIO 用示波器或者逻辑分析仪观察,能很直观地看到任务占空比和抖动。更精细的做法是在代码里记录高精度定时器的计数值,计算任务的运行时间和周期偏差。连续跑几千次,把最大值、平均值、标准差打出来。只要发现最大运行时间超过任务周期的 50%,就要认真去做最坏情况分析。
我第一次做这种测量时踩过一个很典型的坑:只在稳定状态下测任务运行时间,忘了触发故障切换和通信链路的突发流量。结果正常飞行时数据特别漂亮,一到遥控链路切换或急加速任务时就现出原型。现在我的习惯是至少覆盖三类工况:巡航、急加速、连续跑链路丢包与重连,只有在这三类工况下都满足时序预算,我才会说这个系统时间确定性达标。
4. 从任务划分到落地实现:设计一个典型飞控软件
4.1 一份典型飞控任务表:优先级不是越高越好
设计飞控软件,第一步就是明确任务划分和周期。下面这个表是一个典型的无人机飞控任务分配,不同机型会有变化,但骨架高度相似:
| 任务名称 | 典型周期 | 优先级 | 说明 |
|---|---|---|---|
| 传感器采集与预处理 | 1kHz | 最高 | IMU、磁力计、气压计原始数据获取与滤波 |
| 姿态解算与控制律 | 500Hz - 1kHz | 很高 | 输出姿态与角速度控制量 |
| 执行机构输出刷新 | 500Hz - 1kHz | 高 | 将控制量映射到舵机、电调并刷新 PWM |
| 导航状态估计 | 50Hz - 200Hz | 中 | 融合 GPS、视觉、气压得到位置速度 |
| 路径规划与任务管理 | 20Hz - 50Hz | 中低 | 航点调度、模式切换、保护逻辑 |
| 遥测与数传 | 10Hz - 50Hz | 低 | 状态上报、指令解析 |
| 日志与调试输出 | 1Hz - 10Hz | 很低 | 记录黑匣子数据,不影响主链路 |
这里有个反直觉的点:传感器采集的优先级往往比姿态解算还高。原因是控制律计算依赖最新传感器数据,如果把采集放到低优先级,万一调度延迟,姿态环拿到的就是过时数据。为了保证相位一致性,采集任务和控制任务之间常常用信号量或队列做“握手”,采集完成一帧数据后立刻释放触发信号,控制任务拿到信号才算完成一次完整解算。
另外,像日志、遥测这类低优先级任务,不要和高优先级控制任务共用同一个大缓冲区,更不要在低优先级任务里阻塞等待串口发送完成。串口波特率再高,一帧数据发送也需要毫秒级时间,控制任务一阻塞就是灾难。通常做法是用 DMA 发送,或者直接设计成“能丢就丢”的实时日志,保证低优先级任务永远不阻塞关键路径。
4.2 任务间通信与共享数据:别在控制环里用普通互斥锁
飞控任务之间通信,最常见的数据形态是周期性更新的传感器状态和控制状态。很多人第一时间想到用互斥锁保护共享结构体,但在高频率任务里,频繁加锁解锁会带来可观的调度开销。更重要的是,如果在高优先级任务内部等待一个低优先级任务释放锁,就容易触发优先级反转。
更常见的工程做法是“单写者单读者 + 双缓冲”,或者“发布者更新 + 订阅者只读最新快照”。以姿态控制任务读取传感器数据为例,传感器采集任务把原始数据写入缓冲区 A,然后原子地更新一个数据就绪标志,姿态控制任务只读取标志和数据快照。这里要特别注意 C 语言里的 volatile 和内存屏障问题,简单标志位可以用无锁读取,但完整结构体必须保证拷贝操作不被分拆成多次可见的写操作。最稳妥的办法是让结构体大小满足单次原子访问宽度,或者通过 memcpy 配合局部快照来读取。
我见过不止一次,有人把整块共享结构体用互斥锁保护,然后抱着“加锁就安全”的心态写代码,结果一次 I2C 总线重试把低优先级任务阻塞了几十毫秒,控制任务全被拖下水。真实飞控场景里,共享数据更新的最佳实践是:高频关键数据走无锁原子更新和快照,低频管理数据走队列或事件,只有必须保护的长临界区才用互斥锁,而且一旦用了就一定要查优先级继承和天花板协议是否开启。
4.3 实测心得:把 1000Hz 姿态环跑到稳定的几个硬约束
要把姿态环稳稳跑在 1000Hz,我总结出几条硬约束,少一条都会在关键时刻咬你一口。
第一,控制路径上不允许任何可能阻塞的调用。串口发送、块设备写入、动态内存分配这些操作,要么放到低优先级任务,要么用预分配缓冲区。我见过一个很典型的案例,控制任务里加了一句调试打印,平时 printf 很快,一旦串口 FIFO 满了,整个 1000Hz 控制环直接掉到 200Hz,飞机在空中就开始抖。把这些调试输出全部替换成环形缓冲 + 低优先级任务落盘之后,问题立刻消失。
第二,高优先级任务要避免在中断上下文做大量浮点运算。很多 MCU 有硬件 FPU 和 FPU 上下文切换,在中断里频繁做浮点计算会显著增加上下文保存开销,间接拉长中断延迟。建议中断服务函数里只做标志设置、数据搬运和队列发送,真正复杂的浮点融合计算放到高优先级任务里做。
第三,数据采样、控制解算、输出刷新要在时序上对齐。最理想的结构是把采样触发放到定时器中断里,控制任务等到数据就绪信号后再启动,控制输出放在周期尾巴统一刷新。这样能保证每一帧控制周期都有新鲜数据,而不会出现采样和控制相位错开的问题。实际做下来,这种结构比“任务各跑各的周期”要稳定一个数量级。
第四,看门狗超时不能随便喂。飞控看门狗要在关键任务周期确认后才喂狗,比如姿态控制任务每 5ms 产生一次心跳。如果把喂狗放在一个独立低优先级任务里,很可能出现控制环已经卡死但狗还在被喂的情况。这种错误在飞行测试中往往表现为“飞机突然失去姿态保持但系统没有复位”,排查起来非常痛苦。
5. 常见问题与排查实录:调试抖动和任务超时的思路
5.1 经典问题速查表:先看现象,再动内核
飞控系统排查,最忌讳上来就改调度参数。我习惯先列一张问题速查表,按表定位:
| 现象 | 常见原因 | 定位手段 | 处理方向 |
|---|---|---|---|
| 控制环周期忽长忽短 | 低优先级任务持有共享锁 | 记录任务入口时间戳,对比周期 | 改用无锁快照或优先级继承 |
| CPU 占用不高但控制任务超时 | 中断服务函数耗时过长 | 测中断到控制任务入口延迟 | 压缩中断逻辑,用队列转普通任务处理 |
| 只有急加速时任务超时 | 突发计算峰值超过预算 | 统计任务运行时间最大最小值 | 把重计算拆到离线或低优先级预处理 |
| 串口日志导致系统卡顿 | 任务外设发送阻塞 | 波形观察任务执行时间 | 改用 DMA 发送或环形缓冲 |
| 看门狗复位原因不明 | 低优先级任务饿死和高优先级任务死循环并存 | 记录复位前任务状态 | 排查高优先级任务的锁等待和循环边界条件 |
这张表列的都是我实际踩过或者同事项目里踩过的坑。每个问题单独拿出来都不复杂,但它们叠加起来,很容易给系统造成“看起来像硬件异常”的假象。排查的关键是先相信软件有时间确定性漏洞,再用数据证明。
5.2 用 GPIO 标记法拷问调度延迟:一次完整的抖动定位过程
分享一次我印象很深的排查过程。某飞控在特定飞行模式下出现轻微滚转振荡,遥测数据看不出规律,飞行轨迹回放也没有明显异常。我们先用示波器把姿态控制任务的执行窗口抓出来,在任务入口置高 GPIO、出口置低 GPIO,波形立刻显示出周期内有一个稳定的 2ms 二次突刺,几乎每次都在同一个位置。这个突刺和姿态解算无关,因为它跑在所有波形中间的固定位置,说明有一个更高优先级的中断或者锁等待插了进来。
顺着时间轴往回查,最后定位到执行机构反馈读取,那里用了一个软件 I2C 驱动,每次读取前等待总线仲裁,仲裁期间屏蔽了调度中断。于是我们在驱动代码里看到了一段明显过长的临界区:整整 2ms。修复方案有两步,先把软件 I2C 换成硬件 I2C 或者 DMA 采样,再把等待仲裁的循环改成超时退出机制。改完以后,控制环抖动从 2ms 直接降到了几十微秒。
这个案例给我印象特别深的地方是,最初整个团队都认为是滤波算法和增益问题,调了两周控制参数都没用。结果用时间标记一量,问题根本不在控制,而在任务被低优先级外设操作“偷走”了时间。所以我一再建议,飞控开发早期就把 GPIO 时间标注法和逻辑分析仪纳入标配工具链,别等到问题出现才临时搭仪表。
5.3 避坑记录:看起来没道理却真实存在的坑
飞控调试几年下来,有几个坑特别容易反复出现,而且都不是大会错误,而是小细节。
动态内存分配是个高发区。FreeRTOS 或 NuttX 里的默认堆管理器,在并发环境下的分配时间是不可控的,可能这次分配只要几微秒,下次就触发碎片整理拖到几十微秒。高优先级控制任务里如果用了 malloc,哪怕只是偶尔用一次,都等于给自己埋雷。我的铁律是:控制路径上只用静态数组和预分配对象,动态分配只允许出现在初始化阶段或者低优先级任务里。
栈溢出也是最容易“薛定谔”的问题。飞控任务栈设小了不会立即崩溃,而是会在任务调用深度增加时偶尔踩踏相邻内存,产生看起来毫无规律的异常。排查方法是在内核里开栈溢出检测,每个任务栈尾部放一组特殊填充值,周期性检查填充值是否被改写。实际运行中,一个控制任务如果调用链很深、程序里有递归或者大形参结构体,栈需求往往比预估多一倍,安全起见按两倍余量设。
还有一个细节,多核飞控平台上的共享内存一致性。很多新一代飞控 MCU 是双核或多核,一个核跑实时控制,另一个核跑视觉识别,两个核之间通过硬件邮箱或共享内存通信。此时需要在关键共享变量上用原子访问和内存屏障,否则 CPU 缓存不一致会让数据在核间“串味”。这个坑比单核时代隐蔽得多,查到最后常常发现不是程序逻辑错,而是跨核缓存同步出了问题。
6. 选型思路与趋势观察
6.1 按产品阶段与团队能力选型,别只抄别人的任务清单
飞控操作系统选型没有一个标准答案。别人能用的方案,放到你的团队和产品上不一定成立,所以要回归自身条件做判断。
如果你是在原型阶段做验证,团队以算法工程师为主,嵌入式功底一般,FreeRTOS 或 NuttX 是最好入口。FreeRTOS 简单,NuttX 的 POSIX 接口则能让你未来迁移到 Linux 仿真环境不费力。如果产品要上量、成本敏感、团队对内核底层有掌控力,那同样可以在开源内核上继续深耕,把驱动、审核、故障注入测试都自己补上。如果产品将来要走适航相关的事故安全流程,那商业认证内核几乎可以说是绕不开的选项。认证并不仅仅是审查代码,而是连同工具链、测试用例、需求追踪矩阵一起交付。这个工作自己从零做,成本远高于直接采购认证方案。
另外,选型时除了看内核本身,还要看外设驱动完备度。有些 RTOS 内核非常漂亮,但目标 MCU 的网络栈、CAN 驱动、SD 卡驱动都要自己写,这会极大拉长项目周期。飞控开发最不值钱的时间不是写算法,而是在外设驱动和底层板级支持上反复折腾。
6.2 多核、分区隔离与认证趋势对选型的潜在影响
飞控系统正在向多核甚至异构计算演进。一个内核负责飞控稳定控制,另一个内核跑视觉、激光建图或者深度学习推理,这样的架构越来越普遍。多核能带来性能和并行能力,却也带来调度资源和共享内存一致性问题。选型时要有意识地询问 OS 的 SMP 支持程度、核间信号能力、以及共享内存同步方案的成熟度。
分区隔离也变得越来越重要。所谓分区,就是把 CPU、内存、外设资源按时间或空间划分为多个完全隔离的域,一个域崩溃不影响另一个域。很多大型航电系统使用的分区调度,正在逐步下沉到中大型无人机和 eVTOL 这类飞行器上。对于这类产品,内核最好支持空间隔离和时间窗口机制,让控制域始终拥有确定性的 CPU 份额,而不会被其他业务域的突发计算挤压。
认证趋势方面,行业对开源内核的接受度也在提高。开源系统并非不能用于安全关键场景,关键是团队有没有能力补齐测试覆盖率、静态分析、故障注入和需求追踪。相比十年前,现在开源生态的开发工具和测试框架已经成熟很多,已经有开源飞控在大量飞行器上长期飞行验证,这些飞行数据本身就是一种可靠性背书。未来选择面会更宽,但内核只是基础,真正的区分度在团队对系统时间的把控能力。
6.3 我踩过坑之后留下的选型原则
我做飞控这么多年,最后留下几条很简单的选型原则,也算个人体会。
第一条,永远不要为了追求“最新最炫”而选择一个社区小、资料少的 RTOS。飞控开发经常要把大量时间花在非算法问题上,系统热度越高,踩坑后的救援资源越充足。第二条,内核再硬,不如任务纪律重要。很多团队以为买了商业 RTOS 就不会有调度问题了,结果代码里锁嵌套、长临界区一样把自己坑惨。再好的内核也只能提供工具,关键路径的设计和执行纪律才是实时性的真正保证。第三条,尽早建立时间测量和 trace 能力。哪怕最廉价的板子,也应该在第一天就接好 GPIO 时间标注和逻辑分析仪,把所有任务的执行时间、周期抖动数据记录下来。很多隐蔽问题,等你看 trace 时已经用肉眼在波形里看见了。
操作系统的选择没有标准答案,但只要每个任务都能在确定时间内完成自己的动作,飞控就能在高空稳稳地飞下去。这也是我写这篇文章时最想强调的一点。