参考:
Linux是非常优秀开源操作系统有着十分广泛应用基于该操作系统设备驱动需求越来越多PCI作为种广泛采用总线标准在嵌入式系统中正被大量使用而Linux内核也能很好地支持PCI设备为此本文介绍了Linux下无配置信息PCI设备驱动设计开发方法 1 PCI总线及无配置信息PCI设备 1.1 PCI总线 PCI是外围设备互连(Peripheral ComponentInterconnect)
简称
是
种通用
总线接口标准
原先是应用于计算机系统
PCI提供了
组完整
总线接口规范
其目
是描述如何将计算机系统中
外围设备以
种结构化和可控化
方式连接在
起
该规范同时详细定义了计算机系统中各个不同部件之间应该如何正确地进行交互
在
般
计算机系统中
总线子系统与存储子系统被PCI总线分开
CPU通过
块称为PCI桥
设备来完成同总线子系统
交互
图1所示是
个PCI子系统
体系结构
尽管目前PCI设备大多采用32位数据总线
但PCI规范中已经给出了64位
扩展实现方案
从而使PCI总线能够更好地实现平台无关性
虽然PCI总线是由Intel公司提出
但它不局限于Intel系列
处理器
当今流行
其它处理器系列如Alpha、PowerPC、APARC
以及多处理器结构
下
代处理器都可以使用PCI总线
具体而言
PCI总线包含
特点可简要描述为高性能、线性突发传输、极小
存取延误、采用总线主控和同步操作、独立于处理器、兼容性强、预留了发展空间、低成本、高效益、软件透明等等
1.2 PCI设备配置空间 标准
PCI设备上有三种地址空间:I/O空间、存储空间及配置空间
CPU可以访问PCI设备上
所有地址空间
其中I/O空间和存储空间提供给设备驱动
使用
主要用来实现PCI设备和Linux内核中设备驱动
之间
通讯
而配置空间则装载着PCI设备
配置信息
主要由Linux内核中
PCI
化代码使用
PCI设备
配置信息空间如图2所示
标准PCI设备配置信息空间
大小为256个字节
其中低64个字节称为头标区
这部分区域
格式是固定
内容包括PCI设备号、厂商识别号、命令寄存器、状态寄存器、基址寄存器等重要信息;其余
192个字节称为设备有关区
不同
设备可以对这部分寄存器进行不同
定义
1.3 无配置信息PCI设备 目前
嵌入式系统往往会要求CPU和专用数据运算器之间以很高
速率通信
由于现行
总线规范中
PCI
高性能是最为突出
因此PCI总线
连接方式被大量采用
数据运算器往往是针对某
系统设计
通常会采用FPGA设计
即在FPGA中添加进PCI
接口设计
也就是把FPGA设计成为
块PCI设备
但是由于嵌入式系统
局限性
在某些FPGA
PCI接口设计中不能划分配置信息空间(I/O空间和存储空间是设备与CPU信息交互
基础
是必须存在
)
因此这个设计也就是
块无配置信息
PCI设备
2 Linux设备驱动 Linux
设备驱动
大致可以分为驱动
注册与注销、设备
打开与释放、设备
读写操作、设备
控制操作、设备
中断和轮询处理几个部分
2.1 设备注册与注销 向系统增加
个驱动
就要赋予它
个主设备号
这
赋值过程应该在驱动
化中完成
它通过
register_chrdev
或reg-iste_blkdev
向内核注册
接下来就是给
个设备驱动
名
这个名字必须插入到/dev目录中
并与驱动
主设备号和次设备号相连
获得主设备号
方法是选择
个当前不用
设备号
或者在
register_chrdev时让参数ma-jor为0
这样
其返回值便是设备
主设备号
另外
在关闭
设备或块设备时
还需要通过unregisler_chrdev
或unregister_blkdev
从内核中注销设备
并释放主设备号
2.2 设备打开与释放 打开设备可由open
完成
在大部分驱动
中
open主要用于检查设备相关
(如设备尚未准备好等)、识别次设备号(如有必要更新当前read/write位置f_ops指针)
以及分配和填写要放在file->private_data里
数据结构
释放设备由release
完成
release
作用与open相反
主要是释放file->private_data中open分配
内存
并在最后
次关闭操作时关闭设备
2.3 设备读写操作 设备使用各自
read
和write
来对设备进行数据读写
块设备则使用通用block_read
和block_write
来对设备进行数据读写
这两个通用
可以向请求表中增加读写请求
这样
内核就可以优化请求顺序
由于是对内存缓冲区而不是对设备进行操作
因而能加快读写请求
如果内存缓冲区内没有要读入
数据或者需要将写请求写入设备
那么就需要真正地执行数据传输
2.4 设备控制操作和中断处理 除了读写操作外
有时还需要控制设备
这在操作时可以通过设备驱动
中
ioctl
来完成
另外
对于不支持中断
设备
读写时需要轮流查询设备状态
以决定是否继续进行数据传输
如果设备支持中断
则可按中断方式进行
3 无配置信息PCI设备驱动设计 无配置信息PCI设备驱动
设计
关键在于
化
其余部分与标准PCI设备驱动差别不大
其
化
方法有两种:
是选用外接
EEPROM来存储该设备
配置信息;二是直接在驱动
探测模块里注册设备
用外接EEPROM配置方式时
内核启动后会检测EEPROM
然后读出其中
配置信息
并将设备
信息注册到pci dev里
在实际
系统应用中
如果无法外接EEP-ROM
就必须直接在驱动
探测模块里注册设备
在这种方式下
若系统中没有其它
即插即用PCI设备
则可能会导致检测设备失败
但事实上已经注册了该PCI设备
因此完全可以正常运行
笔者开发
嵌入式TDMA卫星通信系统中
CPU采用MPC8250芯片
基带信号处理模块采用Xilinx公司
X3SC4000(FG676)
MPC8250是Mo-torola公司开发
款PowerPC系列嵌入式处理器
该处理器中有32位超标量体系结构Power-PC603e处理器内核
并集成有PCI桥、PCI仲裁器、存储器控制器等部件
FPGA
设计中则包括PCI接口、sdram控制器及编码调制运算模块
此操作系统采用Linux
内核版本为2.6
由于Linux能很好地支持PCI总线
本设计在CPU和FPGA之间采用了PCI总线连接方式
由于FPGA
设计要求
PCI总线
中断信号未被使用
而是另行设定了两条中断信号线通往MPC8250
通用设计口
该系统支持FPGA中bin文件实时更新因此没有采用配置EPROM来配置FPGA而是把要下载到FPGA里bin文件同Uboot、Linux内核及jffs2文件系统起放在了FLASH里然后通过MPC8250提供SPI总线下载到FPGA中实际上如需要更新FPGA.bin文件则可通过以太网口将文件拷入FLASH中再下载 在系统上电启动后
由于Linux内核先于jffs2解压
而FPGA
文件又必须在jffs2解压完后才能释放到内核空间
然后再借助SPI总线下载到FP-GA中
因此无法在FPGA中创建PCI设备配置信息空间
所以
本设计采用在检测PCI设备时直接注册
方法
3.1 驱动总体框架 下面是笔者驱动
整体框架
从中可以很明显地看出几个模块是如何联系起来
:
3.2 具体模块实现 由于本系统没有采用标准PCI总线提供
中断信号
因此驱动
中无中断处理模块
下面着重介绍对本设计比较重要
化设备过程以及打开设备模块、读写模块
设计方法
(1)
化设备过程
化设备过程也是本系统PCI设备驱动中最为关键
部分
由于本系统中允许PCI总线挂接其它
即插即用设备
因此
这部分
还需要保留
其部分代码及注释如下:
在2.4之前
内核版本中
需要手动
pci_find_device
来查找PCI设备
但在2.4版本后
则可以
probe探测
来完成对硬件
检测及信息获取工作
其部分代码如下:
在获取
PCI信息子
pci_rewin_pci_re-sources_claim
和注册设备子
pci_rewin_de-vice_register
里
笔者自己创建
PCI设备信息可以写人到pci_dev
然后由Liunx内核通过pci_register_drivet
将此PCI设备信息创建在PCI设备列表中
(2) 打开设备模块
打开设备模块主要用来检查设备号、开辟PCI总线映射空间
打开设备模块
部分代码及注释如下:
(3) 读写模块
读操作就是先通过memcpy_fromio
将PCI上传来
数据搬移到内核空间中
接收缓冲区
再用copy_to_user搬移到用户数据空间
接收缓冲区和接收数据散列表都要在
化模块中进行处理
读操作
部分代码及注释如下:
写操作与读操作正好相反
它先通过copy_from_user
将用户空间
数据搬移到内核空间中
发送缓冲区
再通过memcpy
搬移到PCI总线上
由于发送
数据长度是可变
所以每次发送都需要构造不同
发送散列表(发送缓冲区可以再
化时分配)
写操作
代码与读操作类似
故此省略
值得注意
是
在PCI设备用I/O方式读写
时候
CPU将被迫停止工作以等待PCI设备完成此操作
且每次只允许
个设备访问
这个策略不利于提升系统性能
但利用MPC8250芯片提供
DMA(直接内存访问)机制则可大大提高PCI总线
性能
这也是笔者下
步需要改进
地方
4 结束语 本文讨论了Linux2.6版本下开发设备驱动
原理和相关知识
着重介绍了无配置信息PCI设备驱动
开发方法
该驱动开发方法可成功应用于嵌入式TDMA卫星通信系统
测试证明:本系统可稳定有效工作
今后
工作将着重是提升系统性能并进行改进.
阅读(1609) | 评论(0) | 转发(0) |