2024年6月12日发(作者:)

SPI协议是一种同步的串行数据连接标准,由摩托罗拉公司命名,可工作于全双工模式。相

关通讯设备可工作于m/s模式。主设备发起数据帧,允许多个从设备的存在。每个从设备

有独立的片选信号,SPI一般来说是四线串行总线结构。

接口:

SCLK——Serial Clock(output from master)时钟(主设备发出)

MOSI/SIMO——Master Output, Slave Input(output from master)数据信号线mosi(主设备

发出)

MISO/SOMI——Master Input,Slave Outpu(output from slave)数据信号线(从设备)

SS——Slave Select(active low;output from master)片选信号

下面来看一下Linux中的SPI驱动。在Linux设备驱动框架的设计中,有一个重要的主机,

外设驱动框架分离的思想,如下图。

外设a,b,c的驱动与主机控制器A,B,C的驱动不相关,主机控制器驱动不关心外设,而外设

驱动也不关心主机,外设只是访问核心层的通用的API进行数据的传输,主机和外设之间

可以进行任意的组合。如果我们不进行如图的主机和外设分离,外设a,b,c和主机A,B,C进

行组合的时候,需要9种不同的驱动。设想一共有个主机控制器,n个外设,分离的结构是

需要m+n个驱动,不分离则需要m*n个驱动。

下面介绍spi子系统的数据结构:

在Linux中,使用spi_master结构来描述一个SPI主机控制器的驱动。

view plain

1.

2.

3.

4.

5.

6.

struct spi_master {

struct device dev;/*总线编号,从0开始*/

s16 bus_num;/*支持的片选的数量,从设备的片选号不能大于这个数量*/

u16 num_chipselect;

u16 dma_alignment;/*改变spi_device的特性如:传输模式,字长,时钟频率*/

int (*setup)(struct spi_device *spi);/*添加消息到队列的方法,这个函数不可睡眠,他的任务是安排发生的传送

并且调用注册的回调函数complete()*/

7. int (*transfer)(struct spi_device *spi,struct spi_message *mesg);

8.

9.

void (*cleanup)(struct spi_device *spi);

};

分配,注册和注销的SPI主机的API由SPI核心提供:

view plain

1.

2.

3.

struct spi_master *spi_alloc_master(struct device *host, unsigned size);

int spi_register_master(struct spi_master *master);

void spi_unregister_master(struct spi_master *master);

在Linux中用spi_driver来描述一个SPI外设驱动。

view plain

1.

2.

3.

4.

5.

6.

7.

8.

struct spi_driver {

int (*probe)(struct spi_device *spi);

int (*remove)(struct spi_device *spi);

void (*shutdown)(struct spi_device *spi);

int (*suspend)(struct spi_device *spi, pm_message_t mesg);

int (*resume)(struct spi_device *spi);

struct device_driver driver;

};

可以看出,spi_driver结构体和platform_driver结构体有极大的相似性,都有

probe(),remove(),suspend(),resume()这样的接口。

Linux用spi_device来描述一个SPI外设设备。

view plain

1.

2.

3.

4.

5.

6.

7.

8.

9.

struct spi_device {

struct device dev;

struct spi_master *master; //对应的控制器指针u32

max_speed_hz; //spi通信的时钟u8

chip_select; //片选,用于区分同一总线上的不同设备

u8 mode;

#define SPI_CPHA 0x01 /* clock phase */

#define SPI_CPOL 0x02 /* clock polarity */

#define SPI_MODE_0 (0|0) /* (original MicroWire) */#define SPI_MODE_1 (0|SPI_CPHA)

10. #define SPI_MODE_2 (SPI_CPOL|0)

11. #define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)#define SPI_CS_HIGH 0x04 /* chipselect active h

igh? */

12. #define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */

13. #define SPI_3WIRE 0x10 /* SI/SO signals shared */

14. #define SPI_LOOP 0x20 /* loopback mode */

15. u8 bits_per_word; //每个字长的比特数

16. int irq; //使用的中断