高通嵌入式Linux开发实战(3):外设驱动开发:I²C、SPI、CAN-FD与MIPI摄像头的Hexagon低功耗方案
0. 本篇要解决什么问题
工业机器人和智能相机的外设开发,难点不只是“让一个节点出现在 /dev 下”,而是同时保证实时链路、相机稳定性、待机功耗和 BSP 可维护性。
本篇给出一条可落地的分层路径:Linux 负责真实硬件控制与标准设备模型,Hexagon 负责可卸载的帧处理,应用通过 V4L2、SocketCAN、IIO 与 FastRPC 组合能力。
1. 先建立正确的驱动边界
1.1 三类外设,三种 Linux 子系统
| 外设 | 首选 Linux 框架 | 用户态接口 | 项目关键点 |
|---|---|---|---|
| I²C 传感器、EEPROM、IO 扩展器 | I²C core + regmap + IIO / hwmon / input |
IIO sysfs、/dev/iio、hwmon、input |
中断、量程、供电时序、总线恢复 |
| SPI ADC、IMU、编码器前端、FPGA | SPI core + regmap + IIO / MTD / 自定义驱动 |
IIO、MTD、专用字符设备 | mode、bits-per-word、DMA 阈值、片选时序 |
| CAN-FD 控制器/收发器 | CAN networking + SocketCAN | canX、CAN_RAW socket |
位定时、错误帧、Bus-Off、时间戳 |
| MIPI CSI-2 相机 | V4L2 + Media Controller + CAMSS / ISP | /dev/video、media graph |
电源、CSI lane、sensor mode、buffer 生命周期 |
不要把协议栈重复实现到应用层。CAN-FD 应进入 SocketCAN;连续采样数据优先进入 IIO;相机走 V4L2 media graph。这样可直接复用诊断工具、权限模型、时间戳和上游生态
2. 板级准备:先把硬件事实写成清单
在修改 Device Tree 前,依据原理图和 BSP 的 board DTS,完成下面的“外设合同”。它能避免大量“驱动绑定了却没有数据”的问题。
| 项目 | I²C/SPI | CAN-FD | MIPI 摄像头 |
|---|---|---|---|
| 物理连线 | 控制器、pinctrl、地址/片选、IRQ | 控制器、收发器 EN/STB、CANH/CANL、120 Ω 终端 | CSI port、lane 数、时钟、reset/pwdn、I²C 控制总线 |
| 电源 | VDD/VIO、enable GPIO、上电延迟 | 控制器域与收发器电源、待机脚 | AVDD/DVDD/IOVDD、时钟稳定时间、下电顺序 |
| 时钟 | SPI 最大 SCLK、传感器 ODR | 标称/数据相位时钟源 | MCLK、CSI PHY、传感器 PLL |
| 软件归属 | IIO/hwmon/input 或专用子系统 | SocketCAN + transceiver 控制 | sensor subdev + CAMSS/ISP + V4L2 |
| 验收指标 | IRQ、采样率、丢样率 | error counter、Bus-Off、恢复 | 首帧时间、帧率、丢帧、恢复 |
3. I²C / SPI:从“能读寄存器”到可维护驱动

