grep "SPI_S3C64XX" * -nR
find -name "*.o" -type f
分析SPI子系统
Linux中SPI子系统的初始化时从drivers/spi/spi.c文件中的spi_init函数开始的
分配spi buf内存,其中buf和SPI_BUFSZ都是在spi.c文件中定义:
注册spi总线,同样是spi.c文件中:
总线的名字就叫spi,
比较重要的,spi_match_device是spi总线上匹配设备和设备驱动的函数
写过驱动的都应该知道platform总线有struct platform_device 和 struct platform_driver
到了SPI总线,当然也有对应的struct spi_device和struct spi_driver,
dev 嵌入到设备模型中用的
master,spi设备的更高描述,每一个spi控制器就对应一个master,一个spi必须对应一个master,
master下可以有多个spi设备。
mode,针对时钟相位CPHA(0或1)和时钟极性CPOL(0或1)
driver就是在设备模型中使用的那个device_driver,,其他都是一些函数指针的定义,
回到spi_match_driver函数,91行和95行就是设备和驱动匹配的另外两种方法,因为后文
讲的SPI驱动使用的是第三种方法,
对于具体的平台,nand,iic,frame buffer 等这些都是平台设备,spi当然也一样是平台设备
对于平台设备,大部分情况下是先注册设备在注册驱动。
前面简要讨论了如何构建和运行SPI,使得大家对如何用SPI有了一个基本的了解,下面我们
将深入SPI内部的运行机制的讨论。
同样,我们将从系统运行时的对象开始讨论,而这又离不开对sturct的分析,以及系统运行时
的内核对SPI队形的分析
我们首先从spi.h文件中定义了的各个struct对象开始分析
在这个文件中定义了如下结构
spi_device,spi_driver,spi_master,spi_transfer,spi_message,spi_board_info
spi_device
是SPI从设备,即连接在SPI总线上的外围设备
spi_driver
是SPI主机边的协议驱动
spi_master
是spi控制器,即s3c6410中的spi端口的软件控制器
spi_transfer :a read/write buffer pair
struct spi_message: one M\multi-segment SPI transaction
在spidev.h中定义了如下结构
struct spi_ioc_transfer-describes a single SPI transfer
从这个注释中可以知道这个结构是对内核中的spi_transfer的映射
这个函数生成了一个 spi_message 和一个spi_transfer
并把他们加入到了一个传输队列中,spi_message_init 函数就不细讲了,就是初始化spi_message
的结构而spi_message_add_tail函数做了什么工作呢?是将spi_transfer加入到spi_message的传输任务刘表
即spi_transfer其实是一个院子的传输任务单元
最终由spidev_sync 负责执行,这个函数是同步执行的所以函数内部由异步执行的
status = spi_async(spidev->spi,message);
和wait_for_completion(&done);转换为同步执行
我们再看spi_async函数都做了什么?
它执行了一个内部函数 ret = __spi_async(spi,message);
这个内部函数真正的传输动作是master->transfer(spi,message);
而我们追踪到这里发现api_master结构中transfer仅仅是一个预定义的函数指针
platform_device从字面理解就是平台设备,注意它内含了一个名为dev的device
我们分析一下这个结构,包含了kobject对象,file_operations函数结构体,kobject我们都知道
这是linux文件系统结构中最重要的结构,用来表示文件对象
我们先搁下handle_msg不表,先来回一下这个过程,可以发现整个过程是这样的,具体的传输
任务其实最后都是由芯片厂商提供的代码完成,而linux团队负责定制了spi的用户标准,并为
芯片厂商制定了向下的接口标准,这就是linux内核负责的核心负责的核心负责工作,它与架构无关的
他负责定制标准,芯片厂商根须linux内核的标准,又提供了一些芯片相关的基础设施
而由主板厂商负责进行设备的组装。最终完成了spi控制器和spi从设备在内核中的安装工作
包括静态的数据结构和动态的函数功能的组装
linux内核研发团队,芯片厂商,主板厂商,应用厂商
exynos_device_spi0
Dev-spi.c
目录 arch\arm\mach-exynos
static struct s3c64xx_spi_csinfo spi0_csi[]
mach-tiny4412.c 目录
spi_board_info
mach-tiny4412.c
spidev_spi_driver
spidev.c文件中定义:driver\spi
spi_master_class
spi.c
driver\spi
spi_init
spi.c
driver\spi
接下来介绍SPI目录下的各个对象的定义
spi-sunmmary.txt是必须阅读的参考文档
从spi目录可以看出这是与平台无关的,也就是linux对linux对spi接口进行抽象,形成的用户层相关代码
而platform下面的代码是具体进行工作的代码,他们与平台相关,而spi代码是与用户空间接口相关的代码
他必须与平台无关,即平台如何更换过,对用户空间的接口都是一致的,这就是linux设备驱动架构的精髓
我们注意到spi目录下只有一个spidev的驱动,其他都是指向platform下的设备衔接
git clone https://github.com/friendlyarm/linux-3.4.y.git
cd linux-3.4.y
git checkout nanopi2-lollipop-mr1
转载请注明原文地址: https://ju.6miu.com/read-676931.html