SPI基础
#
SPI基础知识硬件连接:
SCK:时钟线
DO(MOSI):数据输出
DI(MISO):数据输入
CSx:片选信号
示例如下:在每一个时钟周期传输数据
问题:
SCK的初始电平? CPOL 极性
SCK的第1 or 2个边沿传输数据? CPHA 相位
CPOL | CPHA | 模式 | 含义 |
---|---|---|---|
0 | 0 | 0 | SPI CLK初始电平为低电平,在第一个时钟沿采样数据 |
0 | 1 | 1 | SPI CLK初始电平为低电平,在第二个时钟沿采样数据 |
1 | 0 | 2 | SPI CLK初始电平为高电平,在第一个时钟沿采样数据 |
1 | 1 | 3 | SPI CLK初始电平为高电平,在第二个时钟沿采样数据 |
我们常用的是模式0和模式3,因为它们都是在上升沿采样数据,不用去在乎时钟的初始电平是什么,只要在上升沿采集数据就行。
SPI控制器内部框图:
在控制寄存器里可以设置极性和相位;状态寄存器可以分辨数据是否发送完成,或使能中断等等
波特率寄存器,设置时钟频率;数据寄存器,把要发送的数据写入数据寄存器即可
SPI控制器有驱动程序,提供SPI的传输能力。
SPI设备也有自己的驱动程序,提供SPI设备的访问能力:
- 它知道怎么访问这个设备,它知道这个设备的数据含义是什么
- 它会调用SPI控制器的函数来收发数据。
内核SPI设备驱动:
#
SPI数据结构#
SPI控制器Linux中使用spi_master结构体描述SPI控制器,里面最重要的成员就是transfer
函数指针:
#
SPI设备Linux中使用spi_device结构体描述SPI设备,里面记录有设备的片选引脚、频率、挂在哪个SPI控制器下面:
#
SPI设备驱动Linux中使用spi_driver结构体描述SPI设备驱动:
#
SPI驱动框架SPI控制器的驱动程序基于"平台总线设备驱动"模型来实现:
- 在设备树里描述SPI控制器的硬件信息,在设备树子节点里描述挂在下面的SPI设备的信息
- 在platform_driver中提供一个probe函数
- 它会注册一个spi_master
- 还会解析设备树子节点,创建spi_device结构体
跟"平台总线设备驱动模型"类似,Linux中也有一个"SPI总线设备驱动模型":
- 左边是spi_driver,使用C文件实现,里面有id_table表示能支持哪些SPI设备,有probe函数
- 右边是spi_device,用来描述SPI设备,比如它的片选引脚、频率
- 可以来自设备树:比如由SPI控制器驱动程序解析设备树后创建、注册spi_device
- 可以来自C文件:比如使用
spi_register_board_info
创建、注册spi_device
在I2C设备模型中,我们直接使用了I2C总线设备模型,为什么?
#
SPI设备树的处理过程设备树示例:
spi@f00
表示一个spi_master
#address-cells 表示描述地址的cells数量;#size-cells 表示地址长度
compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
对应一个spi_master driver驱动程序
cs-gpios = <&gpio1 0 0>, <&gpio1 1 0>, <&gpio1 2 0>;
表示片选引脚,一一对应
ethernet-switch@0
和codec@1
是两个spi子节点,分别对应一个SPI设备,这个SPI设备连接在该SPI Master下面
子节点的属性:
前三个属性是必须的,其余属性是可选的空属性
,需要时直接写上即可,不写默认为0,写了为1,如spi-cpol;
1.上述的SPI节点会在platform_driver中,即spi_master驱动
构造成一个spi_master
解析子节点,构造spi_device
spi_device结构体:
各个成员含义如下:
max_speed_hz
:该设备能支持的SPI时钟最大值chip_select
:是这个spi_master下的第几个设备- 在spi_master中有一个cs_gpios数组,里面存放有下面各个spi设备的片选引脚
- spi_device的片选引脚就是:
cs_gpios[spi_device.chip_select]
cs_gpio
:这是可选项,也可以把spi_device的片选引脚记录在这里bits_per_word
:每个基本的SPI传输涉及多少位(不是来自于设备树,来自应用程序,传输的时候可以设置它)- word:我们使用SPI控制器时,一般是往某个寄存器里写入数据,SPI控制器就会把这些数据一位一位地发送出去
- 一个寄存器是32位的,被称为一个word(有时候也称为double word)
- 这个寄存器里多少位会被发送出去?使用bits_per_word来表示
- 扩展:bits_per_word是可以大于32的,也就是每次SPI传输可能会发送多于32位的数据,这适用于DMA突发传输
mode
:含义广泛,看看结构体里那些宏- SPI_CPHA:在第1个周期采样,在第2个周期采样?
- SPI_CPOL:平时时钟极性
- SPI_CPHA和SPI_CPOL组合起来就可以得到4种模式
- SPI_MODE_0:平时SCK为低(SPI_CPOL为0),在第1个周期采样(SPI_CPHA为0)
- SPI_MODE_1:平时SCK为低(SPI_CPOL为0),在第2个周期采样(SPI_CPHA为1)
- SPI_MODE_2:平时SCK为高(SPI_CPOL为1),在第1个周期采样(SPI_CPHA为0)
- SPI_MODE_3:平时SCK为高(SPI_CPOL为1),在第2个周期采样(SPI_CPHA为1)
- SPI_CS_HIGH:一般来说片选引脚时低电平有效,SPI_CS_HIGH表示高电平有效
- SPI_LSB_FIRST:
- 一般来说先传输MSB(最高位),SPI_LSB_FIRST表示先传LSB(最低位);
- 很多SPI控制器并不支持SPI_LSB_FIRST
- SPI_3WIRE:SO、SI共用一条线
- SPI_LOOP:回环模式,就是SO、SI连接在一起
- SPI_NO_CS:只有一个SPI设备,没有片选信号,也不需要片选信号
- SPI_READY:SPI从设备可以拉低信号,表示暂停、表示未就绪
- SPI_TX_DUAL:发送数据时有2条信号线
- SPI_TX_QUAD:发送数据时有4条信号线
- SPI_RX_DUAL:接收数据时有2条信号线
- SPI_RX_QUAD:接收数据时有4条信号线
处理过程:
Linux内核drivers\spi\spi.c
的
请点击左侧菜单(移动端为右下角)选择要查看的所有笔记吧。