PX4 SOC 与 BSP 层平台抽象
一、三层结构概览
Board 层、BSP 层、SOC 层构成 PX4 硬件抽象的三级结构,职责各异:
1 | flowchart TD |
相关前置知识:Board 层硬件配置
二、构建关系
platforms/nuttx/src/px4/stm32f7/CMakeLists.txt 负责将 BSP 与 SOC 组件聚合到同一编译目标:
- BSP 通用模块(stm32_common):ADC、HRT、SPI、io_timer 等,被所有 STM32 系列复用
- SOC 专属(stm32f7):
px4io_serial:F7 特定的 DMA + DCache + IDLE 中断处理watchdog:F7 具体的硬件看门狗实现
Board 层在更高层的 Board CMake 中被加入同一构建图谱,最终与 BSP/SOC 一起链接成单一的 .elf 固件镜像。
三、运行时调用链路
3.1 stm32_boardinitialize()
NuttX 启动序列最早调用的板级入口,在 init.c 中实现:
1 | stm32_boardinitialize() |
3.2 board_app_initialize()
应用层初始化入口,PX4 平台起来前的最后板级准备:
1 | board_app_initialize() |
四、BSP 层核心文件
4.1 micro_hal.h
BSP 层将 Board 层定义的宏落地到 NuttX STM32 HAL 的关键桥接文件,统一将 px4_arch_* 映射到 NuttX STM32 的 stm32_* 实现:
1 | px4_arch_configgpio(pinset) -> stm32_configgpio(pinset) |
Board 层产出 Pinset 位域(端口/引脚/模式/上下拉/AF/默认电平),BSP 层把 Pinset 写进 STM32 GPIO 寄存器。Board 层不允许直接操作寄存器。
4.2 board_hw_rev_ver.c
硬件版本识别:将 ADC 电阻梯码值转为 V5xxxx 类型信息。
Board 层在 board_config.h 定义版本识别的引脚宏与 ADC 通道,BSP 层 determine_hw_info() 用 read_id_dn() 做两次测量(先测 revision,再测 version),将 ADC 码值 dn 转成 ordinal(离散编号),最终生成 hw_info 字符串。
4.3 board_reset.cpp
复位到 Bootloader 或应用程序,核心机制:
- 写 RTC 备份寄存器(如
STM32_RTC_BK0R)存放模式魔数 - 魔数类型:boot to BL、boot to app、CAN BL 等
- 调用
up_systemreset()触发复位 - 备份域掉电保持,适合跨复位传递启动模式意图
4.4 hrt.c
HRT 高精度时钟与 PPM 解码绑定在同一硬件定时器上。直接占用一个 TIM,不走 NuttX 通用定时器驱动:
- 需要稳定 1 MHz free-running 计数作微秒级时间基准
- 需要比较中断,安排未来某时刻触发回调
- 需要最小抖动与最小开销
hrt_init() 核心流程:
1 | // 打开定时器时钟 RCC |
同一颗 TIM 同时承担:
- HRT:系统微秒时基 + callout 调度(比较中断)
- PPM:输入捕获/边沿时间戳 → PPM 状态机解码
4.5 adc.cpp
ADC 采样抽象,单次转换、寄存器级操作:
1 | // 初始化接口 |
Board 层定义引脚与通道映射,board_hw_rev_ver.c 与 board_adc 驱动只关心通道编号,不关心寄存器细节。
4.6 io_timer.c
PWM/捕获/Oneshot/DShot 的统一定时器框架:
1 | 初始化流程: |
Board 层 timer_config.cpp 决定”哪些 TIM 实例可用、每个通道映射到哪个引脚”,BSP io_timer.c 只负责把”映射表 + 模式”变成寄存器配置。同一套框架覆盖 PWM/捕获/OneShot/DShot,差异只在 mode 与寄存器位。
五、SOC 层:stm32f7 特定实现
stm32f7/px4io_serial/px4io_serial.cpp 是 SOC 层的典型代表。
ArchPX4IOSerial::init()
通过 PX4IO_SERIAL_* 宏(来自 Board 层 board_config.h)拿到 UART base/vector/DMAMAP/RCC 等硬件细节:
1 | -> 申请 TX/RX DMA 通道:stm32_dmachannel(PX4IO_SERIAL_TX_DMAMAP) |
ArchPX4IOSerial::_bus_exchange()
每次事务流程:
1 | 准备 RX DMA -> TX DMA 发包 -> 等待 RX DMA 完成或超时 |
F7 有 DCache,DMA 必须处理 cache line 对齐与 invalidate/clean。这也是 SOC 层独立于 BSP 层的原因:不同 STM32 系列的 UART/DMA/中断细节差异显著,通用化会引入大量条件编译。
驱动层(src/drivers/px4io/)通过 PX4IO_serial_interface() 工厂函数拿到 ArchPX4IOSerial 实例,px4io 驱动本身不直接写寄存器,实现了驱动层与 SOC 层的解耦。
六、Board/BSP/SOC 层宏到行为的对应关系
GPIO 链路
1 | Board -> 定义 GPIO_*、PX4_GPIO_INIT_LIST |
ADC/硬件版本链路
1 | Board -> 定义 ADC_HW_VER_SENSE_CHANNEL 等 |
HRT 链路
1 | Board -> 选择 HRT_TIMER=8、HRT_TIMER_CHANNEL=3、HRT_PPM_CHANNEL=1 |
PX4IO 串口链路
1 | Board -> 给出 /dev/ttyS6、UART base/vector、DMA map、RCC enable、TX/RX GPIO |
上一篇:Board 层硬件配置
下一篇:固件编译与烧写流程