4. PX4代码结构与驱动目录
在PX4中开发自定义传感器驱动,第一步不是写代码,而是理解代码放在哪里、如何被编译、如何被启动。PX4采用“模块化驱动 + 启动脚本 + CMake构建 + 模块加载”的组合机制,驱动并不是自动运行的,而是通过启动脚本显式加载。掌握这条链路,才能让新驱动真正进入系统。
一、src/drivers 的组织方式
PX4源码中,src/drivers 目录是传感器和执行器驱动的主要存放位置。它按“总线类型 + 设备类别”进行分层组织,常见结构如下:
src/drivers/
├── barometer/ # 气压计驱动
├── distance_sensor/ # 测距/激光雷达驱动
├── gps/ # GPS驱动
├── imu/ # 惯性测量单元驱动
├── magnetometer/ # 磁力计驱动
├── optical_flow/ # 光流驱动
├── px4io/ # PX4IO协处理器
├── rgbled/ # RGB LED驱动
├── telemetry/ # 数传驱动
└── ...
每个驱动子目录通常包含:驱动源文件(.cpp)、头文件、CMakeLists.txt 以及可选的 Kconfig 或参数定义文件。以 src/drivers/imu 为例,内部还会按具体芯片型号继续细分,例如 invensense/icm42688p、bosch/bmi088 等。这种组织方式让驱动与硬件型号一一对应,便于裁剪和复用。
src/drivers/ 下新建独立子目录,例如 src/drivers/my_sensor/,避免直接修改公共目录,方便后续升级和版本管理。二、CMake构建:驱动如何被编译进固件
PX4使用CMake作为构建系统。每个驱动目录下的 CMakeLists.txt 负责声明该驱动的源文件、依赖库和编译选项。典型内容如下:
px4_add_module(
MODULE drivers__my_sensor
MAIN my_sensor
SRCS
my_sensor.cpp
DEPENDS
drivers__imu
)
其中 MODULE 是模块名,MAIN 是模块入口,SRCS 列出源文件,DEPENDS 声明依赖。构建时,CMake会递归扫描 src/drivers 下的所有 CMakeLists.txt,根据目标板配置决定是否将该驱动编入固件。对于PX4,常用命令为:
make px4_fmu-v6x_default
# 或
make px4_sitl_default
如果驱动只针对特定硬件,可通过 CONFIG_DRIVERS_MY_SENSOR=y 在板级配置中启用,避免影响其他目标。
三、启动脚本:驱动加载的入口
PX4启动脚本位于 ROMFS/px4fmu_common/init.d/,常见文件包括 rcS、rc.sensors、rc.mc_defaults 等。驱动加载通常写在 rc.sensors 或板级启动脚本中,例如:
# 启动自定义传感器驱动
my_sensor start -X -b 1
# 启动IMU驱动
icm42688p start -s
启动脚本在系统上电后由 rcS 依次执行,负责初始化总线、加载驱动、设置参数。驱动模块通常提供 start、stop、status 等命令,通过 module 机制注册到系统。若驱动未在脚本中启动,即使编译进固件也不会运行。
CMakeLists.txt 并编译成功,却忘记在启动脚本中添加 start 命令,导致驱动“编译进去了但没跑起来”。排查时先用 my_sensor status 确认模块是否存在。四、驱动加载机制与模块生命周期
PX4驱动本质上是可加载模块。模块通过 px4_add_module 注册,运行时由 module 命令管理。加载流程可概括为:
- 系统启动,执行
rcS及子脚本; - 脚本调用
my_sensor start; - 模块入口函数执行,初始化总线、注册
uORB主题; - 驱动进入工作循环,周期读取传感器数据并发布;
- 可通过
my_sensor stop停止,释放资源。
驱动与飞控之间的数据交互通过 uORB 完成。例如自定义传感器发布 sensor_my_data 主题,其他模块订阅后即可使用。加载机制的核心是“脚本驱动 + 模块管理 + uORB通信”。
五、案例:自定义驱动接入流程
假设要新增一个I2C温度传感器驱动 my_temp,完整接入步骤如下:
| 步骤 | 操作 | 文件/命令 |
|---|---|---|
| 1 | 创建驱动目录 | src/drivers/my_temp/ |
| 2 | 编写驱动源码 | my_temp.cpp、my_temp.hpp |
| 3 | 声明CMake模块 | CMakeLists.txt 使用 px4_add_module |
| 4 | 注册到父级CMake | 在 src/drivers/CMakeLists.txt 添加 add_subdirectory(my_temp) |
| 5 | 添加启动命令 | rc.sensors 中加入 my_temp start |
| 6 | 编译并烧录 | make px4_fmu-v6x_default upload |
| 7 | 验证运行 | my_temp status、listener sensor_temp |
六、常见误区与复盘
- 只改驱动,不改CMake:驱动文件不会被编译,固件中不存在该模块。
- 只改CMake,不改启动脚本:模块存在但不会自动运行,需手动
start。 - 模块名冲突:
MODULE名必须唯一,否则链接或加载会失败。 - 依赖缺失:若驱动依赖其他模块,需在
DEPENDS中声明,否则运行时报错。 - 启动顺序错误:传感器驱动应在总线初始化之后启动,否则I2C/SPI访问失败。
理解 src/drivers 的组织方式、CMake构建规则、启动脚本和模块加载机制,是PX4自定义传感器驱动开发的基础。只有把驱动正确放入目录、编入固件、写入启动脚本,并通过uORB发布数据,才算真正完成一次驱动接入。