Linux Kernel SPI子系统架构
简介 本文主要讲解linux的spi子系统。从宏观到微观的角度,循序渐进解剖spi子系统,为开发spi相关驱动打好基础;也可通过此文理解linux相关总线子系统(如I2C、USB)的实现思想和本质,避免看内核源码时,处于管中窥豹的状态。 软硬件环境linux kernel version:2.6.35.
简介
本文主要讲解linux的spi子系统。从宏观到微观的角度,循序渐进解剖spi子系统,为开发spi相关驱动打好基础;也可通过此文理解linux相关总线子系统(如I2C、USB)的实现思想和本质,避免看内核源码时,处于管中窥豹的状态。
编写完此文后,作者会继续分享出具体spi外设和主机驱动相关的实操技术出来。
软硬件环境
- linux kernel version:2.6.35.7
- SOC:S5PV210 (ARMv7指令集,Cortex-A8架构)
- gcc version: 4.4.1 (Sourcery G++ Lite 2009q3-67)
第一节 面向对象分析spi总线
关于spi(Serial Peripheral Interface—串行外设接口)总线的电气硬件特性,相关介绍的文章琳琅满目,本文不再赘述。
spi总线应用的一般硬件抽象模型如下图1左所示。SOC(system-on-chip)集成多个spi控制器,每个控制器连入一条spi总线,其上坐着多个spi设备;SOC可作主机或从机,需注意linux的spi子系统只实现了主机。怎么实现soc与外部的spi设备通讯? 一般情况你会这样想,先实现操作spi控制器本身的驱动(操作特殊寄存器):spi控制器的初始化(规定spi总线的波形特征),控制与其它spi设备的数据传输;然后用前述驱动包装好的spi读写方法,实现不同外部spi设备的驱动:控制与spi设备通讯的内容。这是所谓面向过程的思考。
现以面向对象思考上述问题。总结出,上述过程中有数个主要对象:spi主机控制器,spi外部设备,板级硬件逻辑,通讯消息;如图1右所示。
图1 soc和外设抽象图
另外,linux kernel总线相关子系统践行主机驱动和外设驱动分离设计思想,以及用设备和驱动表示硬件外设的属性和行为,所以接下来以上述思想分析内核的spi体系结构。
第二节 Linux spi 体系结构
Linux 的spi体系结构分为4个软件模块。如图2所示为spi子系统的体系结构,描绘了各个软件模块的关系。
(1)SPI controller driver(主机端驱动)
SPI总线控制器驱动根据SOC的datasheet,由CPU core操作一般集成在SOC内的SPI控制器。
SPI主机端驱动主要包含SPI主机数据结构spi_master
和控制SPI主机产生通信信号的函数(transfer method
)。经由SPI总线驱动的代码,我们可以控制SPI控制器以主机模式产生spi总线的SCLK、MOSI、CS波形,以及读取MISO的数据。
(2)SPI-core(spi核心)
SPI核心提供了SPI总线驱动和设备驱动的注册和注销方法,SPI通信方法(读和写)与具体的主机控制器无关的代码以及匹配设备、驱动的探测等,实现于drivers/spi/spi.c
。
图2 linux spi体系结构
(3)protocol driver(设备协议驱动)
SPI设备驱动,内核doc称它为protocol driver,是对硬件体系中外部设备端的实现,通过SPI主机控制器与CPU交换数据。
SPI设备协议驱动主要包含数据结构spi_driver
, 通过调用SPI-core提供的标准SPI通信API,实现具体成员函数和所寄生的设备类驱动。
(4)spi board info(板级逻辑)
spi板级逻辑描述了主机和外设的互联,它相当于第二次工业革命中接线员的角色,如图3。
图3 板级逻辑是接线员
假设板子上有多个SPI控制器和多个SPI外设,那究竟谁接在谁上面?这个互联关系,既不是主机的责任,也不是外设端的责任,而是属于板级硬件逻辑规格的责任。
spi板级逻辑主要包含数据结构spi_board_info
,其成员主要描述了spi设备的通信规格、硬件配置,将其注册进SPI核心后,衍生为spi_device
。
在Linux kernel 2.6中,可通过sysfs文件系统看到所有的SPI设备,存于/sys/bus/spi/
路径下,以总线号和外部设备号形式列出,如:
[root@zxd210 /]# tree /sys/bus/spi/
/sys/bus/spi/
|-- devices
| |-- spi0.0 -> ../../../devices/platform/spi-s5p.0/spi0.0
| `-- spi1.0 -> ../../../devices/platform/spi-s5p.1/spi1.0
|-- drivers
| `-- mpu6500_spi
| |-- bind
| |-- module -> ../../../../module/mpu6500_spidrv
| |-- spi1.0 -> ../../../../devices/platform/spi-s5p.1/spi1.0
| |-- uevent
| `-- unbind
|-- drivers_autoprobe
|-- drivers_probe
`-- uevent
第三节 关键数据结构
上节主要介绍了Linux 的SPI体系结构及其主要研究对象,这节从宏观到微观讲解这些对象宏观协作套路和代码清单。
数据结构spi_master
、spi_driver
、spi_board_info
、spi_device
定义于include/linux/spi/spi.h
文件中,如下代码清单所示。
struct spi_master {
struct device dev;
s16 bus_num;
u16 num_chipselect;
u16 dma_alignment;
u16 mode_bits;
u16 flags;
int (*setup)(struct spi_device *spi);
int (*transfer)(struct spi_device *spi, struct spi_message *mesg);
void (*cleanup)(struct spi_device *spi);
};
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);
int (*suspend)(struct spi_device *spi, pm_message_t mesg);
int (*resume)(struct spi_device *spi);
struct device_driver driver;
};
struct spi_board_info {
char modalias[SPI_NAME_SIZE];
const void *platform_data;
void *controller_data;
int irq;
u32 max_speed_hz;
u16 bus_num;
u16 chip_select;
u8 mode;
};
struct spi_device {
struct device dev;
struct spi_master *master;
u32 max_speed_hz;
u8 chip_select;
u8 mode;
u8 bits_per_word;
int irq;
void *controller_state;
void *controller_data;
char modalias[SPI_NAME_SIZE];
};
上述数据结构在spi子系统上怎么协作的呢?如图4所示为关键数据结构间宏观协作关系。
图4 关键数据结构间宏观协作
图4中标出来的序号为宏观执行顺序:
①通常在
arch/arm/mach-<SOC>/mach-<BOARD>.c
里进行,将板级信息挂到spi核心的board_list
链表,形成”羊肉串”;
②主机驱动注册spi_master
时在board_list
链表中匹配所有对应bus_num
的板级信息;
③用流程②匹配到的板级信息构造spi_device
;
④设备驱动中注册spi_driver
时,通过成员name匹配对应的spi_device,再执行probe
;
⑤外设端驱动通过调用spi核心层的标准API传输通信内容时,会传递到对应spi总线主机驱动中,让它操作底层硬件产生⑥波形。
假设SPI总线主机控制器xxx 上有两个使用相同外设端驱动程序的yyy SPI设备,在打开SPI总线的设备节点后,相关数据结构之间的逻辑组织关系如图5所示。
图5 spi驱动的各种数据结构的关系
参考文献
[1] 宋宝华. Linux设备驱动开发详解[M].北京:机械工业出版社,2015
[2] David Brownell,Russell King,Dmitry Pervushin等. spi-summary[EB/OL].Kernel.org git repositories,2007
[3] 韦东山.SPI模块配套视频[M/CD].韦东山老师个人店,2018
由于作者水平有限,难免出现纰漏,需要您的宝贵修改意见,后续作者会持续更新此文以完善它。
更多推荐
所有评论(0)