3.1 Device Tree 的最小职责
DTS 描述硬件存在、连接方式和不可在运行时改变的属性,不应承载业务策略。典型信息包括控制器 pinctrl、设备地址/片选、compatible、IRQ、regulator、reset GPIO、时钟与固定安装方向。
&qup_i2c5 {
status = "okay";
imu@68 {
compatible = "vendor,imu123";
reg = <0x68>;
interrupt-parent = <&tlmm>;
interrupts = <42 IRQ_TYPE_LEVEL_LOW>;
vdd-supply = <&vreg_sensor_3p3>;
vddio-supply = <&vreg_sensor_1p8>;
reset-gpios = <&tlmm 43 GPIO_ACTIVE_LOW>;
status = "okay";
};
};
&qup_spi3 {
status = "okay";
adc@0 {
compatible = "vendor,adc456";
reg = <0>;
spi-max-frequency = <12000000>;
interrupt-parent = <&tlmm>;
interrupts = <58 IRQ_TYPE_EDGE_RISING>;
status = "okay";
};
};
示例名称仅为演示,必须对照当前 BSP 的 binding 文档和 DTSI。
3.2 驱动实现的推荐顺序
-
优先使用上游或 BSP 现有驱动:仅地址、GPIO、供电时序不同,优先 DTS 适配,不复制“近似驱动”。
-
寄存器访问使用
regmap:统一缓存、位操作、调试和总线传输。 -
进入正确子系统:连续采样传感器优先 IIO;健康信息优先 hwmon;按键、霍尔开关等事件可考虑 input。
-
中断优于高频轮询:IRQ 线程只做最少工作;批量读取与时间戳交由 IIO buffer / 工作队列。
-
电源管理是功能的一部分:实现 runtime PM,停流时关闭采样或进入 low-power mode,并验证恢复后的寄存器状态。
3.3 首轮调试命令
# 实验室确认地址与总线;量产逻辑不要依赖扫描。
i2cdetect -y 5
i2ctransfer -y 5 w1@0x68 0x75 r1
# SPI 绑定及 IIO 数据
ls -l /sys/bus/spi/devices/
dmesg | grep -Ei 'spi|iio|imu'
iio_info
cat /sys/bus/iio/devices/iio:device*/name
I²C NACK 不一定是地址错误,也可能是 VIO 未上电、reset/pwdn 极性错误、上电延迟不足或 pinmux 冲突。SPI 读回全 0xff / 0x00 时,优先检查 CPOL/CPHA、片选极性、bits-per-word 与 MISO 电平域。
4. CAN-FD:使用 SocketCAN,而不是自建字符设备协议
CAN-FD 在 Linux 中是网络设备。控制器驱动注册 canX,应用通过 PF_CAN / CAN_RAW socket 收发;iproute2、can-utils、ROS 2 bridge 和抓包工具均可复用。
若载板挂接外置 CAN-FD 控制器,通常通过 SPI 接入,驱动还要控制收发器的 standby / enable GPIO。若平台已有 CAN 控制器,重点是 pinctrl、时钟、收发器与 DTS 配置。不要假设任意 IQ 载板都引出了同一控制器实例;请以原理图和 BSP 为准。
# 500 kbit/s 仲裁相位 + 2 Mbit/s 数据相位:仅为示例。
ip link set can0 down
ip link set can0 type can bitrate 500000 dbitrate 2000000 fd on \
berr-reporting on restart-ms 100
ip link set can0 up
ip -details -statistics link show can0
candump -e -x can0
cansend can0 123##31122334455667788
restart-ms 是否适合产品,取决于安全策略:普通遥测总线可以自动恢复;涉及机器人安全状态的总线,Bus-Off 后通常应上报故障、进入受控状态,并由安全状态机决定是否重新使能。
工业机器人要点:核对双端 120 Ω 终端、隔离收发器、共模范围、地参考和线束屏蔽;按系统设计计算仲裁/数据相位采样点;持续采集 TX/RX error counter、error passive、Bus-Off、重启次数和丢帧计数;相机、编码器和 CAN 融合时统一单调时钟/硬件时间戳策略。
5. MIPI 摄像头:Linux 负责采集,Hexagon 负责低功耗处理
5.1 为什么不能把“摄像头驱动放到 Hexagon”
典型 Qualcomm Linux BSP 中,摄像头传感器以 V4L2 sub-device 表达,CSI 接收器、CAMSS/ISP 和 video node 通过 Media Controller 形成图。sensor 的 I²C 配置、regulator、MCLK、reset/pwdn、CSI PHY 与 buffer queue 依赖 Linux 相机栈和 BSP 专有组件。
Hexagon 的正确位置是算法数据面:ROI 裁切、色彩转换、缩放、帧差、运动检测、质量统计、事件筛选和 NPU 前处理。它不应接管 CSI-2 sensor 的 probe、stream on/off 或 V4L2 内核 buffer 生命周期;该边界能避免电源域、缓存一致性和相机 vendor stack 被双重控制。
5.2 推荐实现:V4L2 DMABUF + FastRPC + 事件唤醒
-
Linux camera service 使用 V4L2 配置 sensor mode,申请多缓冲队列;buffer 使用 DMA-BUF 在内核/用户态组件间传递。
-
应用服务 取得帧描述符与元数据(时间戳、stride、format、sequence),不复制整帧到普通堆内存。
-
FastRPC client 将共享缓冲区句柄、尺寸和算法参数传递给 Hexagon 动态库;DSP 只读输入帧,或写入独立输出/metadata buffer。
-
Hexagon worker 做轻量预处理与事件判断;仅在检测到目标、异常或达到上报周期时返回小型 metadata/ROI。
-
Linux/ROS 2 节点 决定是否启动重模型、NPU 推理、录像、CAN 告警或网络上报。
关键不在于“每帧都送 DSP”,而是减少 DDR 往返、避免 CPU copy,用事件而非持续全分辨率处理唤醒重负载任务。
5.3 缓冲区与同步规则
| 规则 | 工程含义 |
|---|---|
| 明确 buffer 所有权 | 每帧必须有唯一生产者、消费者完成条件与回收者;不能把 V4L2 buffer 当永久内存。 |
| 显式同步 | 跨 CPU/DSP/ISP 使用 DMA-BUF 时,按 BSP 接口处理 fence、cache 同步和 map/unmap。 |
| 元数据随帧走 | 帧号、单调时间戳、曝光/增益、格式和 ROI 坐标必须与 buffer 绑定。 |
| 限制处理预算 | DSP worker 需要最大队列深度和超时策略;预览积压时丢弃旧帧通常优于增加延迟。 |
| CPU fallback | FastRPC/DSP 不可用或共享 buffer 导入失败时,降级到 CPU 路径并上报健康状态。 |
5.4 相机调试顺序
# 1) 确认 sensor -> CSI -> ISP/video node 链路。
media-ctl -p
# 2) 检查 V4L2 能力、格式和帧率。
v4l2-ctl -d /dev/video0 --all
v4l2-ctl -d /dev/video0 --list-formats-ext
# 3) 短时采集验证,再接 ROS 2 / DSP 算法。
v4l2-ctl -d /dev/video0 --stream-mmap=4 --stream-count=120 --stream-to=/dev/null
# 4) 检查 sensor、CSI、CAMSS/ISP、IOMMU 错误。
dmesg -w | grep -Ei 'camera|camss|csi|isp|i2c|iommu'
推荐定位顺序:供电/时钟 → I²C probe → sensor ID → media link → CSI 错误计数 → 首帧 → 连续采集 → buffer 导入 → DSP 算法。首帧没有稳定前,不要调优 Hexagon 算法。
6. MIPI 到 Hexagon 的低功耗处理流程
实际 FastRPC 方法名、DSP domain 与 buffer-import API 以当前 Qualcomm BSP / Hexagon SDK 为准。

