Linux SPi总线使用

1. 简介

SPI总线是很常用的总线类型,有好多设备的数据接口都采用了SPI总线,比如ICM20608加速度陀螺仪传感器。在Linux中,SPI设备是采用了Linux惯用的设备模型:driver->bus->device,此总线类型是SPI总线,driver就是我们针对某一SPI设备所编写的设备驱动,使用bus给我们提供的SPI总线操控函数,然后根据SPI设备信息来编写SPI设备驱动。当我们编写SPI设备驱动时,需要将SPI设备驱动(spi_driver)使用设备注册函数(spi_register_driver)注册到Linux内核中,然后我们就可以使用bus所提供的的SPI操控函数了。SPI操控函数是由SPI控制器提供的。
SPI控制器其实也是一个driver->bus->device模型,只不过这个SPI控制器驱动由芯片厂商人员编写,提供给我们操控SPI控制器。这个总线是platform总线类型,device设备是在设备树中获取的SPI控制器的信息,然后芯片厂商编写driver,最后将SPI控制器注册到内核中,这样我们编写SPI设备驱动时就可以使用厂商提供的SPI控制器操控函数了。
其简单的模型如下:
在这里插入图片描述

2. SPI数据类型

1). SPI控制器驱动结构体

这个结构体里面主要是包含了某个SPI控制器的所有课操控信息结构体,比如这个SPI控制器的传输函数等信息。spi_master结构体在include/linux/spi/spi.h的第315行左右定义,其具体内容如下:

struct spi_master {
   
	......
	int (*transfer)(struct spi_device *spi, struct spi_message *mesg);	/* 次函数就是SPI传输数据函数	*/
	......
	int (*transfer_one_message)(struct spi_master *master, struct spi_message *mesg); /* 这个也是 */
	......

其实这个结构体我们不需要关心,这个结构体在芯片厂商人员编写SPI控制器驱动时,注册后,这里面的信息就已经有了,我们不需要去干预。结构体具体的信息很复杂,可以不去了解,也可以通过315行上面的注释来了解。

2). SPI设备信息结构体

spi_device结构体里面储存着这个SPI设备从设备树中获取的信息,在include/linux/spi/spi.h中的第72行左右有定义,其内容如下:

struct spi_device {
   
	struct device		dev;	/* SPI设备信息的父类	*/
	struct spi_master	*master;	/* 所使用的SPI控制器结构体*/
	u32			max_speed_hz;	/* spi设备所支持的最大时钟频率	*/
	u8			chip_select;	/* 片选选中电平	*/
	u8			bits_per_word;	/* 每个字的bit数,默认8位,可以被驱动使用者修改	*/
	u16			mode;	/* 数据传输模式,cpol,chpa */
/* 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)
#define	SPI_MODE_2	(SPI_CPOL|0)
#define	SPI_MODE_3	(SPI_CPOL|SPI_CPHA)
#define	SPI_CS_HIGH	0x04			/* chipselect active high? */
#define	SPI_LSB_FIRST	0x08			/* per-word bits-on-wire */
#define	SPI_3WIRE	0x10			/* SI/SO signals shared */
#define	SPI_LOOP	0x20			/* loopback mode */
#define	SPI_NO_CS	0x40			/* 1 dev/bus, no chipselect */
#define	SPI_READY	0x80			/* slave pulls low to pause */
#define	SPI_TX_DUAL	0x100			/* transmit with 2 wires */
#define	SPI_TX_QUAD	0x200			/* transmit with 4 wires */
#define	SPI_RX_DUAL	0x400			/* receive with 2 wires */
#define	SPI_RX_QUAD	0x800			/* receive with 4 wires */
	int			irq;	/* 所使用的的irq号	*/
	void			*controller_state;
	void			*controller_data;
	char			modalias[SPI_NAME_SIZE];
	int			cs_gpio;	/* 片选所使用的的gpio号 */

	/*
	 * likely need more hooks for more protocol options affecting how
	 * the controller talks to each chip, like:
	 *  - memory packing (12 bit samples into low bits, others zeroed)
	 *  - priority
	 *  - drop chipselect after each word
	 *  - chipselect delays
	 *  - ...
	 */
};

一个SPi控制器可能挂了很多个SPI设备,有可能每个SPI设备所需要的的SPI控制器的参数不同,比如SPI速率,片选引脚,等每个SPI特有的信息,这个特有的信息不能放在共有的结构体中,需要针对某个SPI初始化,所以这个spi_device中除了保存从设备树获取的设备树信息,还保存着自己特有的信息,如果设备树里面没有添加,我们也可以修改这个结构体,然后设置这个SPI控制器。
一般都需要修改了cpol,csph,这个是按照SPI设备芯片所配置的,本次全部配置为0,然后使用spi_setup函数设置。
其中master结构体就是在设备树中设备指定所使用的的SPI控制器,让kernel读取设备树时,就会将所指定的SPI控制器的地址保存在这个master变量中,当进行设备传输时,就需要将spi_device结构体传入进去,用来寻找所使用的的哪个SPI控制器。

3). SPI设备驱动结构体

spi_driver是需要我们针对SPI设备所写驱动所使用的的结构体,当我们将其内容写完时,需要注册到内核进去,然后这个SPI设备就可以自由的使用。spi_driver结构体在/include/linux/spi/spi.h的第180行左右,其内容如下:

struct spi_driver {
   
	const struct spi_device_id *id_table;	/* 传统设备匹配表	*/
	int			(*probe)(struct spi_device *spi);	/* 设备和驱动匹配后会自动运行的函数	*/
	int			(*remove)(struct spi_device *spi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值