资讯动态

HPM6750非对称双核RISC-V飞控开发实战:PX4移植与电调调试

发布时间:2026/10/26 9:33:28 来源:尧图企业网站定制
1. 从一颗国产芯片说起为什么飞控开始盯上非对称双核飞控这块板子过去十年基本是 STM32 的天下。F4、F7、H7 一路走过来大家闭着眼睛都能画最小系统。但这两年做无人机、做机器人底盘、做巡线小车的人越来越多需求开始分层底层要硬实时、要能扛住电机换相的抖动上层要跑姿态融合、要接图传、要处理日志、要跟地面站对话。单核跑这些事要么主频拉满发热感人要么任务互相抢时间片姿态解算偶尔抖一下飞机就在空中画龙。HPM6750 这颗芯片进入视野就是因为它把这件事拆开了。它内部是双核 RISC-V 架构两个核不是对称的——一个偏实时控制一个偏应用处理主频能跑到 800MHz 级别带双精度浮点单元外设资源也够铺。所谓非对称双核架构说白了就是两个核分工不同、各干各的活而不是两个一模一样的核去轮流跑同一个任务队列。这个思路放到飞控上天然契合一个核死磕传感器采样和电机输出另一个核负责导航、日志、通信。我最早接触这套组合是因为一个植保机的项目。原来的方案是单核跑 PX4姿态环 1kHz日志一开、图传一接CPU 占用直接顶到 80% 以上偶尔出现解锁后电机响应迟滞。换成 HPM6750 双核之后把控制环单独扔给一个核另一个核专门处理 MAVLink 和 SD 卡日志整个系统的抖动肉眼可见地降下来了。这不是玄学是任务隔离带来的确定性。这篇文章不打算写成芯片手册的复述而是把我在 HPM6750 上搭国产飞控系统的完整思路摊开讲双核怎么分工、PX4 怎么往 RISC-V 上迁、仿真环境怎么搭、四合一电调为什么会失控、舵机怎么接、日志和参数怎么管。适合已经玩过 PX4、想往国产芯片上迁移的开发者也适合刚入门、想搞清楚飞控底层到底在跑什么的人。下面按我实际踩过的顺序来。2. HPM6750 双核到底怎么切任务划分的底层逻辑2.1 非对称双核和对称双核的本质区别很多人第一次听到“双核”脑子里浮现的是电脑上的两颗对等 CPU操作系统把线程随便调度到哪个核都行。那是对称多处理SMP。HPM6750 走的是另一条路两个核的定位不一样一个更偏向实时控制和外设响应一个更偏向通用计算和协议栈处理。它们各自有独立的指令流通过共享内存和核间中断来通信。这个区别决定了软件架构。对称双核下你可以偷懒让调度器去平衡负载非对称双核下你必须自己决定“谁干什么”一旦分错实时核被非实时任务拖住整个控制环就废了。所以第一步不是写代码是画任务地图。我的划分原则很简单凡是和“时间确定性”强相关的全部归实时核凡是和“吞吐量、协议、存储”相关的全部归应用核。姿态解算里的传感器读取、电机 PWM 输出、失控保护触发这些必须在确定的时间窗口内完成放实时核。日志写入、MAVLink 打包、参数读写、地面站握手这些允许几十毫秒的延迟放应用核。2.2 实时核该背哪些活实时核的任务清单我一般这么列IMU 采样与同步SPI 读 ICM42688 或 BMI088固定 1kHz 触发带时间戳。姿态控制环从传感器数据到姿态角速度再到 PID 输出整条链路在一个控制周期内闭环。电机混控与 PWM/DShot 输出把控制量映射到四个或更多电机的占空比。失控保护与解锁逻辑遥控信号丢失、姿态超限、电压过低时的紧急动作。核间通信的发送端把姿态、状态、传感器摘要打包丢给应用核。这些任务的特点是周期固定、延迟敏感。实时核上不要跑文件系统不要跑 TCP/IP不要做浮点密集的矩阵运算之外的杂事。我见过有人把 SD 卡日志直接挂在实时核上结果每次写卡那几毫秒姿态环就漏拍飞机在悬停时轻微点头。后来把日志挪到应用核问题消失。2.3 应用核该接哪些活应用核更像一个“地面站代理 数据管家”它负责MAVLink 协议栈和地面站、机载计算机通信收发指令和遥测。日志系统把实时核送来的数据写进 SD 卡或 Flash支持按需回放。参数管理参数的存储、加载、在线修改改完通知实时核生效。任务调度与模式管理自动航线、返航、定点等上层逻辑。仿真接口在 SITL 模式下应用核负责和仿真器交换数据。这样分下来实时核的 CPU 占用能压到 40% 以下应用核即使跑满也不影响控制环。两个核之间用共享内存加环形缓冲区传递数据配合核间中断做通知延迟能控制在微秒级。2.4 核间通信的坑共享内存不是随便读写的核间通信听起来简单实际最容易出问题。两个核同时读写同一块内存如果没有同步机制数据会撕裂。我的做法是在共享内存里开两个环形缓冲区一个方向一个避免读写指针互相踩。生产者写完数据后更新写指针然后触发核间中断。消费者在中断里读数据读完更新读指针。指针更新用原子操作或者用内存屏障保证顺序。注意不要用普通的全局变量在两个核之间传数据编译器优化和缓存一致性会让你怀疑人生。一定要用 volatile 加内存屏障或者干脆用芯片厂商提供的核间通信库。还有一个细节共享内存的地址映射。两个核看到的物理地址可能不一样配置的时候要确认链接脚本里共享段的位置别一个核写进去另一个核读出来是空的。我第一次调的时候就是地址没对齐调了一下午才发现。3. 把 PX4 搬到 RISC-V 上移植不是改个编译选项3.1 PX4 的架构为什么适合双核拆分PX4 本身是模块化的uORB 消息总线把各个模块解耦。姿态控制、传感器驱动、通信、日志都是独立模块通过发布订阅交换数据。这个结构天然适合往双核上映射把实时相关的模块编译到实时核把通信和日志模块编译到应用核中间用 uORB 的跨核扩展来桥接。但 PX4 官方对 RISC-V 的支持还在演进中HPM6750 这种非对称双核更是没有现成板级配置。所以移植的核心工作是让 PX4 的构建系统认识这颗芯片让 uORB 能跨核工作让驱动能对上外设。3.2 工具链和构建系统的准备先说工具链。RISC-V 的 GCC 工具链要选对版本太老的缺指令集支持太新的可能有 ABI 变动。我用的是一套稳定的 riscv64-unknown-elf 工具链配 CMake 和 Ninja 构建。PX4 的构建系统基于 CMake需要新增一个板级目录里面放链接脚本、启动文件、外设配置。具体步骤大致是在boards/下新建厂商和板子目录参考已有的 RISC-V 或 ARM 板级配置。写链接脚本把实时核和应用核的代码段、数据段、共享内存段分开。配置启动流程上电后先跑引导核初始化时钟和外设再启动另一个核。把 PX4 的驱动层对接 HPM6750 的 SPI、I2C、UART、PWM 外设。这里最容易卡住的是启动流程。非对称双核的启动顺序有讲究通常一个核先起来做基础初始化然后释放另一个核的复位。如果两个核同时抢外设初始化会互相干扰。我的做法是实时核先初始化控制相关外设应用核后初始化通信和存储外设中间用标志位同步。3.3 uORB 跨核通信的改造uORB 原本是单核内的发布订阅底层是共享内存加锁。跨核之后锁不能用了得换成无锁队列或者核间中断驱动的消息传递。我的改造思路是保留 uORB 的 API 不变让上层模块无感知。在底层增加一个“跨核传输层”当发布者在一个核、订阅者在另一个核时消息通过共享内存环形缓冲区传递。用核间中断通知对方有新消息避免轮询浪费 CPU。对高频消息如姿态做降采样不是每条都跨核传只传关键状态。这样改完之后实时核上的姿态模块照常发布应用核上的日志模块照常订阅中间的路由由传输层搞定。实测跨核消息延迟在 50 微秒以内对 1kHz 控制环没有影响。3.4 驱动适配SPI、PWM 和定时器HPM6750 的外设和 STM32 不完全一样驱动要重写。重点说三个SPI 读 IMUHPM6750 的 SPI 支持 DMA配置成固定频率触发DMA 搬运数据减少 CPU 干预。IMU 的片选和数据就绪引脚要接对中断优先级要高于其他外设。PWM 输出电机控制用 PWM 或 DShot。PWM 模式下定时器要配置成互补输出加死区频率一般 400Hz 到 1kHz。DShot 模式下用 DMA 发送数字协议时序要求更严。定时器控制环的节拍靠硬件定时器不要用软件延时。定时器中断里触发传感器读取和控制计算保证周期稳定。提示外设中断优先级一定要排好。IMU 数据就绪中断最高定时器中断次之通信中断最低。优先级排错控制环就会被通信打断。4. 仿真环境搭建先在电脑上跑通再上板子4.1 为什么仿真这一步不能省直接上板子调飞控效率极低。一个参数改错飞机可能直接翻掉硬件损坏不说排查也麻烦。仿真环境能在电脑上把控制逻辑、通信协议、任务调度全部跑一遍确认没问题再烧到板子上。PX4 的 SITL 仿真配合 Gazebo 或 jMAVSim能模拟传感器、电机、物理环境是移植过程中最省时间的工具。4.2 Ubuntu 下搭建 PX4 仿真环境我用的 Ubuntu 20.04 或 22.04步骤大致如下# 克隆 PX4 源码 git clone https://github.com/PX4/PX4-Autopilot.git --recursive cd PX4-Autopilot # 安装依赖 bash Tools/setup/ubuntu.sh # 编译并启动 SITL make px4_sitl gazebo如果网络环境导致子模块拉取慢可以分步克隆先拉主仓库再初始化子模块。编译过程中如果报 Python 包缺失按提示装就行。Gazebo 第一次启动会下载模型耐心等。启动成功后你会看到 PX4 的控制台输出可以用commander takeoff解锁起飞用 QGroundControl 连接 UDP 端口看遥测。这一步跑通说明 PX4 的基本逻辑没问题接下来才是往 HPM6750 上迁。4.3 把 HPM6750 的板级配置接进仿真仿真的意义在于我可以先用仿真的传感器数据喂给实时核的控制算法验证 PID 参数和混控逻辑再换成真实 IMU。具体做法是写一个仿真桥接模块把 Gazebo 的传感器数据通过共享内存或 UDP 送给实时核实时核算完控制量再送回仿真器驱动虚拟电机。这个桥接模块的接口要和真实驱动一致这样上板子时只需要换驱动实现控制逻辑不用动。我一般把驱动层抽象成统一的sensor_read()和motor_write()接口仿真和真实硬件各实现一套。4.4 仿真里能发现的问题仿真能提前暴露很多问题控制环周期不稳、PID 参数发散、模式切换逻辑错误、通信超时处理缺失。我在仿真里就发现过一次模式切换时的状态机死锁飞机在悬停和返航之间反复横跳。这种问题如果上真机基本就是炸机。注意仿真不能替代真机测试但能过滤掉 80% 的逻辑错误。仿真跑通不等于真机没问题传感器噪声、电机响应延迟、电磁干扰这些只有真机才能遇到。5. 四合一电调失控一次完整的排查链路5.1 现象描述解锁后电机疯转这是我在 HPM6750 平台上遇到的最棘手的问题。现象是地面站显示解锁成功但四个电机中有一个或两个突然满油门疯转其他电机不动飞机直接侧翻。重新上电后又可能正常偶发性极强。这种偶发问题最折磨人因为它不是每次都复现。我一开始怀疑是电调协议不兼容换了两种电调还是一样。又怀疑是 PWM 频率不对改了频率问题依旧。最后是通过示波器抓波形才定位到根因。5.2 排查第一步确认电调协议和信号电平四合一电调常见协议有 PWM、OneShot、DShot。不同协议对信号电平和时序要求不同。HPM6750 的 IO 电平是 3.3V大部分电调能接受但有些电调对高电平阈值敏感3.3V 可能处于临界状态。我先用示波器量了 PWM 信号发现空闲时信号线有毛刺幅度接近阈值。这说明不是协议问题是信号完整性问题。信号线太长、没有屏蔽、和电机线捆在一起都会引入干扰。5.3 排查第二步看定时器初始化和死区配置信号毛刺只是表象真正的问题在定时器初始化。HPM6750 的 PWM 定时器在启动瞬间如果比较寄存器的初值没设好会输出一个异常占空比。这个异常脉冲被电调当成有效信号电机就疯转。我的修复方案是定时器初始化时先把所有通道的比较值设成安全值对应电机停转的占空比。使能输出前先让定时器空转几个周期确认输出稳定。加死区配置防止上下桥臂直通。解锁逻辑里增加一步先发一段时间的最低油门信号让电调完成自检和校准再进入正常控制。改完之后疯转问题再没出现过。这个坑的本质是电调上电后会等待一段时间的有效信号来校准油门行程如果这段时间收到异常脉冲校准就错了。5.4 排查第三步电源和地线的处理还有一个容易被忽略的点地和电源。四合一电调的电流很大电机启动瞬间的电流冲击会让地线电位跳动。如果飞控和电调共地不好信号参考电平就会漂移导致误判。我的做法是飞控和电调之间用粗地线连接信号线单独走不要和电源线并行。必要时在信号线上加小电阻和电容做滤波。这些是硬件层面的经验软件调不出来。5.5 举一反三其他外设的类似问题同样的思路可以套到舵机上。舵机也是靠 PWM 信号控制上电瞬间如果收到异常脉冲会转到极限位置。所以舵机初始化也要先输出中位信号等舵机稳定后再进入控制。这个在后面的舵机章节还会细说。6. 舵机接入与混控配置固定翼和VTOL的必修课6.1 舵机信号和电调信号的区别舵机用的也是 PWM但频率低得多通常 50Hz脉宽 1ms 到 2ms 对应角度范围。电调频率高400Hz 以上。两者不能混在一个定时器组里用同一个频率否则要么舵机抖要么电调响应慢。HPM6750 的定时器资源够我把舵机分配到一个独立的定时器配置成 50Hz电调分配到另一个定时器配置成 400Hz 或更高。这样互不干扰。6.2 舵机上电初始化的正确姿势舵机上电时如果信号线悬空或收到乱码舵机会乱转。正确做法是飞控上电后先把舵机信号引脚配置成输出输出中位脉宽1.5ms。保持中位一段时间等舵机内部完成初始化。再根据控制逻辑输出实际角度。这个顺序不能反。我见过有人先初始化控制逻辑再配置引脚结果上电瞬间舵机打到极限舵机臂都掰弯了。6.3 混控配置从固定翼到多旋翼PX4 的混控配置在mixer文件里定义把控制量映射到具体的输出通道。固定翼的副翼、升降、油门、方向多旋翼的四个电机VTOL 的过渡逻辑都在这里配。在 HPM6750 上混控计算放在实时核输出直接写定时器比较寄存器。配置的时候要注意通道映射和方向方向反了飞机就翻。我的习惯是先在仿真里验证混控方向再上真机。提示混控文件改完一定要重新校准遥控器行程否则舵机行程和遥控器不匹配操作会很难受。7. 日志、参数与地面站应用核的日常7.1 日志系统怎么设计才不拖累实时核日志是排查问题的命根子但写日志很耗时。我的方案是实时核只负责把数据打包丢进共享内存环形缓冲区应用核从缓冲区取数据写 SD 卡。缓冲区够大能扛住 SD 卡偶尔的写入延迟。日志格式用二进制比文本省空间也省 CPU。每条日志带时间戳和消息 ID回放的时候按 ID 解析。SD 卡选高速卡文件系统用 FatFS 或 LittleFS写入用 DMA 或大块缓冲减少频繁小写。7.2 参数管理的读写一致性参数存在 Flash 里上电加载运行时可以改。改参数的时候要注意应用核改了参数要通知实时核重新读取否则实时核还在用旧值。我的做法是参数改完后发一个核间中断实时核在中断里重新加载相关参数。参数存储要防掉电写入的时候先擦除再写写完校验。如果掉电导致参数损坏要有默认值兜底不能让飞机因为参数读不出来就罢工。7.3 地面站连接和 MAVLink 调参地面站用 QGroundControl通过数传或 USB 连接。MAVLink 协议栈跑在应用核实时核的状态通过跨核消息送给应用核再打包发给地面站。调参的时候地面站发的参数修改请求由应用核处理改完通知实时核。这里有个细节MAVLink 的心跳包要定期发否则地面站会认为飞控失联。心跳包由应用核负责即使实时核在忙心跳也不能断。8. 实测中的几个硬核经验8.1 控制环周期不要盲目追高很多人觉得控制环频率越高越好1kHz 不够就上 2kHz、4kHz。实际上频率越高CPU 占用越大对传感器和电调的响应要求也越高。HPM6750 跑 1kHz 控制环绰绰有余姿态解算和混控加起来占用不到 30%。盲目提高频率反而可能因为传感器数据没准备好而读到重复值。我的建议是先确定传感器的最快输出速率控制环频率不超过传感器速率。IMU 能出 1kHz控制环就 1kHzIMU 只有 500Hz控制环就别超过 500Hz。8.2 核间通信的延迟要实测核间通信的延迟不能靠猜要用示波器或 GPIO 翻转来测。我在实时核发消息时翻转一个 GPIO应用核收到消息时翻转另一个示波器上看两个边沿的时间差。实测下来共享内存加中断的方式延迟在 20 到 50 微秒之间完全够用。如果延迟超过 100 微秒就要检查是不是中断优先级太低或者共享内存访问有冲突。8.3 温度对 IMU 的影响不能忽视IMU 的零偏随温度漂移这是物理特性软件只能补偿。我的做法是上电后先静置一段时间让 IMU 温度稳定再校准零偏。飞行过程中如果温度变化大姿态会缓慢漂移。高端做法是加温度补偿曲线普通做法是起飞前充分预热。8.4 国产芯片的生态还在完善HPM6750 的文档和例程相比 STM32 还有差距有些外设的配置需要自己摸索。我的经验是多看芯片厂商提供的 SDK 和例程遇到问题先查社区再不行就抓波形。RISC-V 的工具链和调试器也在成熟中选型的时候要确认调试工具是否好用。9. 从能飞到好用后续可以继续打磨的方向这套 HPM6750 双核飞控系统跑通之后能飞、能控、能记录但离“好用”还有距离。我接下来打算做几件事一是把日志回放工具做完善能在电脑上可视化飞行数据二是把参数系统做成在线可调不用重新烧固件三是把双核的负载监控做出来实时看两个核的占用率方便优化任务分配。另外RISC-V 生态里的实时操作系统也在发展未来可以考虑在应用核上跑一个轻量 RTOS把任务管理做得更规范。实时核保持裸机或轻量调度保证确定性。这个组合在国产飞控里会越来越常见。如果你也在做类似的项目我的建议是先把单核逻辑跑通再拆到双核先在仿真里验证再上真机先保证控制环稳定再堆功能。飞控这东西稳定永远比功能多重要。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