在前面几篇文章我们分析了SPI驱动框架模型、SPI总线、SPI MASTER、SPI DEVICE、SPI通信接口等内容,本篇是SPI总线的最后一篇,主要介绍SPI通用字符设备。
在SPI驱动模块提供了通用字符设备驱动以及注册接口,我们知道I2C模块的通用字符设备也提
供了通用字符设备,在分析SPI通用字符设备模型之前,我们先来说明下I2C通用字符设备模型与SPI通用字符设备模型的区别,以便我们对SPI通用字符设备模型有一个感性的认识。
以上便是spi通用字符设备与i2c通用字符设备的区别,简单点说就是:spi通用字符设备需自行
创建,且与挂载至spi控制器上的spi设备绑定。
clip许可证设备id与绑定设备不匹配。为Spi 通用字符设备创建而注册的spi driver
spi模块为通用字符设备创建的spi driver如下,该驱动实现的功能如下:
static const struct of_device_id spidev_dt_ids[] = {{ .compatible = "rohm,dh2228fv" },{},};static struct spi_driver spidev_spi_driver = {.driver = {.name ="spidev",.owner =THIS_MODULE,.of_match_table = of_match_ptr(spidev_dt_ids),},.probe =spidev_probe,.remove =spidev_remove,}
spi通用字符设备驱动创建流程
SPI 模块提供的通用字符设备是与具体的spi设备向关联的,即我们必须创建一个设备名称或者设备节点名称固定的spi device(spi 设备名称为“spidev”或设备节点名称为“rohm,dh2228fv”),然后与spi驱动模块注册的spi 驱动匹配,方才触发spi 通用字符设备的创建。我们下面来分析下spi通用字符设备的创建流程。
其实spi通用字符设备与我们自己在spi驱动中实现字符设备的流程基本上是一致的,区别是我们会在spi驱动的probe接口进行一些spi设备的初始化操作,而spi通用字符设备创建所对应的spi驱动的probe仅用来创建字符设备。如下图所示,为我们自己创建spi 字符设备的创建流程,将这个流程图中的红色虚线框中的内容去除,即为spi通用字符设备驱动的创建流程。
在接口spidev_init中,完成了主设备号为SPIDEV_MAJOR,次设备号为0的spi字符设备的创建,
字符设备驱动框架,该字符设备文件对应的处理接口为spidev_fops,其定义如下:
static const struct file_operations spidev_fops = { .owner =THIS_MODULE, /* REVISIT switch to aio primitives, so that userspace * gets more complete API coverage. It'll simplify things * too, except for the locking. */ .write =spidev_write, .read =spidev_read, .unlocked_ioctl = spidev_ioctl, .compat_ioctl = spidev_compat_ioctl, .open =spidev_open, .release =spidev_release, .llseek =no_llseek,};
spidev_open
spidev_open接口主要用于判断所要打开的spi通用字符设备文件,并根据字符设备文件的设备号在device_list链表上查找对应的spidev_data类型的变量,并将其绑定至文件描述的私有变量指针上。(当进行通用字符设备文件节点的创建前,通过注册spidevice并与spidev_spi_driver绑定时,通过调用spidev_probe时,将该spidevice对应的spidev_data类型的变量添加到device_list链表上,同时通过调用device_create接口完成device类型变量的创建,同时向应用层发送uevent,由应用层的udev或mdev完成字符设备节点的创建(通过mknod系统调用))。
如下是struct spidev_data类型的变量,该变量实现了spi通用字符设备节点对应的文件描述符与spi模块的关联:
struct spidev_data { dev_tdevt; spinlock_tspi_lock; struct spi_device*spi; struct list_headdevice_entry; /* buffer is NULL unless this device is open (users > 0) */ struct mutexbuf_lock; unsignedusers; u8*buffer;};
spidev_read、spidev_write
这两个接口主要通过调用spi通信接口spi_async,完成与具体的spidevice的通信(同步通信)。当spidev_read、spidev_write接口调用spi_async时,借助完成量接口,完成了同步通信(调用wait_for_completion使本进程进入sleep状态,待spi-core完成通信后,则通过执行spidev_complete将该进程唤醒,从而完成了同步通信操作)。
csp注册许可证。spidev_ioctl、spidev_compat_ioctl
这两个接口主要进行通信速率、通信模式等设置操作,包括SPI_IOC_WR_MODE、SPI_IOC_WR_LSB_FIRST、SPI_IOC_WR_BITS_PER_WORD、SPI_IOC_WR_MAX_SPEED_HZ等接口,也支持与spi device的读写通信等。
以上为spi模块通用字符设备模型相关的内容,个人认为该模型被低估了,该模型为我们实现了字符设备模型接口,而且支持读、写、ioctl等功能,若我们需要编写驱动的spi device,仅仅用于读写状态等信息,并不需要进行特殊的初始化,可以完全使用该通用字符设备模型,而不需要重新编写驱动,只需要注册对应的spidev即可。
至此,我们完成了LINUX SPI设备驱动模型的分析,主要设置spi 总线、 spi master、 spi device、 spi driver、 spi通信接口、spi通用字符设备模型等模块。
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态