4. SPI设备树绑定:设备树节点语法、compatible属性、reg属性、spi-max-frequency等关键属性
在嵌入式Linux系统中,设备树(Device Tree)是描述硬件拓扑结构的核心机制。对于SPI设备驱动而言,设备树节点是驱动与硬件之间的“契约”——驱动通过解析设备树节点获取SPI从设备的地址、最大频率、工作模式等关键参数。本章将深入剖析SPI设备树绑定的语法规则与关键属性。
核心概念:设备树节点中的SPI子节点必须遵循特定的绑定规范,否则驱动无法正确识别和配置SPI从设备。错误的绑定可能导致设备无法枚举、数据传输失败甚至系统崩溃。
4.1 SPI设备树节点语法
SPI控制器节点下的每个子节点代表一个挂载在该SPI总线上的从设备。其基本语法结构如下:
spi_controller: spi@xxxxxxx {
compatible = "vendor,spi-controller";
reg = <0x...>;
#address-cells = <1>;
#size-cells = <0>;
/* SPI控制器属性 */
spi_device0: device@0 {
compatible = "vendor,spi-device";
reg = <0>; /* 片选编号,必须 */
spi-max-frequency = <1000000>; /* 最大SPI时钟频率,必须 */
/* 可选属性:spi-cpha, spi-cpol, spi-cs-high 等 */
};
spi_device1: device@1 {
compatible = "vendor,another-device";
reg = <1>;
spi-max-frequency = <5000000>;
spi-cpha; /* 相位模式1 */
spi-cpol; /* 极性模式1 */
};
};
语法要点:
- 节点命名:子节点名称通常为
device@片选编号,如adc@0、sensor@1。 - #address-cells = <1>; #size-cells = <0>;:表示子节点的
reg属性只包含一个地址(片选号),没有长度字段。 - 子节点顺序:设备树中的子节点顺序不影响实际片选优先级,片选由
reg属性值决定。
4.2 compatible属性:驱动匹配的关键
compatible 属性是设备树节点与驱动进行匹配的“身份证”。SPI驱动通过该属性值在设备树中查找对应的设备节点,并建立绑定关系。
| 属性格式 | 示例 | 说明 |
|---|---|---|
"厂商,设备型号" |
"ti,ads1256" |
标准格式,厂商前缀+设备型号,驱动优先匹配此值 |
"通用设备类型" |
"spidev" |
通用兼容性标识,用于用户空间SPI设备驱动 |
多值列表 |
"ti,ads1256", "generic-adc" |
按优先级从高到低列出兼容设备,驱动依次尝试匹配 |
常见错误:compatible 属性值必须与驱动中
of_match_table 定义的字符串完全一致(包括大小写和标点)。例如,驱动中写 "ti,ads1256",设备树中写 "ti,ADS1256" 将导致匹配失败。
驱动端匹配代码示例:
static const struct of_device_id spi_device_of_match[] = {
{ .compatible = "ti,ads1256", .data = &ads1256_config },
{ .compatible = "maxim,max31865", .data = &max31865_config },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, spi_device_of_match);
static int spi_device_probe(struct spi_device *spi)
{
const struct of_device_id *match;
match = of_match_device(spi_device_of_match, &spi->dev);
if (match) {
/* 根据 match->data 进行设备初始化 */
}
return 0;
}
4.3 reg属性:片选地址与总线位置
reg 属性在SPI子节点中用于指定从设备在SPI总线上的片选编号。该编号直接对应硬件上SPI控制器输出的片选信号(CSn)。
- 单片选设备:
reg = <0>;—— 使用片选信号 CS0。 - 多片选设备:某些SPI控制器支持多个片选,如
reg = <2>;表示使用 CS2。 - 地址单元:由父节点的
#address-cells决定,通常为1(一个32位整数表示片选号)。 - 大小单元:由父节点的
#size-cells决定,通常为0(无长度字段)。
注意事项:
- 同一SPI控制器下的子节点,
reg值不能重复,否则会导致设备注册冲突。 - 某些SPI控制器支持“多片选”模式,此时
reg可能包含多个地址,需参考具体控制器的绑定文档。 - 如果硬件上片选信号是低电平有效,设备树中通常不需要额外配置,由SPI控制器硬件自动处理。
4.4 spi-max-frequency属性:时钟频率上限
spi-max-frequency 属性定义了SPI从设备所能支持的最大时钟频率(单位:Hz)。SPI控制器在初始化时会根据此属性设置SCLK频率,确保不超过从设备的额定值。
| 属性值 | 实际频率 | 适用场景 |
|---|---|---|
<1000000> |
1 MHz | 低速传感器、ADC、温度芯片 |
<5000000> |
5 MHz | 中速数据转换器、存储器 |
<20000000> |
20 MHz | 高速ADC、DAC、FPGA配置 |
<50000000> |
50 MHz | 高速存储器、显示控制器 |
驱动行为:SPI核心框架在
spi_setup() 函数中读取 spi-max-frequency,并将其赋值给 spi_device->max_speed_hz。驱动在后续数据传输中应确保实际使用的频率不超过此值。
驱动中读取频率的典型代码:
static int spi_device_probe(struct spi_device *spi)
{
u32 max_freq;
/* 设备树解析时已自动设置 spi->max_speed_hz */
dev_info(&spi->dev, "SPI device max frequency: %u Hz\n", spi->max_speed_hz);
/* 驱动可以进一步限制频率 */
if (spi->max_speed_hz > 5000000) {
dev_warn(&spi->dev, "Limiting frequency to 5 MHz\n");
spi->max_speed_hz = 5000000;
}
return 0;
}
4.5 SPI模式属性:cpha、cpol与cs-high
除了频率,SPI设备还需要配置时钟极性(CPOL)和时钟相位(CPHA),以及片选信号的有效电平。这些属性在设备树中以布尔标志或整数值的形式存在。
| 设备树属性 | 对应SPI模式位 | 说明 |
|---|---|---|
spi-cpha |
SPI_CPHA | 时钟相位:1表示数据在第二个时钟边沿采样,0表示第一个边沿 |
spi-cpol |
SPI_CPOL | 时钟极性:1表示空闲时时钟为高电平,0表示空闲时为低电平 |
spi-cs-high |
SPI_CS_HIGH | 片选信号高电平有效(默认低电平有效) |
spi-3wire |
SPI_3WIRE | 三线模式:MISO和MOSI共用一条数据线 |
spi-lsb-first |
SPI_LSB_FIRST | LSB优先传输(默认MSB优先) |
SPI模式组合与设备树配置示例:
/* SPI模式0:CPOL=0, CPHA=0 */
device@0 {
compatible = "vendor,device-mode0";
reg = <0>;
spi-max-frequency = <1000000>;
/* 不设置 spi-cpol 和 spi-cpha,默认模式0 */
};
/* SPI模式3:CPOL=1, CPHA=1 */
device@1 {
compatible = "vendor,device-mode3";
reg = <1>;
spi-max-frequency = <5000000>;
spi-cpol;
spi-cpha;
};
/* 片选高电平有效 */
device@2 {
compatible = "vendor,device-cs-high";
reg = <2>;
spi-max-frequency = <2000000>;
spi-cs-high;
};
注意:如果设备树中同时设置了
spi-cpol 和 spi-cpha,驱动将组合成对应的SPI模式(0/1/2/3)。如果从设备数据手册要求特定模式,务必在设备树中正确配置,否则可能导致通信失败。
4.6 完整SPI设备树绑定示例
以下是一个完整的SPI设备树绑定示例,包含多个从设备及其关键属性:
&spi1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>;
/* 温度传感器:MAX31865 */
temp_sensor: max31865@0 {
compatible = "maxim,max31865";
reg = <0>;
spi-max-frequency = <5000000>;
spi-cpha;
spi-cpol;
/* 可选:中断引脚 */
interrupts = <&gpio3 15 IRQ_TYPE_EDGE_FALLING>;
};
/* ADC:ADS1256 */
adc: ads1256@1 {
compatible = "ti,ads1256";
reg = <1>;
spi-max-frequency = <19200000>;
spi-cpol;
/* 参考电压配置 */
vref-supply = <&vref_2_5v>;
};
/* 用户空间SPI设备(spidev) */
spidev@2 {
compatible = "spidev";
reg = <2>;
spi-max-frequency = <10000000>;
};
};
关键点总结:
- compatible:驱动匹配的唯一标识,必须与驱动中的
of_match_table一致。 - reg:片选编号,决定硬件CS信号,同一控制器下不能重复。
- spi-max-frequency:从设备最大时钟频率,驱动应遵守此上限。
- spi-cpol/spi-cpha:定义SPI模式,必须与从设备数据手册一致。
- spi-cs-high:片选极性,默认低电平有效,特殊设备需配置。
4.7 常见绑定错误与调试方法
在实际开发中,SPI设备树绑定错误是导致驱动无法正常工作的常见原因。以下列出典型错误及其排查方法:
| 错误现象 | 可能原因 | 排查方法 |
|---|---|---|
| 驱动 probe 未调用 | compatible 不匹配 | 检查 /sys/firmware/devicetree/base/.../compatible 内容 |
| SPI设备未注册 | reg 值冲突或超出范围 | 查看内核日志 dmesg | grep spi |
| 数据传输错误 | spi-max-frequency 过高或模式错误 | 使用逻辑分析仪抓取SPI波形 |
| 片选信号异常 | spi-cs-high 配置错误 | 检查设备树中片选极性设置 |
| 设备树编译错误 | 语法错误或缺少必要属性 | 使用 dtc -I dts -O dtb 编译检查 |
调试技巧:在
/sys/kernel/debug/spi/ 目录下可以查看已注册的SPI设备信息,包括片选、频率、模式等。使用 cat /sys/kernel/debug/spi/spiX/spiX.Y 查看具体设备参数。
通过本章的学习,你应该能够熟练编写SPI设备树节点,正确配置compatible、reg、spi-max-frequency等关键属性,并理解这些属性如何影响驱动的匹配与初始化过程。掌握设备树绑定是SPI驱动开发的基础,也是后续实现高效数据传输的前提。