7. 推荐的代码组织
peripheral-stack/
├── dts/ # 板级 overlay / patch,与原理图版本对应
├── kernel/ # 必要的 I2C/SPI/CAN 驱动补丁
├── userspace/
│ ├── camera-service/ # V4L2、DMA-BUF、帧元数据、健康检查
│ ├── can-service/ # SocketCAN、协议解析、Bus-Off 状态机
│ ├── sensor-service/ # IIO 采集、校准、时间戳
│ └── dsp-client/ # FastRPC client、buffer 导入、降级策略
├── hexagon/ # DSP 算法库;不放 sensor kernel driver
├── ros2/ # image/can/sensor bridge 与 diagnostics
└── tests/ # 台架回归、长稳、异常注入
8. 验收清单:不要只验证“启动成功”
I²C / SPI
- 冷启动、热复位、反复 suspend/resume 后均能 probe 与采样。
- IRQ 频率、采样率、时间戳和丢样计数在目标负载下符合预期。
- NACK、IRQ 卡死、电源抖动时,日志与健康状态可定位。
- runtime PM 后,寄存器、校准状态和数据通路正确。
CAN-FD
- 标称/数据相位速率、BRS、终端和收发器待机脚经过台架验证。
- error warning、error passive、Bus-Off 与恢复策略均有记录和测试。
- 长时间高负载下无异常重启,诊断计数持续采集。
- 安全相关控制帧与普通遥测帧在状态机和故障策略上明确隔离。
MIPI + Hexagon
- 冷启动首帧、连续运行、停流再开流、异常恢复均通过。
- 采集到 DSP 无额外整帧 CPU copy,buffer 生命周期有可追踪日志。
- DSP 队列深度、处理时延、事件触发率和 fallback 次数均可观测。
- DSP/相机服务失败时,ROS 2 节点收到明确健康状态,不把陈旧帧当实时数据。
- 在目标温度、供电和 CPU/NPU 负载下完成产品要求时长的稳定性测试。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)