4. SPI 总线节点属性:spi-max-frequency、spi-cpha、spi-cpol、spi-cs-high 等属性配置

SPI 从设备节点的属性配置决定了控制器与设备之间的通信协议细节。这些属性必须在设备树中正确设置,以确保时序匹配、信号极性正确以及总线速率在设备允许范围内。本节将详细解析最关键的四个 SPI 属性及其配置方法。

4.1 属性概览与功能对照

下表列出了 SPI 从设备节点中最常用的属性,以及它们各自控制的硬件行为:

属性名 数据类型 默认值 功能描述
spi-max-frequency <u32> 无(必须指定) 设置 SPI 时钟(SCLK)的最高频率,单位 Hz
spi-cpha 空属性(布尔) 0(CPHA=0) 设置时钟相位:0 表示第一个边沿采样,1 表示第二个边沿采样
spi-cpol 空属性(布尔) 0(CPOL=0) 设置时钟极性:0 表示空闲时低电平,1 表示空闲时高电平
spi-cs-high 空属性(布尔) 片选低电平有效 设置片选信号为高电平有效(默认低电平有效)
spi-3wire 空属性(布尔) 标准 4 线模式 启用 3 线半双工模式(MISO 与 MOSI 共用)
spi-lsb-first 空属性(布尔) MSB 优先 设置数据以 LSB 优先方式传输
关键理解: spi-cpha 和 spi-cpol 共同定义了 SPI 的四种工作模式(Mode 0~3)。这两个属性是布尔类型,在设备树中只要出现即表示值为 1,不出现则表示值为 0。

4.2 spi-max-frequency:总线速率上限

spi-max-frequency 是每个从设备节点必须指定的属性,它告诉 SPI 控制器该从设备支持的最高时钟频率。控制器在通信时会根据此值自动分频,确保实际 SCLK 频率不超过该上限。

/* 设备树示例:为不同从设备设置不同的最大频率 */
&spi1 {
    status = "okay";
    
    temperature_sensor: sensor@0 {
        compatible = "maxim,ds18b20";
        reg = <0>;
        spi-max-frequency = <1000000>;  /* 最高 1 MHz */
    };
    
    display_controller: display@1 {
        compatible = "ilitek,ili9341";
        reg = <1>;
        spi-max-frequency = <32000000>; /* 最高 32 MHz */
    };
};
配置陷阱: 如果 spi-max-frequency 设置过高,超出从设备规格,可能导致数据采样错误、通信不稳定甚至设备损坏。建议参考芯片数据手册中的最大 SCLK 参数,并保留 10%~20% 的余量。

4.3 spi-cpha 与 spi-cpol:时钟相位与极性

这两个属性共同决定了 SPI 的四种标准模式。理解它们对正确配置至关重要:

  • CPOL(Clock Polarity):定义 SCLK 空闲时的电平状态。
    • CPOL=0:空闲时 SCLK 为低电平
    • CPOL=1:空闲时 SCLK 为高电平
  • CPHA(Clock Phase):定义数据采样发生在哪个时钟边沿。
    • CPHA=0:在第一个边沿(上升沿或下降沿)采样数据
    • CPHA=1:在第二个边沿采样数据

四种模式的组合关系如下表所示:

SPI 模式 CPOL CPHA 空闲时钟电平 数据采样边沿
Mode 0 0 0 低电平 上升沿(第一个边沿)
Mode 1 0 1 低电平 下降沿(第二个边沿)
Mode 2 1 0 高电平 下降沿(第一个边沿)
Mode 3 1 1 高电平 上升沿(第二个边沿)
/* 设备树配置示例:设置 SPI Mode 3(CPOL=1, CPHA=1) */
spi_nor_flash: flash@0 {
    compatible = "jedec,spi-nor";
    reg = <0>;
    spi-max-frequency = <50000000>;
    spi-cpol;      /* 空闲时高电平 */
    spi-cpha;      /* 第二个边沿采样 */
};
模式匹配原则: 从设备的数据手册通常会明确标注其支持的 SPI 模式(如 "SPI Mode 0 and Mode 3")。务必确保设备树中配置的模式与从设备要求的模式完全一致,否则通信将完全失败。

4.4 SPI 四种模式时序对比 SVG

