基于嵌入式Linux的MPC850&nbspUSB 驱动程序的实现

摘  要: 本文介绍了嵌入式Linux下设备驱动程序的编写原理,并阐述了在Linux下MPC850&nbspUSB的驱动程序的具体实现。
关键词: 嵌入式Linux;驱动程序;USB;主控制器
Linux驱动程序的基本原理
Linux下开发设备驱动程序的原理较之Windows系统来说结构层次简单明了。Linux操作系统中定义了三种设备,即字符设备、块设备和网络设备。字符设备是指存取时没有缓存的设备。块设备的读写都有缓存来支持,并且块设备必须能够随机存取,字符设备则没有这个要求,USB设备主要通过快速串行通信来读写数据,一般把它作为字符设备处理。


图1 &nbspUSB驱动程序组成

挂在Linux系统上的每个设备都被描述为设备驱动程序文件,一些与设备有关的设备参数文件被保存在/dev目录下。用户自己提供或编写设备驱动时,也需要在/dev目录下有一个设备文件。设备驱动程序可以分为三个主要组成部分:一是自动配置和初始化子程序  二是服务于I/O请求的子程序  三是中断服务子程序。
用户对设备的访问主要有如下函数:
open,打开设备,典型的用法如下:open("/dev/xxx",&nbspflag);&nbspflag指定打开的参数,例如读写属性等;open函数返回一个整数fd句柄,如果fd小于0,表示打开错误。
read,&nbspwrite读写函数,用法如下:read(int&nbspfd,&nbspchar *buf,&nbspchar&nbsplength,..)。
ioctrl设备控制函数,用户各类设备的特殊控制。
驱动程序的设计就是实现上述四个函数与外加一个设备初始化函数。这些函数在设备驱动程序中可以是dev_init(),dev_open(),dev_read(),&nbspdev_write(),dev_ioctrl()等。声明一个称之为file&nbspoperation的结构体将用户级的open等函数与设备dev_open()等函数联系起来。例如
static&nbspstruct&nbspfile_operations&nbspdev-xxx_fops = {
NULL, /*&nbsplseek */
dev_read, /*&nbspread */
dev_write, /*&nbspwrite */
NULL, /*&nbspreaddir */
NULL, /*&nbspselect */
NULL, /*&nbspioctl */
NULL, /*&nbspmmap */
dev_open,
dev_close,
NULL /*&nbspfsync */
};
为了将用户驱动程序与内核结合起来,首先向内核注册,请求内核分配主设备号与次设备号;二是注册中断,以便外部设备向CPU发出中断后能够处理设备中断函数。这些操作的一半在dev_init()函数内完成。dev_init()函数除了注册设备与注册中断外,还要完成设备特有寄存器初始化等操作。驱动程序与内核结合起来后,为了让应用程序能够访问该设备,还需要做一些额外的工作。前面提到,应用程序对设备的访问是通过访问文件的形式实现的,所以要建立一个文件节点与该设备相关联,使用命令 :
mknod  /dev/xxx&nbspoption &nbspmajor&nbspminor
可以实现上述的关联。该命令的含义是建立一个/dev/xxx的文件节点,并且把特定主设备号与次设备号的设备与该节点关联。Option选项指定设备的类型,字符型还是块设备。有了关联后,应用程序要访问该设备,只要调用open (“dev/xxx”,...)函数即可。

MPC850&nbspUSB
MPC850是Motorola公司生产的32位嵌入式通信处理器,具有强大的通信和网络协议处理能力,特别适用于嵌入式通信和网络系统,它提供的功能与MPC860相似,在MPC860系统功能基础上增加了对USB的支持。
MPC850&nbspUSB不提供任何OHCI和UHCI接口,但它有作为主机控制器必须的功能。MPC850&nbspUSB没有与根集线器连接,当不止一个USB设备时需接一个外部集线器。在MPC850中主控制器类似于功能单元(function),它不遵循OHCI和UHCI标准。USB控制器由一个发送模块、一个接收模块、两个协议状态机构组成。一个协议机构执行功能状态表,另一个执行主机状态表。USB控制器可完成一个USB功能端点,一个USB主机和两种检测的任务。主控制器的特点如下:

