SPI外设驱动与DMA传输结合内存映射性能调优 - 第1节

1.1 SPI 总线架构与四线制工作原理

SPI(Serial Peripheral Interface,串行外设接口)是一种由 Motorola 公司推出的全双工、同步、主从式串行通信总线。在嵌入式系统中,SPI 凭借其极低的引脚开销(仅需 4 根线)和高达数十 MHz 的时钟速率,成为连接传感器、ADC/DAC、LCD 控制器、Flash 存储器等外设的首选接口之一。

1.1.1 总线拓扑结构

SPI 总线采用主-从(Master-Slave)架构。一个 SPI 主设备(通常是 MCU 或 SoC)可以连接一个或多个从设备。根据从设备的片选信号连接方式,分为两种典型拓扑:

拓扑类型 连接方式 优点 缺点
独立片选(标准模式) 每个从设备独占一根 CS 线,SCLK/MOSI/MISO 共享 从设备完全独立,支持任意组合 从设备数量受限于主设备 GPIO 引脚数
菊花链(Daisy-Chain) 所有从设备共享 CS,数据从主设备经第一个从设备依次传递 节省 CS 引脚,适合大量同型号设备 延迟累加,仅支持支持菊花链模式的设备
💡 驱动开发要点: 在 Linux 内核中,独立片选模式通过 struct spi_device 的 chip_select 字段标识;菊花链模式则需要驱动层手动处理数据帧的拼接与拆分,通常不推荐在性能敏感场景中使用。

1.1.2 四线制信号定义

SPI 总线使用四根信号线完成全双工通信,每根线的角色在通信过程中是固定的:

  • SCLK(Serial Clock) —— 串行时钟,由主设备产生,决定数据传输的比特率。每个时钟脉冲传输 1 bit 数据。
  • MOSI(Master Out Slave In) —— 主设备输出、从设备输入。数据从主设备流向从设备。
  • MISO(Master In Slave Out) —— 主设备输入、从设备输出。数据从从设备流向主设备。
  • CS(Chip Select) —— 片选信号,由主设备控制,低电平有效(大多数器件)。选中从设备后,该设备才能参与通信。
🔧 硬件设计提示: 在高速 SPI(≥ 20 MHz)布线时,SCLK 与 MOSI/MISO 应保持等长,且 CS 信号建议使用独立的 GPIO 而非共享,以避免信号串扰导致的误触发。

1.1.3 SPI 全双工通信流程

SPI 的每一次数据传输都是同步且全双工的:主设备在 SCLK 的每个时钟周期同时发送 1 bit(通过 MOSI)并接收 1 bit(通过 MISO)。下图展示了单次 8-bit 传输的典型时序:

SPI 四线制 8-bit 数据传输时序图 SPI 四线制 8-bit 数据传输时序(CPOL=0, CPHA=0) CS CS 拉低(选中从设备) SCLK 0 1 2 3 4 5 6 7 MOSI D7 D6 D5 D4 D3 D2 D1 D0 MISO Q7 Q6 Q5 Q4 Q3 Q2 Q1 Q0 在 SCLK 第一个跳变沿(上升沿)采样数据,MOSI 与 MISO 同时传输
⚠️ 常见误区: 初学者常误以为 SPI 的 MOSI 和 MISO 是分时复用的。实际上,SPI 是真正的全双工——主设备在发送一个字节的同时,也在接收从设备返回的一个字节。如果从设备没有数据返回,MISO 通常保持高阻态或返回 0xFF。

1.2 时钟极性(CPOL)与相位(CPHA)详解

SPI 协议定义了四种工作模式,由时钟极性(CPOL)和时钟相位(CPHA)两个参数组合决定。这两个参数决定了 SCLK 空闲时的电平状态以及数据采样/切换的边沿时刻。主设备和从设备必须使用相同的模式才能正常通信。

1.2.1 CPOL 与 CPHA 的定义

参数 取值 含义
CPOL 0 SCLK 空闲时为低电平(低电平有效)
CPOL 1 SCLK 空闲时为高电平(高电平有效)
CPHA 0 数据在 SCLK 的第一个跳变沿(上升沿或下降沿)被采样
CPHA 1 数据在 SCLK 的第二个跳变沿被采样
📘 内核对应关系: 在 Linux SPI 子系统中,struct spi_device 的 mode 字段通过 SPI_CPOL 和 SPI_CPHA 标志位设置模式。例如:spi->mode = SPI_MODE_0 对应 CPOL=0, CPHA=0。

1.2.2 四种 SPI 模式对比

将 CPOL 和 CPHA 组合,得到 SPI 的四种标准模式。下表总结了每种模式的特点和典型应用场景:

