第一:linux系统下SPI驱动框架简介
SPI驱动框架分为主机控制器驱动和设备驱动,主机控制器就是SOC的SPI控制器接口。不管是什么SPI设备,SPI控制器部分的驱动都是一样的,重点就落在种类繁多的SPI设备驱动上了。
//SPI主机驱动就是SOC的SPI控制器驱动,linux系统中采用spi_master struct spi_master{ struct device dev; struct list_head list; int (*transfer)(struct spi_device *spi, struct spi_message *mesg); int (*transfer_one_message)(struct spi_master *master,struct spi_message *mesg); ..... };
SPI主机驱动的核心就是申请spi_master,然后初始化spi_master,最后向linux内核注册spi_master。
第二:SPI设备驱动编写
linux内核使用spi_driver结构体来表示spi设备驱动,我们在编写SPI设备驱动的时候需要实现spi_driver。
struct spi_driver{ const struct spi_device_id *id_table; int (*probe)(struct spi_device *spi); int (*remove)(struct spi_device *spi); void (*shutdown)(struct spi_device *spi); struct device_driver driver; };
spi_driver初始化完成以后需要向linux内核注册,spi_driver注册函数为spi_register_driver函数原型如下:
int spi_register_driver(struct spi_driver *sdrv) sdrv:要注册的spi_driver
第三:SPI设备和驱动匹配过程
SPI设备和驱动的匹配过程是由SPI总线来完成的。
struct bus_type spi_bus_type = { .name = "spi", .dev_groups = spi_dev_groups, .match = spi_match_device, .uevent = spi_ueent, };
采用设备树的情况下,SPI设备信息描述就通过创建喜迎的设备子节点来完成,可以打开设备树头文件,在此文件中找到对应的内容:
&ecspil{ fsl,spi-num-chipselects = <1>; cs-gpios = <&gpio4 9 0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ecspi1>; status = "okay"; flash: m25p80@0 { #address-cells = <1>; #size-cells = <1>; compatible = "st,m25p32"; spi-max-frequency = <20000000>; reg = <0>; }; };
SPI数据传输步骤如下:
1、申请并初始化 spi_transfer,设置 spi_transfer 的 tx_buf 成员变量,tx_buf 为要发送的数 据。然后设置 rx_buf 成员变量,rx_buf 保存着接收到的数据。最后设置 len 成员变量,也就是 要进行数据通信的长度。
2、使用 spi_message_init 函数初始化 spi_message。
3、使用spi_message_add_tail函数将前面设置好的spi_transfer添加到spi_message 队列中。
4、使用 spi_sync 函数完成 SPI 数据同步传输。
对于SPI设备驱动,首先就是要初始化并向系统注册spi_driver初始化,注册与注销代码如下:
/* 传统匹配方式 ID 列表 */ static const struct spi_device_id icm20608_id[] = { {"alientek,icm20608", 0}, {} }; /* 设备树匹配列表 */ static const struct of_device_id icm20608_of_match[] = { { .compatible = "alientek,icm20608" }, { /* Sentinel */ } }; /* SPI 驱动结构体 */ static struct spi_driver icm20608_driver = { .probe = icm20608_probe, .remove = icm20608_remove, .driver = { .owner = THIS_MODULE, .name = "icm20608", .of_match_table = icm20608_of_match, }, .id_table = icm20608_id, };
总结:linux系统中安装SPI驱动框架,可以编写出利用SPI通信协议的总线的通信过程,值得反复推敲。