4. 设备树中SPI节点配置:SPI控制器节点、SPI从设备节点、reg属性、spi-max-frequency等关键属性
在Linux内核中,SPI总线设备的硬件拓扑与配置参数通过设备树(Device Tree)进行描述。设备树为驱动提供了与硬件解耦的静态描述机制,使得同一份内核镜像可以适配不同板级配置。SPI设备树节点主要分为两类:SPI控制器节点(描述SoC内部的SPI主机控制器)和SPI从设备节点(描述挂载在SPI总线上的外设)。正确配置这些节点是SPI通信正常工作的前提。
binding文档。错误的reg值或缺失的spi-max-frequency属性是导致SPI通信失败的最常见原因之一。
4.1 SPI控制器节点
SPI控制器节点通常位于SoC的soc或ahb总线节点下,描述了SPI主机控制器的寄存器基址、中断号、时钟源、DMA请求线以及Pinctrl配置。控制器节点是SPI子系统的根节点,所有挂载在该控制器下的从设备节点都必须作为其子节点存在。
以下是一个典型的SPI控制器节点示例(以i.MX6ULL为例):
&ecspi1 {
pinctrl-names = "default";
pinctrl-0 = &pinctrl_ecspi1;
cs-gpios = <&gpio4 9 GPIO_ACTIVE_LOW>;
status = "okay";
spidev0: spidev@0 {
compatible = "spidev";
reg = <0>;
spi-max-frequency = <1000000>;
};
};
控制器节点关键属性说明:
| 属性名 | 类型 | 说明 | 是否必须 |
|---|---|---|---|
compatible |
字符串 | 匹配驱动,如"fsl,imx6ul-ecspi" |
是 |
reg |
u32数组 | 控制器寄存器基址和长度 | 是 |
interrupts |
u32数组 | SPI中断号及触发类型 | 是 |
clocks |
phandle数组 | SPI模块时钟和PIO时钟 | 是 |
pinctrl-0 |
phandle | 引脚复用配置 | 推荐 |
cs-gpios |
gpio数组 | 片选GPIO列表(软件片选模式) | 可选 |
dmas |
phandle数组 | DMA传输通道 | 可选 |
status |
字符串 | "okay"或"disabled" |
是 |
pinctrl配置,内核将无法正确配置SCLK、MOSI、MISO和CS引脚的复用功能,导致SPI总线无时钟输出。检查/sys/kernel/debug/gpio和cat /sys/kernel/debug/pinctrl/*/pinmux-pins可以验证引脚状态。
4.2 SPI从设备节点
SPI从设备节点描述了挂载在SPI总线上的具体外设。每个从设备节点必须包含compatible、reg和spi-max-frequency三个核心属性。从设备节点是驱动匹配的入口,内核通过compatible属性查找对应的SPI设备驱动。
从设备节点典型结构:
&ecspi1 {
status = "okay";
/* 第一个从设备:温度传感器 */
temp_sensor: max31865@0 {
compatible = "maxim,max31865";
reg = <0>;
spi-max-frequency = <5000000>;
spi-cpha;
spi-cpol;
status = "okay";
};
/* 第二个从设备:ADC转换器 */
adc_device: ads1256@1 {
compatible = "ti,ads1256";
reg = <1>;
spi-max-frequency = <19200000>;
interrupts-extended = <&gpio5 19 IRQ_TYPE_EDGE_FALLING>;
status = "okay";
};
};
4.3 reg属性详解
reg属性在SPI从设备节点中表示该设备使用的片选(Chip Select, CS)索引号。SPI控制器通常支持多个片选信号(CS0、CS1、CS2...),每个片选对应一条独立的硬件CS线。内核通过解析reg值来确定在发起SPI传输时应该拉低哪条CS线。
| reg值 | 对应片选 | 典型硬件连接 | 注意事项 |
|---|---|---|---|
0 |
CS0 | 连接从设备的CS引脚 | 大多数SPI控制器默认支持CS0 |
1 |
CS1 | 连接第二个从设备的CS引脚 | 需要控制器硬件支持多片选 |
2 |
CS2 | 连接第三个从设备的CS引脚 | 部分控制器通过GPIO模拟扩展 |
reg值(例如都设为0),内核在注册SPI设备时会报错:spi_master spi0: chipselect 0 already in use。此时第二个设备将无法注册成功。务必确保每个从设备的reg值在同一个控制器下唯一。
4.4 spi-max-frequency属性
spi-max-frequency定义了该从设备支持的最高SPI时钟频率,单位是Hz。内核SPI核心层在初始化传输时会读取该属性,并将其作为SCLK频率的上限。实际传输频率由控制器驱动根据硬件能力向下取整。
频率配置原则:
- 不能超过控制器支持的最高频率:例如i.MX6ULL的ECSPI最高频率为60MHz,设置
spi-max-frequency = <100000000>会被内核自动截断。 - 不能超过从设备数据手册规定的最高频率:例如某SPI Flash最高支持50MHz,设置80MHz会导致通信不稳定或数据错误。
- 频率越低,信号完整性越好:在长距离传输或高噪声环境下,适当降低频率可以提高通信可靠性。
/* 频率配置示例 */
/* 低速传感器,最高1MHz */
spi-max-frequency = <1000000>;
/* 高速SPI Flash,最高50MHz */
spi-max-frequency = <50000000>;
/* 调试阶段建议使用较低频率,排除时序问题 */
spi-max-frequency = <500000>; /* 500KHz,适合调试 */
4.5 SPI模式属性(spi-cpha / spi-cpol)
SPI有四种工作模式,由时钟极性(CPOL)和时钟相位(CPHA)组合决定。设备树通过以下布尔属性配置SPI模式:
| 属性 | 含义 | SPI模式 | 典型设备 |
|---|---|---|---|
| 无(默认) | CPOL=0, CPHA=0 | 模式0 | 多数SPI Flash、SD卡 |
spi-cpha |
CPOL=0, CPHA=1 | 模式1 | 部分ADC、DAC |
spi-cpol |
CPOL=1, CPHA=0 | 模式2 | 某些温度传感器 |
spi-cpol; spi-cpha; |
CPOL=1, CPHA=1 | 模式3 | 部分MEMS传感器 |
/* 模式3配置示例 */
spi-cpol; /* 时钟空闲时为高电平 */
spi-cpha; /* 数据在时钟的第二个边沿采样 */
4.6 其他关键属性
除了上述核心属性外,SPI从设备节点还支持以下常用属性:
spi-cs-high:片选信号高电平有效(默认低电平有效)。某些设备要求CS在高电平时被选中。spi-3wire:使用三线制SPI(省略MISO或MOSI),适用于半双工设备。spi-lsb-first:数据以LSB(最低有效位)优先传输(默认MSB优先)。spi-rx-bus-width和spi-tx-bus-width:用于Quad SPI或Dual SPI模式,设置数据线宽度。interrupts或interrupts-extended:从设备的中断引脚,用于事件通知。
/* 完整配置示例:使用四线SPI的Flash设备 */
spi_flash: flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <80000000>;
spi-rx-bus-width = <4>; /* Quad SPI读取 */
spi-tx-bus-width = <4>; /* Quad SPI写入 */
spi-cpol;
spi-cpha;
m25p,fast-read;
status = "okay";
};
4.7 常见配置错误与排查方法
设备树SPI节点配置错误会导致驱动无法加载或通信异常。以下汇总了最常见的错误场景及排查方法:
| 错误现象 | 可能原因 | 排查方法 |
|---|---|---|
| 驱动probe不执行 | compatible不匹配或status不是"okay" | 检查/sys/bus/spi/devices目录是否存在设备节点 |
| SPI时钟无输出 | pinctrl配置缺失或错误 | 检查/sys/kernel/debug/pinctrl引脚复用状态 |
| 数据全部为0xFF | 片选未正确拉低或MISO连接错误 | 用示波器测量CS和MISO引脚电平 |
| 数据错位 | SPI模式(CPOL/CPHA)不匹配 | 逻辑分析仪抓取波形,对比数据手册时序 |
| 传输超时 | spi-max-frequency过高或DMA配置错误 | 降低频率测试,关闭DMA使用PIO模式 |
| 设备注册失败 | reg值冲突或控制器节点status为disabled | 查看dmesg中spi_master相关错误日志 |
ls /sys/bus/spi/devices/查看已注册的SPI设备。如果设备节点存在但驱动未绑定,执行cat /sys/bus/spi/devices/spi0.0/modalias查看内核匹配的驱动名称,与设备树中的compatible对比。