SPI 设备驱动编写流程:SPI 设备数据收发处理流程中涉及的结构体与函数

本文详细介绍了Linux下SPI设备驱动的编写流程,重点讨论了spi_transfer和spi_message结构体,以及如何进行同步(spi_sync)和异步(spi_async)数据收发。通过spi_message结构组织传输,并演示了在实际应用中的同步传输示例。
摘要由CSDN通过智能技术生成

一.  简介

前面一篇文章学习了SPI设备驱动涉及的结构体与(注册/注销)函数。

另一篇文章学习了(在支持设备树情况下),SPI 设备信息如何描述,具体就是在设备树文件中创建SPI节点及SPI设备节点,文章如下:

Linux下SPI驱动:SPI设备驱动简介-CSDN博客

SPI 设备驱动编写流程:创建SPI节点以及SPI设备节点(在设备树文件中)-CSDN博客

本文继续学习SPI设备驱动的编写流程,具体学习SPI设备数据收发处理。

二. SPI 设备驱动编写流程:SPI 设备数据收发处理流程

SPI 设备驱动的核心是 spi_driver
当我们向 Linux 核注册成功 spi_driver 以后,就可以使用 SPI 核心层提供的 API 函数来对设备进行读写操作了。

1. spi_transfer结构体与 spi_message结构体

首先是 spi_transfer 结构体,此结构体用于描述 SPI 传输信息,结构体内容如下:
struct spi_transfer {
	/* it's ok if tx_buf == rx_buf (right?)
	 * for MicroWire, one buffer must be null
	 * buffers must work with dma_*map_single() calls, unless
	 *   spi_message.is_dma_mapped reports a pre-existing mapping
	 */
	const void	*tx_buf;
	void		*rx_buf;
	unsigned	len;

	dma_addr_t	tx_dma;
	dma_addr_t	rx_dma;
	struct sg_table tx_sg;
	struct sg_table rx_sg;

	unsigned	cs_change:1;
	unsigned	tx_nbits:3;
	unsigned	rx_nbits:3;
#define	SPI_NBITS_SINGLE	0x01 /* 1bit transfer */
#define	SPI_NBITS_DUAL		0x02 /* 2bits transfer */
#define	SPI_NBITS_QUAD		0x04 /* 4bits transfer */
	u8		bits_per_word;
	u16		delay_usecs;
	u32		speed_hz;

	struct list_head transfer_list;
};
7 行, tx_buf 保存着要发送的数据。
8 行, rx_buf 用于保存接收到的数据。
9 行, len 是要进行传输的数据长度, SPI 是全双工通信,因此在一次通信中发送和 接收的字节数都是一样的,所以 spi_transfer 中也就没有发送长度和接收长度之分。
spi_transfer 需要组织成 spi_messagespi_message 也是一个结构体,内容如下:
struct spi_message {
	struct list_head	transfers;

	struct spi_device	*spi;

	unsigned		is_dma_mapped:1;
.....................
/* completion is reported through a callback */
	void			(*complete)(void *context);
	void			*context;
	unsigned		frame_length;
	unsigned		actual_length;
	int			status;

	/* for optional use by whatever driver currently owns the
	 * spi_message ...  between calls to spi_async and then later
	 * complete(), that's the spi_master controller driver.
	 */
	struct list_head	queue;
	void			*state;
};

2.  初始化 spi_message,添加spi_transfer到spi_message队列中

在使用 spi_message 之前需要对其进行初始化, spi_message 初始化函数为 spi_message_init
函数原型如下:
 void spi_message_init(struct spi_message *m)
函数参数和返回值含义如下:
m 要初始化的 spi_message
返回值: 无。
spi_message 初始化完成以后需要将 spi_transfer 添加到 spi_message 队列中,这里我们要用
spi_message_add_tail 函数,此函数原型如下:
void spi_message_add_tail(struct spi_transfer *t, struct spi_message *m)
函数参数和返回值含义如下:
t 要添加到队列中的 spi_transfer
m spi_transfer 要加入的 spi_message
返回值: 无。

3.  SPI数据传输

spi_message 准备好以后就可以进行数据传输了,数据传输分为同步传输和异步传输。
同步 传输会阻塞的等待 SPI 数据传输完成,同步传输函数为 spi_sync 函数,函数原型如下:
int spi_sync(struct spi_device *spi, struct spi_message *message)
函数参数和返回值含义如下:
spi 要进行数据传输的 spi_device
message :要传输的 spi_message
返回值: 无。
异步传输不会阻塞的等到 SPI 数据传输完成。
异步传输需要设置 spi_message 中的 complete 成员变量, complete 是一个回调函数,当 SPI 异步传输完成以后,此函数就会被调用。 SPI 异步传 输函数为 spi_async 函数,函数原型如下:
int spi_async(struct spi_device *spi, struct spi_message *message)
函数参数和返回值含义如下:
spi 要进行数据传输的 spi_device
message :要传输的 spi_message
返回值: 无。

在本次的 SPI实验中,我们采用同步传输方式来完成 SPI 数据的传输工作,也就是 spi_sync

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值