一、简述
SPI Bus(Serial Peripheral Interface Bus) 最早是由Motorola(摩托罗拉)公司开发的
全双工同步串行总线。实际它并没有统一的协议规范,只是随之其广泛的应用,形成了习惯性的标准。具体的还是要参考特定的器件手册。
二、连接方式
SPI一对一
SPI用于在单个主控制器和一个或多个从设备之间交换数据。提供时钟的为主设备(Master),接收时钟的设备为从设备(Slave),对于单从设备连接使用四条信号线:
SDI(数据输入),SDO(数据输出),SCK(时钟),CS(片选)
-
MISO: 主设备输入/从设备输出引脚。该引脚在从模式下发送数据,在主模式下接收数据。
-
MOSI: 主设备输出/从设备输入引脚。该引脚在主模式下发送数据,在从模式下接收数据。
-
SCLK: 串行时钟信号,由主设备产生。
-
CS/SS: 从设备片选信号,由主设备控制。它的功能是用来作为“片选引脚”,也就是选择指定的从设备,让主设备可以单独地与特定从设备通讯,避免数据线上的冲突。
SPI一对多
三、通讯协议
当SPI主设备想读/写[从设备]时,它首先拉低[从设备]对应的SS线(SS是低电平有效),接着开始发送工作脉冲到时钟线上,在相应的脉冲时间上,[主设备]把信号发到MOSI实现“写”,同时可对MISO采样而实现“读”,如下图:
-
首先确认是mode3,即sck的下降沿发送数据,上升沿采集数据。
-
SSEL(CS)拉低,选中对应的从设备
-
SCK第奇数个边沿(下降沿),MOSI(输出)改变数据(MISO也会类似的变化),例如,如果想要输出1,则此时需要从0变为1或者保持1不变
-
SCK的偶数个边沿(上升沿),此时会采集MISO上的数据,锁存到寄存器中。
-
主次三四步,对于从设备而言,主设备的MOSI和MISO在从设备上刚好是相反的。下面会通过一个例子详细解释过程。
例:
假设主机和从机初始化就绪:并且主机的sbuff=0x72,从机的sbuff=0xC7,下面将分步对spi的8个时钟周期的数据情况演示一遍
假设CPOL为0,SCPH为0,即mode 0,上升沿发送,下降沿接收
编号
|
脉冲
|
主机sbuff
|
从机sbuff
|
MOSI
|
MISO
|
0
|
0 初始状态
|
0111 0010
|
1100 0111
|
0
|
0
|
1
|
0到1,上升沿
|
1110 010X
|
1000 111X
|
0
|
1
|
2
|
1到0,下降沿
|
1110 010
1
|
1000 111
0
|
0
|
1
|
3
|
0到1,上升沿
|
1100 101X
|
0001 110X
|
1
|
1
|
4
|
1到0,下降沿
|
1100 10
1
1
|
0001 11
0
1
|
1
|
1
|
5
|
0到1,上升沿
|
1001 011X
|
0011 101X
|
1
|
0
|
6
|
1到0,下降沿
|
1001 0
110
|
0011 1
011
|
1
|
0
|
7
|
0到1,上升沿
|
0010 110X
|
0111 011X
|
1
|
0
|
8
|
1到0,下降沿
|
0010
1100
|
0111
0111
|
1
|
0
|
9
|
0到1,上升沿
|
0101 100X
|
1110 111X
|
0
|
0
|
10
|
1到0,下降沿
|
010
1 1000
|
111
0 1110
|
0
|
0
|
11
|
0到1,上升沿
|
1011 000X
|
1101 110X
|
0
|
1
|
12
|
1到0,下降沿
|
10
11 0001
|
11
01 1100
|
0
|
1
|
13
|
0到1,上升沿
|
0110 001X
|
1011 100X
|
1
|
1
|
14
|
1到0,下降沿
|
0
110 0011
|
1
011 1001
|
1
|
1
|
15
|
0到1,上升沿
|
1100 011X
|
0111 001X
|
0
|
1
|
16
|
1到0,下降沿
|
1100 0111
|
0111 0010
|
0
|
1
|
|
... ...
|
|
|
|
|
-
首先拉低对应SS信号线,表示与该设备进行通信
-
主机通过发送SCLK时钟信号,来告诉从机写数据或者读数据。这里要注意,SCLK时钟信号可能是低电平有效,也可能是高电平有效,因为SPI有四种模式,这个我们在下面会介绍
-
主机(Master)将要发送的数据写到发送数据缓存区(Menory),缓存区经过移位寄存器(0~7),串行移位寄存器通过MOSI信号线将字节一位一位的移出去传送给从机,同时MISO接口接收到的数据经过移位寄存器一位一位的移到接收缓存区。
-
从机(Slave)也将自己的串行移位寄存器(0~7)中的内容通过MISO信号线返回给主机。同时通过MOSI信号线接收主机发送的数据,这样,两个移位寄存器中的内容就被交换。
注:
SPI只有主模式和从模式之分,没有读和写的说法,外设的写操作和读操作是同步完成的。如果只进行写操作,主机只需忽略接收到的字节;反之,若主机要读取从机的一个字节,就必须发送一个空字节来引发从机的传输。也就是说,你发一个数据必然会收到一个数据;你要收一个数据必须也要先发一个数据。
主从设备必须使用相同的工作模式——SCLK、CPOL 和 CPHA,才能正常工作。如果有多个从设备,并且它们使用了不同的工作模式,那么主设备必须在读写不同从设备时需要重新修改对应从设备的模式。以上SPI总线协议的主要内容。
他没有规定最大传输速率,没有地址方案,也没规定通信应答机制,没有规定流控制规则。
四、四种通信模式
SPI通信有4种不同的操作模式,不同的从设备可能在出厂是就是配置为某种模式,这是不能改变的;但我们的通信双方必须是工作在同一模式下,所以我们可以对我们的主设备的SPI模式进行配置,通过CPOL(时钟极性)和CPHA(时钟相位)来控制我们主设备的通信模式。
1、在主设备处于不使能或者空闲的状态下,主设备输出的从设备选择信号CS保持高电平。
2、时钟极性SCPOL参数决定串口时钟SCLK 在无效的状态下是高电平还是低电平:
(1)SCPOL=0,串口时钟(sclk)在无效的状态下保持低电平。
(2)SCPOL=1,串口时钟( sclk)在无效的状态下保持高电平。
3、时钟相位SCPH参数决定在第几个时钟变化边沿开始采样数据:
(1) SCPH=0时在第一个时钟变化沿开始发送数据。
(2) SCPH=1时在第二个时钟变化沿采样输入数据。
4、SPI 协议时序图
-
首先是四种不同的模式
-
根据不同的模式对应时序图如下(CS、 SCLK 对于主设备 SPI 为输出; spi_tx 为输出, spi_rx 为输入)
-
Mode0: 此时空闲态时,SCLK处于低电平,数据采样是在第1个边沿,也就是SCLK由低电平到高电平的跳变,所以数据采样是在上升沿(准备数据),(发送数据)数据发送是在下降沿。
-
-
Mode 1: 此时空闲态时,SCLK处于低电平,数据发送是在第1个边沿,也就是SCLK由低电平到高电平的跳变,所以数据采样是在下降沿,数据发送是在上升沿。
-
Mode 2:此时空闲态时,SCLK处于高电平,数据采集是在第1个边沿,也就是SCLK由高电平到低电平的跳变,所以数据采集是在下降沿,数据发送是在上升沿。
-
Mode 3:此时空闲态时,SCLK处于高电平,数据发送是在第1个边沿,也就是SCLK由高电平到低电平的跳变,所以数据采集是在上升沿,数据发送是在下降沿。
缺点:没有指定的流控制,没有应答机制确认是否接收到数据。
五、代码相关
kernel4.14中关于SPI接口的详细讲解见
https://www.kernel.org/doc/html/v4.14/driver-api/spi.html
以Sensor为例讲解SPI的配置:
1、sensor对于通讯方式以及GPIO等配置都在.json文件中( /vendor/qcom/proprietary/sensors-see/registry/config/product/kona_qrd_lsm6dso.json)
-
bus_type 即选择哪种传输方式,此处1代表SPI(0:I2C,1:SPI,2:UART,3:I3C)。
-
bus_instance 对应“SSC GPIO #”,根据表格我们知道,可以设置为3或者6。我们设置为3,使用的是SSC_4 - 7。对应的GPIO口是164,165,166,167。
-
slave_config 是片选时使能状态,0和1,0代表选中时为低电平,1代表选中时是高电平。
-
bus_speed_khz 代表时钟速度0-9600KHZ
TZ里想要配置可以看下如下两个文件:
/AMSS/sm8250_tz/trustzone_images/core/settings/buses/qup_accesscontrol/qupv3/config/8250/QUPAC_Access.
/AMSS/sm8250_tz/trustzone_images/core/settings/buses/spi/qupv3/config/sm8250/tz/spi_devcfg.c
/AMSS/sm8250_tz/trustzone_images/core/settings/buses/spi/qupv3/config/sm8250/tz/spi_devcfg.c