模式 CPOL CPHA 空闲电平 数据采样边沿 典型器件
SPI Mode 0 0 0 低电平 第一个边沿(上升沿) W25Qxx Flash, MCP3008 ADC
SPI Mode 1 0 1 低电平 第二个边沿(下降沿) 某些 SD 卡、CC1101 射频模块
SPI Mode 2 1 0 高电平 第一个边沿(下降沿) 某些 LCD 控制器、MAX31865 温度传感器
SPI Mode 3 1 1 高电平 第二个边沿(上升沿) Microchip ENC28J60 以太网控制器

1.2.3 四种模式的时序对比图

下面的 SVG 图直观展示了四种模式下 SCLK 与数据采样的关系。注意观察空闲电平以及数据采样点的位置差异:

SPI 四种模式时序对比图 SPI 四种模式(Mode 0 ~ Mode 3)时序对比 Mode 0 CPOL=0, CPHA=0 ↑ ↓ ↑ ↓ 空闲低,上升沿采样 Mode 1 CPOL=0, CPHA=1 ↑ ↓ ↑ ↓ 空闲低,下降沿采样 Mode 2 CPOL=1, CPHA=0 ↓ ↑ ↓ ↑ 空闲高,下降沿采样 Mode 3 CPOL=1, CPHA=1 ↓ ↑ ↓ ↑ 空闲高,上升沿采样 🔍 采样边沿规律:CPHA=0 时采样第一个边沿,CPHA=1 时采样第二个边沿 空闲电平由 CPOL 决定:CPOL=0 空闲低,CPOL=1 空闲高 数据线 D7 D6 D5 D4 数据在采样边沿被锁存

1.2.4 驱动开发中的模式配置

在 Linux 内核 SPI 驱动中,模式配置通常在设备树(Device Tree)或板级代码中完成。以下是一个典型的设备树配置示例:

/* 设备树中 SPI 从设备节点配置 */
&spi1 {
    status = "okay";
    cs-gpios = <&gpio3 20 GPIO_ACTIVE_LOW>;

    flash: w25q128@0 {
        compatible = "winbond,w25q128";
        reg = <0>;                 /* CS 索引 0 */
        spi-max-frequency = <50000000>;  /* 50 MHz */
        spi-cpol;                  /* CPOL = 1 */
        spi-cpha;                  /* CPHA = 1 */
        /* 等效于 SPI Mode 3 */
    };
};
🔧 调试技巧: 如果通信出现乱码或数据错位,首先检查 CPOL/CPHA 是否匹配。可以使用逻辑分析仪抓取 SCLK 和 MOSI/MISO 波形,对照数据手册确认采样边沿。在 Linux 中,可以通过 /sys/bus/spi/devices/.../modalias 查看当前模式。

1.3 SPI 通信的典型时序与数据帧结构

一次完整的 SPI 传输通常包含以下步骤:

  1. 片选(CS)拉低:主设备将对应从设备的 CS 引脚置为低电平,激活从设备。
  2. 时钟启动:主设备在 SCLK 线上产生连续的时钟脉冲。
  3. 数据交换:在每个时钟周期,主设备通过 MOSI 发送 1 bit,同时从设备通过 MISO 返回 1 bit。
  4. 传输结束:主设备停止 SCLK,并将 CS 拉高,释放从设备。

数据帧的长度通常是 8 位(1 字节),但许多现代 SPI 器件支持 16 位、32 位甚至可变长度帧。在 Linux SPI 子系统中,struct spi_transfer 的 bits_per_word 字段用于指定每帧的位数:

struct spi_transfer t = {
    .tx_buf = tx_data,        /* 发送缓冲区 */
    .rx_buf = rx_data,        /* 接收缓冲区 */
    .len = 4,                 /* 传输 4 字节 */
    .bits_per_word = 16,      /* 每帧 16 位 */
    .speed_hz = 20000000,     /* 20 MHz */
    .cs_change = 0,           /* 传输结束后不改变 CS */
};
📊 性能指标: 在 50 MHz 时钟、8 位帧格式下,SPI 的理论最大吞吐量为 50 Mbps(全双工)。实际有效吞吐量受 CS 切换开销、中断延迟和 DMA 配置影响,通常为理论值的 70%~90%。

1.4 本章小结

  • SPI 总线采用主-从架构,四线制(SCLK、MOSI、MISO、CS)实现全双工同步通信。
  • 时钟极性(CPOL)决定空闲电平,时钟相位(CPHA)决定数据采样边沿,两者组合定义四种 SPI 模式。
  • 主设备和从设备必须使用相同的 SPI 模式,否则通信将失败。
  • 在 Linux 内核中,通过设备树的 spi-cpol 和 spi-cpha 属性或 spi->mode 标志位配置模式。
  • 理解 SPI 时序是后续实现 DMA 传输和内存映射性能调优的基础。