下图直观展示了四种 SPI 模式下 SCLK、数据输出(MOSI)和数据采样点的时序关系:

SPI 四种模式时序对比(CPOL / CPHA) Mode 0 (CPOL=0, CPHA=0) 空闲低电平,上升沿采样 SCLK ▲ 采样 Mode 1 (CPOL=0, CPHA=1) 空闲低电平,下降沿采样 SCLK ▲ 采样 Mode 2 (CPOL=1, CPHA=0) 空闲高电平,下降沿采样 SCLK ▲ 采样 Mode 3 (CPOL=1, CPHA=1) 空闲高电平,上升沿采样 SCLK ▲ 采样 图例: SCLK 时钟线 Mode 0/2 采样点(第一个边沿) Mode 1/3 采样点(第二个边沿)

4.5 spi-cs-high:片选极性控制

SPI 总线的片选信号(CS/SS)默认是低电平有效,即 CS 引脚为低电平时选中从设备。但部分从设备要求片选信号为高电平有效。此时需要在设备树节点中添加 spi-cs-high 属性。

/* 片选高电平有效配置示例 */
spi_adc: adc@2 {
    compatible = "ti,ads1256";
    reg = <2>;
    spi-max-frequency = <19200000>;
    spi-cs-high;  /* 片选信号高电平有效 */
};
硬件兼容性注意: 并非所有 SPI 控制器都支持片选极性反转。如果控制器硬件不支持高电平有效片选,即使设备树中配置了 spi-cs-high,驱动也可能忽略该属性。此时需要通过外部逻辑电路(如反相器)进行电平转换。

4.6 属性配置完整示例与驱动匹配流程

以下是一个完整的 SPI 从设备节点配置,展示了所有关键属性的组合使用:

/* 完整 SPI 从设备节点配置示例 */
&spi2 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_spi2>;
    status = "okay";
    
    /* 从设备 0:SPI NOR Flash */
    flash: w25q128@0 {
        compatible = "winbond,w25q128", "jedec,spi-nor";
        reg = <0>;
        spi-max-frequency = <104000000>;
        spi-cpol;
        spi-cpha;
        #address-cells = <1>;
        #size-cells = <1>;
        
        partition@0 {
            label = "bootloader";
            reg = <0x00000000 0x00100000>;
        };
    };
    
    /* 从设备 1:SPI 触摸控制器 */
    touch: touch@1 {
        compatible = "focaltech,ft5426";
        reg = <1>;
        spi-max-frequency = <5000000>;
        spi-cs-high;
        interrupt-parent = <&gpio3>;
        interrupts = <19 IRQ_TYPE_EDGE_FALLING>;
    };
};

内核在枚举 SPI 从设备时,会按照以下流程匹配和配置这些属性:

  1. 解析节点:内核 SPI 核心层读取设备树中每个从设备子节点。
  2. 提取属性:调用 of_spi_parse_dt() 函数解析 spi-max-frequency、spi-cpol、spi-cpha、spi-cs-high 等属性。
  3. 填充结构体:将解析结果写入 struct spi_device 的对应字段(max_speed_hz、mode 等)。
  4. 控制器配置:SPI 控制器驱动根据 spi_device 中的模式信息,配置硬件寄存器(时钟分频、极性、相位、片选极性)。
  5. 设备注册:将配置好的 spi_device 注册到 SPI 总线,触发匹配对应的从设备驱动。
内核源码参考: 属性解析的核心函数位于 drivers/spi/spi.c 中的 of_spi_parse_dt()。该函数通过 of_property_read_u32() 读取 spi-max-frequency,通过 of_property_read_bool() 读取布尔类型的模式属性。

4.7 属性配置与驱动匹配流程 SVG

下图展示了从设备树解析到 SPI 设备注册的完整数据流:

SPI 从设备属性解析与驱动匹配流程 设备树节点 spi-max-frequency / cpol / cpha of_spi_parse_dt() 解析属性 → 填充 spi_device struct spi_device max_speed_hz / mode 字段 SPI 控制器硬件配置 时钟分频 / 极性寄存器 / 片选极性 SPI 总线设备注册 匹配 compatible → probe() SPI 数据传输 使用配置的模式进行通信 关键函数调用链 spi_register_controller()