欢迎来到天天文库
浏览记录
ID:36285534
大小:77.11 KB
页数:10页
时间:2019-05-08
《linux主机驱动与外设驱动分离思想》由会员上传分享,免费在线阅读,更多相关内容在学术论文-天天文库。
1、Linux主机驱动与外设驱动分离思想1主机、外设驱动分离的意义在Linux设备驱动框架的设计中,除了有分层设计实现以外,还有分隔的思想。举一个简单的例子,假设我们要通过SPI总线访问某外设,在这个访问过程中,要通过操作CPUXXX上的SPI控制器的寄存器来达到访问SPI外设YYY的目的,最简单的方法是:return_typexxx_write_spi_yyy(...){xxx_write_spi_host_ctrl_reg(ctrl);xxx_write_spi_host_data_reg(buf);while(!(xxx_spi_host_s
2、tatus_reg()&SPI_DATA_TRANSFER_DONE));...}如果按照这种方式来设计驱动,结果是对于任何一个SPI外设来讲,它的驱动代码都是CPU相关的。也就是说,当然用在CPUXXX上的时候,它访问XXX的SPI主机控制寄存器,当用在XXX1的时候,它访问XXX1的SPI主机控制寄存器:return_typexxx1_write_spi_yyy(...){xxx1_write_spi_host_ctrl_reg(ctrl);xxx1_write_spi_host_data_reg(buf);while(!(xxx1_spi
3、_host_status_reg()&SPI_DATA_TRANSFER_DONE));...}这显然是不能接受的,因为这意味着外设YYY用在不同的CPUXXX和XXX1上的时候需要不同的驱动。那么,我们可以用如图12.4的思想对主机控制器驱动和外设驱动进行分离。这样的结构是,外设a、b、c的驱动与主机控制器A、B、C的驱动不相关,主机控制器驱动不关心外设,而外设驱动也不关心主机,外设只是访问核心层的通用的API进行数据传输,主机和外设之间可以进行任意的组合。图12.4Linux设备驱动的主机、外设驱动分离如果我们不进行如图12.4的主机和外设
4、分离,外设a、b、c和主机A、B、C进行组合的时候,需要9个不同的驱动。设想一共有m个主机控制器,n个外设,分离的结果是需要m+n个驱动,不分离则需要m*n个驱动。LinuxSPI、I2C、USB、ASoC(ALSASoC)等子系统都典型地利用了这种分离的设计思想,在本章我们先以简单一些的SPI为例,而I2C、USB、ASoC等则在后续章节会进行详细介绍。2LinuxSPI主机和设备驱动SPI(同步外设接口)是由摩托罗拉公司开发的全双工同步串行总线,其接口由MISO(串行数据输入),MOSI(串行数据输出),SCK(串行移位时钟),SS(从使能
5、信号)四种信号构成,SS决定了唯一的与主设备通信的从设备,主设备通过产生移位时钟来发起通讯。通讯时,数据由MOSI输出,MISO输入,数据在时钟的上升或下降沿由MOSI输出,在紧接着的下降或上升沿由MISO读入,这样经过8/16次时钟的改变,完成8/16位数据的传输。SPI模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性(CPOL)和相位(CPHA)可以进行配置。如果CPOL=0,串行同步时钟的空闲状态为低电平;如果CPOL=1,串行同步时钟的空闲状态为高电平。如果CPHA=0,在串行同步时钟的第一个跳变沿(上升或下降)数据
6、被采样;如果CPHA=1,在串行同步时钟的第二个跳变沿(上升或下降)数据被采样。SPI接口时序如图12.5所示。图12.5SPI总线时序在Linux中,用代码清单12.12的spi_master结构体来描述一个SPI主机控制器驱动,其主要成员是主机控制器的序号(系统中可能存在多个SPI主机控制器)、片选数量、SPI模式和时钟设置用到的函数、数据传输用到的函数等。代码清单12.12spi_master结构体1structspi_master{2structdevicedev;3s16bus_num;4u16num_chipselect;56/*设
7、置模式和时钟*/7int(*setup)(structspi_device*spi);89/*双向数据传输*/10int(*transfer)(structspi_device*spi,11structspi_message*mesg);1213void(*cleanup)(structspi_device*spi);14};分配、注册和注销SPI主机的API由SPI核心提供:structspi_master*spi_alloc_master(structdevice*host,unsignedsize);intspi_register_mas
8、ter(structspi_master*master);voidspi_unregister_master(structspi_master*mas
此文档下载收益归作者所有