Duke's Blog

Learning is a life long journey.

Subscribe

SPI 延迟补偿

SPI 是一种非常基础的同步通讯接口,广泛用于各种电路,譬如 MCU 和数模转换芯片、传感器芯片、存储芯片、通讯控制器芯片和显示器的通讯等。

然而 SPI 高速传输以及远距离传输面临了很多挑战,其中一个比较关键的问题是 SPI 从机回复数据的延迟会导致通讯不稳定和出错。

这里的延迟包含以下几种: 1. 主机发送出时钟到从机接收到时钟的传输延迟 2. 从机收到时钟到输出数据的本地处理延迟 3. 从机输出数据到主机读取数据之间的传输延迟 4. 传输通路中可能会增加一些驱动增强芯片、单端和差分转换芯片,或者是隔离等芯片,这些芯片加大了两个方向的传输延迟。

在 SPI 总线上,CPOL(极性)和 CPHA(相位)的不同配置形成了 SPI 数据传输的 4 种模式,以下使用 CPOL CPHA 都为 0 的模式 0 进行举例说明。

图1:

SPI 模式 0,主机和从机都是在 SCK 的上升沿采样数据,其中 SS (或 CS)、SCK、SDI (或 MOSI) 都是主机发送出来的数据,相互之间几乎没有延迟。 而 SDO (或 MISO) 是从机输出的数据,为了让主机在 SCK 的上升沿正确采样数据,SDO 是在 SCK 相应的下降沿开始输出,由于存在上述各种延迟,会稍微滞后,滞后时间对应图中 Td.

图1 中的延迟相对 SCK 时钟来说不算很大,不会影响主机采样,譬如在 Tc 时刻采样 D7 数据,基本还是在 D7 的中间附近采样。

但如果 SPI 的 SCK 时钟提高,或传输延迟加大,则对于主机来说,波形为下图:

图2:

此时,同样在 Tc 时刻,采样不到正确的 D7 数据。

这种情况下,和 SPI 类似的 QSPI 采取的方案是:主机延迟半个时钟周期采样 SDO 数据,也就是在 Tc 右侧的 SCK 下降沿采样。

然而,SPI 主控几乎没有支持推迟采样的功能,且推迟采样会增加传输完成的时间,效率低。

本文提出一种从机端提前半个时钟周期输出 SPI 数据的方法,可以更高效解决 SPI 回复数据延迟导致通讯出错的问题。

具体实施如下:

图3:

从机提前到 Tc 左则的 SCK 上升沿开始输出 SDO 数据,后续每个 SCK 的上升沿更新 SDO 数据。

虽然目标是提前输出 SDO 数据,示例中 SPI 最小传输单元为 8 个位,从机在首传输单元最后一个位的上升沿才完整读到主机下发的地址或命令,此时无法立即输出该地址或命令对应的数据,因为处理数据需要时间。

所以,具体实施的方法是,牺牲主机下发的最后一个位,譬如原本最高位为读写选择,低 7 位为命令,现在改为中间 6 位为命令,最低位忽略不使用(图中 X 表示忽略)。

这样还有一个好处,原本从其收到完整命令到输出数据只有半个 SCK 周期的时间做准备,而现在有一个完整的 SCK 周期,从机芯片内部电路从而也可以支持更高频率的 SCK 时钟。

使用该方法制作出来的从机,可以适配普通 SPI 主控,意义重大。

是否提前半个 SCK 周期输出 SDO 数据,从机也可以动态配置,譬如从机刚上电默认不提前,用户配置相应寄存器后,启用提前模式。

对于延迟超大的情形,可以在使用此方法的情况下,同时在主机端再延迟半个周期采样 SDO 数据。

有些器件,譬如 TI 的 ADS8684 也使用了 SDO 提前半个时钟周期输出的方式,但由于很难在收到完整命令的瞬间输出数据,所以当前命令对应的数据要等到下一次 SPI 传输才输出,这样命令的实效性就很低了。

本文具体实现的 verilog 代码可以参见 https://github.com/dukelec/cdbus 的 next 分支,代码位于 example 目录下。
该工程是 CDBUS 控制器芯片譬如 CDCTL01A 的源码,它可以让 RS485 支持仲裁等功能,实现多主机、对等通讯,打破只能轮询的限制, 更多信息可以参见:https://github.com/dukelec/cdbus_doc 。


Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License.

Comments:


Please visit the original link: /spi-delay-compensation-cn