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

来源:本站
导读:目前正在解读《基于嵌入式Linux的MPC850 USB 驱动程序的实现》的相关信息,《基于嵌入式Linux的MPC850 USB 驱动程序的实现》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《基于嵌入式Linux的MPC850 USB 驱动程序的实现》的详细说明。
简介: 本文介绍了嵌入式Linux下设备驱动程序的编写原理,并阐述了在Linux下MPC850 USB的驱动程序的具体实现。

Linux驱动程序的基本原理

Linux下开发设备驱动程序的原理较之Windows系统来说结构层次简单明了。Linux操作系统中定义了三种设备,即字符设备、块设备和网络设备。字符设备是指存取时没有缓存的设备。块设备的读写都有缓存来支持,并且块设备必须能够随机存取,字符设备则没有这个要求,USB设备主要通过快速串行通信来读写数据,一般把它作为字符设备处理。

挂在Linux系统上的每个设备都被描述为设备驱动程序文件,一些与设备有关的设备参数文件被保存在/dev目录下。用户自己提供或编写设备驱动时,也需要在/dev目录下有一个设备文件。设备驱动程序可以分为三个主要组成部分:一是自动配置和初始化子程序 二是服务于I/O请求的子程序 三是中断服务子程序。

用户对设备的访问主要有如下函数:

open,打开设备,典型的用法如下:open("/dev/xxx", flag); flag指定打开的参数,例如读写属性等;open函数返回一个整数fd句柄,如果fd小于0,表示打开错误。

read, write读写函数,用法如下:read(int fd, char *buf, char length,..)。

ioctrl设备控制函数,用户各类设备的特殊控制。

驱动程序的设计就是实现上述四个函数与外加一个设备初始化函数。这些函数在设备驱动程序中可以是dev_init(),dev_open(),dev_read(), dev_write(),dev_ioctrl()等。声明一个称之为file operation的结构体将用户级的open等函数与设备dev_open()等函数联系起来。例如

static struct file_operations dev-xxx_fops = {

NULL, /* lseek */

dev_read, /* read */

dev_write, /* write */

NULL, /* readdir */

NULL, /* select */

NULL, /* ioctl */

NULL, /* mmap */

dev_open,

dev_close,

NULL /* fsync */

};

为了将用户驱动程序与内核结合起来,首先向内核注册,请求内核分配主设备号与次设备号;二是注册中断,以便外部设备向CPU发出中断后能够处理设备中断函数。这些操作的一半在dev_init()函数内完成。dev_init()函数除了注册设备与注册中断外,还要完成设备特有寄存器初始化等操作。驱动程序与内核结合起来后,为了让应用程序能够访问该设备,还需要做一些额外的工作。前面提到,应用程序对设备的访问是通过访问文件的形式实现的,所以要建立一个文件节点与该设备相关联,使用命令 :

mknod /dev/xxx option major minor

可以实现上述的关联。该命令的含义是建立一个/dev/xxx的文件节点,并且把特定主设备号与次设备号的设备与该节点关联。Option选项指定设备的类型,字符型还是块设备。有了关联后,应用程序要访问该设备,只要调用open (“dev/xxx”,...)函数即可。

MPC850 USB

MPC850是Motorola公司生产的32位嵌入式通信处理器,具有强大的通信和网络协议处理能力,特别适用于嵌入式通信和网络系统,它提供的功能与MPC860相似,在MPC860系统功能基础上增加了对USB的支持。

MPC850 USB不提供任何OHCI和UHCI接口,但它有作为主机控制器必须的功能。MPC850 USB没有与根集线器连接,当不止一个USB设备时需接一个外部集线器。在MPC850中主控制器类似于功能单元(function),它不遵循OHCI和UHCI标准。USB控制器由一个发送模块、一个接收模块、两个协议状态机构组成。一个协议机构执行功能状态表,另一个执行主机状态表。USB控制器可完成一个USB功能端点,一个USB主机和两种检测的任务。主控制器的特点如下:

USB驱动程序由主控制驱动程序、USB子系统、USB设备驱动程序。

在Linux系统中存在一个连接USB设备驱动程序和主控制器驱动程序的子系统USBcore,它通过定义一些数据结构、宏和功能函数来抽象所有的硬件设备。USBcore提供了为硬件处理的所有下层接口,包含所有USB设备驱动和主机控制的通用程序,可称为UpperAPI和LowerAPI。USB子系统提供与设备驱动程序的接口,读取并解析USB设备描述符,配置描述符,为USB设备分配唯一的地址,使用默认的配置来配置设备,支持基本的USB命令请求,连接设备与相应的驱动程序,转发设备驱动程序的数据包。

虽然前面讲了驱动程序有两种加载模式,但是,如果 USBcore或主控制器驱动程序是内核模式,USB设备驱动程序就以模块方式加载。用usb_register和usb_deregister向USBcore子系统注册和注销驱动程序。所有USB驱动程序都有一个向子系统注册的结构。

struct usb_driver{

const char *name; /*模块名字*/

void *(*probe, struct usb_device*, unsigned int); /*probe 功能入口点*/

void (*disconnect, struct usb_device*, void*); /*disconnect功能入口点*/

struct list_head driver_list; /*子系统内部初始化*/

struct file_operations fops; /对驱动函数文件列表*/

int minor;

}

在高速USB中时序安排是以1帧为基本要素的,每1ms为1帧,在每帧要产生并发送SOF包之外,还需要一个微码通道。同步传输和中断传输占90%的有效带宽,控制传输占10%,剩下的为块传输,如下表所示:

SOF Isochronous Interrupt Control Bulk

控制传输完成了设备的配置,设备的轮流检测是由中断传输完成,大量的数据传输由块传输和同步传输完成。

MPC850是不支持这样的时序调度的,我们用1ms的时序器产生一个中断并在软件中运行这个调度。每个SOF时序里我们都加入一个SOF包到tx列表中,并监视发送包的列表,包是依据优先权来加入的。在每帧开始时,检查未处理事务,将符合优先级的队列元素放到当前帧中。驱动程序跟踪处理事务的设备,并不再向它发送事务。程序中用一个队列结构来完成这一调度的。如: 下面是分派队列元素到发送帧的结构。

struct m8xxhci_qe *

take_from_current_frame(int qtype)

{

struct m8xxhci_private *hp = (struct m8xxhci_private *)m8xxhci_ptr;

unsigned long flags;

struct list_head *list;

struct m8xxhci_qe *qe = NULL;

if (!list_empty(list)) {

qe->on_frame_list = 0;

}

spin_unlock_irqrestore(&framelist_lock, flags);

return qe;

}

MPC850 USB主控制器的有些任务是硬件不支持的,必须由软件来实现。例如,发生错误及错误恢复后的重传、每秒产生和传输SOF、CRC5的产生等。这些功能是通过相应的结构体来完成,主控制器驱动向USBcore数据结构注册它的功能函数,它完成接口硬件的初始化、状态控制、传输差错控制、发送SOF帧、数据处理。

结构的每一个成员的名字都对应着一个系统调用,剩下的主要是子函数及结构体的编写,而编写子函数就很容易了。

结语

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

提醒:《基于嵌入式Linux的MPC850 USB 驱动程序的实现》最后刷新时间 2024-03-14 01:03:00,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《基于嵌入式Linux的MPC850 USB 驱动程序的实现》该内容的真实性请自行鉴别。