第一章:PX4驱动架构概览

各位同学好,我是老张。做嵌入式飞控这些年,我见过太多人在PX4驱动面前栽跟头。其实说白了,驱动层没那么神秘——它就是连接硬件和操作系统的桥梁。今天咱们先把架构理清楚,后面读代码才不会迷路。

1.1 PX4系统架构:三层结构

PX4的整体架构,我习惯把它分成三层来看:

  • 应用层:飞行模式、导航算法、任务规划。这部分跑在用户空间,用uORB通信。
  • 中间层:uORB消息总线、参数系统、日志系统。这是整个系统的“血管”。
  • 驱动层:传感器、执行器、外设的底层控制。直接跟寄存器打交道。

你想想看,应用层想读一个陀螺仪数据,它不需要知道I2C时序怎么调、SPI时钟怎么配。它只需要通过uORB订阅一个话题,数据就来了。这就是分层的好处——各司其职。

核心要点:驱动层是唯一直接操作硬件的代码。其他层只能通过uORB或系统调用间接访问。

我在项目中遇到过一个问题:有个同事把传感器校准逻辑写进了驱动里,结果每次固件升级都要重新调参。这就是典型的层次混乱。记住,驱动只负责“读数据”和“写控制”,别掺和业务逻辑。

1.2 驱动层在系统中的位置

驱动层到底在哪儿?我画个图你就明白了。

应用层 飞行模式 · 导航算法 · 任务规划 中间层(uORB总线) 消息发布/订阅 · 参数系统 · 日志 驱动层 传感器驱动 · 执行器驱动 · 外设驱动 硬件(传感器 · 电机 · GPS · 数传)

这张图我每次培训都会放。注意看,驱动层下面是硬件,上面是uORB。驱动把硬件数据“翻译”成uORB消息,应用层只管订阅。嗯,这里要注意:驱动层不能直接调用应用层的函数,反过来也不行。这是架构红线。

1.3 uORB消息机制简介

uORB是PX4的“内部快递员”。我刚开始接触时觉得它很绕,后来发现其实就是发布-订阅模式。

1.3.1 核心概念

  • 话题(Topic):比如sensor_accelvehicle_attitude。每个话题有固定的数据结构。
  • 发布者(Publisher):驱动层通常是发布者。比如IMU驱动发布加速度数据。
  • 订阅者(Subscriber):应用层订阅。比如EKF订阅加速度数据做融合。

小技巧:调试时可以用uorb top命令查看当前所有话题的发布频率。我曾经靠这个抓到一个驱动没启动的bug——话题频率为0,说明驱动根本没在发数据。

1.3.2 驱动中的典型流程

一个传感器驱动的工作流,我总结为四步:

  1. 初始化:配置GPIO、SPI/I2C、中断。注册设备。
  2. 数据采集:在中断或轮询中读取寄存器。
  3. 数据发布:调用orb_publish()把数据塞进uORB。
  4. 错误处理:通信失败时重试或报错。

举个实际例子,这是MPU6000驱动发布加速度数据的核心代码:

// 伪代码,实际代码在 src/drivers/mpu6000/
struct sensor_accel_s accel_data;
accel_data.timestamp = hrt_absolute_time();
accel_data.x = raw_x * scale;
accel_data.y = raw_y * scale;
accel_data.z = raw_z * scale;

// 发布到uORB
orb_publish(ORB_ID(sensor_accel), _accel_pub, &accel_data);

你看,驱动只负责填数据结构和调用orb_publish。至于谁在用这个数据、怎么用,驱动完全不关心。这就是解耦。

1.3.3 避坑指南

我曾经踩过的坑:uORB消息的timestamp字段必须用硬件时间戳,不能用软件获取时间。有一次我偷懒用了hrt_absolute_time(),结果EKF的延迟补偿全乱了。记住,传感器数据的时间戳应该在中断服务函数里就打上,越靠近硬件越好。

1.4 本章小结

总结一下今天的内容:

层级 职责 通信方式
应用层 飞行控制、导航决策 uORB订阅
中间层 消息路由、参数管理 uORB总线
驱动层 硬件数据采集与控制 uORB发布 + 寄存器操作
硬件层 物理传感器、执行器 SPI/I2C/UART/CAN

我个人觉得,理解PX4驱动架构的关键就一句话:驱动是硬件的翻译官,uORB是消息的快递员。后面章节我们会深入每个驱动的具体实现,到时候你会发现,所有驱动都逃不出今天讲的这个框架。

课后思考:如果你要写一个全新的气压计驱动,第一步应该做什么?是找数据手册,还是先搭uORB话题结构?想清楚这个问题,你就入门了。

专注资料整理