USB驱动程序由主控制驱动程序、USB子系统、USB设备驱动程序,如图1所示。
在Linux系统中存在一个连接USB设备驱动程序和主控制器驱动程序的子系统USBcore,它通过定义一些数据结构、宏和功能函数来抽象所有的硬件设备。USBcore提供了为硬件处理的所有下层接口,包含所有USB设备驱动和主机控制的通用程序,可称为UpperAPI和LowerAPI。USB子系统提供与设备驱动程序的接口,读取并解析USB设备描述符,配置描述符,为USB设备分配唯一的地址,使用默认的配置来配置设备,支持基本的USB命令请求,连接设备与相应的驱动程序,转发设备驱动程序的数据包。
虽然前面讲了驱动程序有两种加载模式,但是,如果&nbspUSBcore或主控制器驱动程序是内核模式,USB设备驱动程序就以模块方式加载。用usb_register和usb_deregister向USBcore子系统注册和注销驱动程序。所有USB驱动程序都有一个向子系统注册的结构。
struct&nbspusb_driver{
const&nbspchar *name;                  /*模块名字*/
void *(*probe,&nbspstruct&nbspusb_device*,&nbspunsigned&nbspint);    /*probe 功能入口点*/
void (*disconnect,&nbspstruct&nbspusb_device*,&nbspvoid*);      /*disconnect功能入口点*/
struct&nbsplist_head&nbspdriver_list;    /*子系统内部初始化*/
struct&nbspfile_operations&nbspfops;    /对驱动函数文件列表*/
int&nbspminor;
}
在高速USB中时序安排是以1帧为基本要素的,每1ms为1帧,在每帧要产生并发送SOF包之外,还需要一个微码通道。同步传输和中断传输占90%的有效带宽,控制传输占10%,剩下的为块传输,如下表所示:
SOF&nbspIsochronous&nbspInterrupt&nbspControl&nbspBulk
控制传输完成了设备的配置,设备的轮流检测是由中断传输完成,大量的数据传输由块传输和同步传输完成。
MPC850是不支持这样的时序调度的,我们用1ms的时序器产生一个中断并在软件中运行这个调度。每个SOF时序里我们都加入一个SOF包到tx列表中,并监视发送包的列表,包是依据优先权来加入的。在每帧开始时,检查未处理事务,将符合优先级的队列元素放到当前帧中。驱动程序跟踪处理事务的设备,并不再向它发送事务。程序中用一个队列结构来完成这一调度的。如: 下面是分派队列元素到发送帧的结构。
struct&nbspm8xxhci_qe *
take_from_current_frame(int&nbspqtype)
{
 &nbspstruct&nbspm8xxhci_private *hp = (struct&nbspm8xxhci_private *)m8xxhci_ptr;
 &nbspunsigned&nbsplong&nbspflags;
 &nbspstruct&nbsplist_head *list;
 &nbspstruct&nbspm8xxhci_qe *qe =&nbspNULL;
  ┋
 &nbspif (!list_empty(list)) {
  ┋ 
 &nbspqe->on_frame_list =&nbsp0;
  ┋
  }
 &nbspspin_unlock_irqrestore(&framelist_lock,&nbspflags);
 &nbspreturn&nbspqe;
  }
MPC850&nbspUSB主控制器的有些任务是硬件不支持的,必须由软件来实现。例如,发生错误及错误恢复后的重传、每秒产生和传输SOF、CRC5的产生等。这些功能是通过相应的结构体来完成,主控制器驱动向USBcore数据结构注册它的功能函数,它完成接口硬件的初始化、状态控制、传输差错控制、发送SOF帧、数据处理。
结构的每一个成员的名字都对应着一个系统调用,剩下的主要是子函数及结构体的编写,而编写子函数就很容易了。

结语
嵌入式Linux以及USB设备的应用越来越广泛。本文分析了MPC850&nbspUSB控制器的特点,描述了在嵌入式Linux操作系统下设备驱动程序的实现,对于使用PowerPC 系列CPU的开发人员具有一定的借鉴作用。■

参考文献:
1. &nbspALESSANDRO&nbspRUBINI,‘LINUX设备驱动程序’,中国电力出版社,2000
2. 王学龙,‘嵌入式Linux系统设计与应用’,清华大学出版社,2001


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值