最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

基于嵌入式Linux的USB主控制器驱动设计

IT圈 admin 53浏览 0评论

2024年1月23日发(作者:斐鸿禧)

基于嵌入式Linux的USB主控制器驱动设计

Design of USB Host Controller Driver Based on Embedded Linux

Abstract: This paper designs the USB host controller driver for the USB host

controller of S3C2410. The driver is based on Linux, it followed USB 1.1 and OHCI

1.0 specification. This driver makes the embedded system with S3C2410 has USB

host function and can communicate with USB devices.

Key Word: USB host controller driver, Linux, S3C2410

摘 要:本文为S3C2410的USB主机控制器设计了基于Linux的USB主机控制器驱动程序。该驱动程序遵循USB1.1版本协议和OHCI 1.0版本协议。使具有S3C2410的嵌入式系统具备了USB主机功能,能够和各种USB设备进行通信。

关键词:USB主机控制器驱动,Linux,S3C2410

1 引言

随 着USB技术越来越多地被应用到嵌入式领域,人们对身边所使用的嵌入式系统提出了新的要求,希望在嵌入式系统中增加USB主机功能,使嵌入式系统具有移动 存储功能,如挂接各种移动存储设备、直接与USB打印机连接打印数码相片等。嵌入式USB主机系统的开发成为当前的一个热点。

嵌入式USB主机系 统设计包括软件和硬件两个部分。其中软件设计主要包括USB核心驱动程序和USB主机控制器驱动程序两个部分。Linux操作系统是一个源码开放,资源丰 富的操作系统。Linux系统对USB主机协议提供了一定的支持,并提供了众多的USB类设备驱动程序,为应用开发提供了便捷。

2 USB主机系统概述

在USB接口协议中,USB系统被划分成USB主机和USB设备两个部分。系统中所有的数据传输都发生在主机和设备之间,主机是USB的核心,它管理着每个USB设备,每一次USB数据通信都必须由USB主机来发起。

USB 主机系统由多层构成。其中最低层为硬件,包括根集线器和USB主机控制器(简称HC),HC是USB主机系统的硬件核心,提供USB的物理层功能。HC向 上提供一个接口协议 HCI(Host Controller Interface), USB主机控制器驱动程序(USB Host Controller Driver,简称HCD)是此接口的具体实现;USB核心驱动(USB Driver,简称USBD)为USB设备的用户提供基本的主机接口;USB设备类驱动程序为USB用户驱动程序,需要根据USB设备所属的设备类进行设 计。

HCD作为底层硬件的驱动程序,一方面控制和管理硬件底层,负责将USB事务发送给USB主机控制器芯片,并最终将串行数据发送到电缆上。另 一方面为上层的 USB 系统软件提供了统一的接口,方便地将各种不同的 HC 映射到 USB

系统。目前HCI的实现有三种不同的标准:UHCI、OHCI和EHCI,其中OHCI标准专门用在非PC领域。

3 Linux下的USB子系统

Linux 是一个类Unix的操作系统,具有非常好的移植性,被应用到许多不同体系结构的计算机中。Linux中USB子系统的结构如图3.1所示。该子系统专门用

于支持USB设备和USB主机控制器,分为三层结构。USBD所在层为USB内核,USB内核为客户端驱动程序和HCD提供接口函数,并负责维护设备的加 载、配置、设备驱动程序的安装和卸载等。

4 S3C2410的USB主机控制器驱动实现

4.1 S3C2410简介

S3C2410 是三星公司生产的32位的RISC处理器,采用了ARM920T内核,内部带有全性能的内存处理单元(MMU),最高工作频率可达203MHz。该芯片支 持Thumb16位压缩指令集,从而可以较小的存储空间需求,获得32位的系统性能。S3C2410提供了两个USB主机接口,该接口支持OHCI 标准1.0版本和USB协议 1.1版本,支持低速和高速两类USB设备的数据传输。S3C2410的USB主机接口的相关寄存器均符合OHCI标准的定义和排列。目前S3C2410 芯片已经在手持电话、机顶盒、数码相机、GPS、个人数字助理及因特网设备等方面有了广泛的应用。

4.2 HCD功能描述

OHCI定义了 HCD和HC之间的接口以及他们之间的一些操作。在OHCI标准中,HC负责USB总线的状态管理、帧产生、链表管理。HCD是对USB主机控制器硬件和 数据传输的一种抽象,负责管理主控制器、为各种类型的传输分配带宽、创建和维护各种数据链表并负责根集线器的相关管理。它完成的具体功能如下:

•主机控制器硬件初始化;

•为USBD层提供相应的接口函数;

•为提供根HUB配置、控制功能;

•完成4种类型的数据传输。

4.3 USB主机控制器驱动实现

1.主机控制器的初始化和管理

当 主机控制器驱动程序被Linux操作系统加载后,Linux首先会调用s3c2410_ohci_init函数,对USB接口进行初始化。由于 S3C2410含有两个USB接口,可以配置成2个USB主控接口或1个主控接口、一个设备接口的形式,需要在初始化程序中配置S3C2410的USB接 口的工作方式。之后需要在系统注册一个OHCI标准的USB主控设备,创建一个ohci_hcd 数据结构,该结构包含了OHCI标准定义的操作寄存器、HCCA、各种数据链表等信息。

ohci_hcd创建之后,需要调用USBD中的函数usb_alloc_bus请求系统分配相应的USB总线资源,并给主机控制器分配内存。然后设置各种OHCI控制器、设置总线操作、开启中断,并连接虚根集线器。设置函数定义为hc_start,其具体代码定义如下:

static int hc_start (ohci_t * ohci)

{ ……

//向OHCI寄存器中写入控制、批量链表的表头

writel (0, &ohci->regs->ed_controlhead);

……

//启动控制器操作

ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;

ohci->disabled = 0;

writel (ohci->hc_control, &ohci->regs->control);

//开启中断

mask = OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_WDH |

OHCI_INTR_SO;

writel (mask, &ohci->regs->intrenable);

……

//连接虚根集线器

……

usb_connect (usb_dev);

……

return 0;

}

2.为USBD层提供相应的接口函数

USB主机控制器驱动为USB核心驱动屏蔽了硬件操作,完成了USB底层数据传输,它为上层驱动提供了简单的软件接口,定义了usb_operations数据结构,该数据结构中定义了5个函数供USB总线驱动调用。usb_operations数据结构定义如下:

struct usb_operations sohci_device_operations = {

allocate: sohci_alloc_dev, //分配USB设备资源

deallocate: sohci_free_dev, //收回USB设备资源

get_frame_number: sohci_get_current_frame_number, //取当前帧号

submit_urb: sohci_submit_urb, //提交USB请求块

unlink_urb: sohci_unlink_urb, //撤消USB请求块

};

USB 总线上的所有传输都是由函数sochi_submit_urb发起的。该函数根据URB定位相关端点的ED,将ED添加到相应类型的传输链表。函数为 URB中的数据生成TD队列,并将TD队列链接到相应ED。如果URB指示的传输类型是中断或等时传输,还需要为传输分配所需的带宽。 sohci_submit_urb函数实现过程如下:

static int sohci_submit_urb (struct urb * urb, int mem_flags)

{ ......

//每一个端点都有ED,定位该ED并将URB中的相关信息填充到ED中,然后将该ED添加至相应的管道。

if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1, mem_flags))) {...... }

//根据传输管道类型确定TD的大小。

switch (usb_pipetype (pipe)) { ...... }

//将传输事件分成若干个TD

......

//为中断和等时传输分配所需的带宽

......

bustime = usb_check_bandwidth (urb->dev, urb);

……

usb_claim_bandwidth (urb->dev, urb, bustime, usb_pipeisoc (urb->pipe))

//将ED链接到ED链表上

if (ed->state != ED_OPER) ep_link (ohci, ed);

//填充TD,并将TD链接到ED上

td_submit_urb (urb);

//使ED可用,至此主机控制器就可以处理这个传输事务了。

…….

return 0;

}

sohci_unlink_urb用于取消一个urb的数据请求处理。函数调用ep_rm_ed函数停止控制器对该URB对应的ED处理,并将该ED从对相应链表卸除,继而停止TD队列的处理。

3.链表处理及资源调度

USB 主机控制器完成的所有USB数据传输,都是围绕着OHCD所建立的ED链表和TD队列进行的。如前所述,当USB上层驱动发起一个USB总线请求 时,sohci_submit_urb会调用ep_add_ed等函数对ED链表和TD链表进行插入、删除等操作。这些函数的功能如下述:

ep_add_ed函数,用于创建一个ED。函数首先要判断端点的类型,然后为端点创建一个新的ED,并将ED插入对应与其端点类型相同的ED链表。

ep_link用于完成ED链接到ED链表的操作,对于不同的ED,链接处理是不相同的。对于批量和控制传输的端点来说,直接选定链表,将ED插入链表即可。对于周期性端点的ED来说,需要根据端点的访问周期决定将ED插入到哪个链表当中。

ep_rm_ed用于从链表上删除一个ED。函数首先定位ED是否属于控制ED链表和批量ED链表,如果属于这两种链表,首先停止对这两种链表的处理,然后再将ED从链表上删除。

td_submit_urb 函数根据从URB中获得的数据包的信息,将数据包划分成若干的TD,并形成TD链表。TD的划分需要根据USB协议对不同传输类型的数据传输包尺寸的限制 来进行。对于输出操作来说,要根据各种传输类型限制的最大包长度以及数据缓冲区中剩余的数据长度来决定TD中数据包的尺寸。对输入操作而言,由端点的需求 来决定。如对于控制传输,设定数据包的最大长度为8字节,则每个TD中包含一个最长为8字节的数据包。

4.虚拟根集线器

在OHCI中,根集线器是HC的一个重要组成部分,它和HC的通信不需要经过USB的总线传输,只要通过读取主机控制器硬件中与根集线器相关的寄存器就可以实现。

在 Linux中专门为根集线器编写了标准的USB集线器驱动程序,HCD只要把对根集线器的管理,交给USB集线器驱动统一管理,然后通过专门的函数来模拟

执行从USB集线器驱动程序发来的总线请求即可。HCD对虚拟根集线器管理的函数主要有rh_submit_urb、rh_int_timer_do等。 rh_submit_urb函数来模拟执行集线器驱动程序发来的总线请求。rh_int_timer_do函数以查询的方式循环读每个根端口的状态,并保 存在集线器寄存器中。USB主机控制器把从根集线器寄存器读来的数据送回,这样集线器驱动就会根据端口状态的变化判断设备的插入和拔出。

5 结束语

本文软件上采用Linux操作系统,硬件上采用32位RISC处理器S3C2410。由于S3C2410处理器内部集成了USB主机控制器,省去了CPU和USB主机控制器芯片的接口电路设计,极大的简化了系统的设计,可以为同类嵌入式USB主机系统开发所借鉴。

本文作者创新点:在嵌入式系统开发中,Linux操作系统被广泛的应用,基于Linux操作系统进行USB主机系统的开发,将简化系统的设计,必将广泛应用于工业数据采集、医疗监护、移动数码存储等领域。

参考文献

[1] Universal Serial Bus Specification Revision 1.1, September

23,://;

[2] Compaq, Microsoft, National, Semiconductor. Open Host Controller Interface

Specification for USB Release 1.0a. ;

[3] 孙天泽等.嵌入式设计及LINUX驱动开发指南—基于ARM9处理器[M].北京:电子工业出版社.2005;

[4]李信利,吕月娥.基于S3C4510B的嵌入式USB的设计与实现[J]. 微计算机信息,2007,5-2,161-162,165.

2024年1月23日发(作者:斐鸿禧)

基于嵌入式Linux的USB主控制器驱动设计

Design of USB Host Controller Driver Based on Embedded Linux

Abstract: This paper designs the USB host controller driver for the USB host

controller of S3C2410. The driver is based on Linux, it followed USB 1.1 and OHCI

1.0 specification. This driver makes the embedded system with S3C2410 has USB

host function and can communicate with USB devices.

Key Word: USB host controller driver, Linux, S3C2410

摘 要:本文为S3C2410的USB主机控制器设计了基于Linux的USB主机控制器驱动程序。该驱动程序遵循USB1.1版本协议和OHCI 1.0版本协议。使具有S3C2410的嵌入式系统具备了USB主机功能,能够和各种USB设备进行通信。

关键词:USB主机控制器驱动,Linux,S3C2410

1 引言

随 着USB技术越来越多地被应用到嵌入式领域,人们对身边所使用的嵌入式系统提出了新的要求,希望在嵌入式系统中增加USB主机功能,使嵌入式系统具有移动 存储功能,如挂接各种移动存储设备、直接与USB打印机连接打印数码相片等。嵌入式USB主机系统的开发成为当前的一个热点。

嵌入式USB主机系 统设计包括软件和硬件两个部分。其中软件设计主要包括USB核心驱动程序和USB主机控制器驱动程序两个部分。Linux操作系统是一个源码开放,资源丰 富的操作系统。Linux系统对USB主机协议提供了一定的支持,并提供了众多的USB类设备驱动程序,为应用开发提供了便捷。

2 USB主机系统概述

在USB接口协议中,USB系统被划分成USB主机和USB设备两个部分。系统中所有的数据传输都发生在主机和设备之间,主机是USB的核心,它管理着每个USB设备,每一次USB数据通信都必须由USB主机来发起。

USB 主机系统由多层构成。其中最低层为硬件,包括根集线器和USB主机控制器(简称HC),HC是USB主机系统的硬件核心,提供USB的物理层功能。HC向 上提供一个接口协议 HCI(Host Controller Interface), USB主机控制器驱动程序(USB Host Controller Driver,简称HCD)是此接口的具体实现;USB核心驱动(USB Driver,简称USBD)为USB设备的用户提供基本的主机接口;USB设备类驱动程序为USB用户驱动程序,需要根据USB设备所属的设备类进行设 计。

HCD作为底层硬件的驱动程序,一方面控制和管理硬件底层,负责将USB事务发送给USB主机控制器芯片,并最终将串行数据发送到电缆上。另 一方面为上层的 USB 系统软件提供了统一的接口,方便地将各种不同的 HC 映射到 USB

系统。目前HCI的实现有三种不同的标准:UHCI、OHCI和EHCI,其中OHCI标准专门用在非PC领域。

3 Linux下的USB子系统

Linux 是一个类Unix的操作系统,具有非常好的移植性,被应用到许多不同体系结构的计算机中。Linux中USB子系统的结构如图3.1所示。该子系统专门用

于支持USB设备和USB主机控制器,分为三层结构。USBD所在层为USB内核,USB内核为客户端驱动程序和HCD提供接口函数,并负责维护设备的加 载、配置、设备驱动程序的安装和卸载等。

4 S3C2410的USB主机控制器驱动实现

4.1 S3C2410简介

S3C2410 是三星公司生产的32位的RISC处理器,采用了ARM920T内核,内部带有全性能的内存处理单元(MMU),最高工作频率可达203MHz。该芯片支 持Thumb16位压缩指令集,从而可以较小的存储空间需求,获得32位的系统性能。S3C2410提供了两个USB主机接口,该接口支持OHCI 标准1.0版本和USB协议 1.1版本,支持低速和高速两类USB设备的数据传输。S3C2410的USB主机接口的相关寄存器均符合OHCI标准的定义和排列。目前S3C2410 芯片已经在手持电话、机顶盒、数码相机、GPS、个人数字助理及因特网设备等方面有了广泛的应用。

4.2 HCD功能描述

OHCI定义了 HCD和HC之间的接口以及他们之间的一些操作。在OHCI标准中,HC负责USB总线的状态管理、帧产生、链表管理。HCD是对USB主机控制器硬件和 数据传输的一种抽象,负责管理主控制器、为各种类型的传输分配带宽、创建和维护各种数据链表并负责根集线器的相关管理。它完成的具体功能如下:

•主机控制器硬件初始化;

•为USBD层提供相应的接口函数;

•为提供根HUB配置、控制功能;

•完成4种类型的数据传输。

4.3 USB主机控制器驱动实现

1.主机控制器的初始化和管理

当 主机控制器驱动程序被Linux操作系统加载后,Linux首先会调用s3c2410_ohci_init函数,对USB接口进行初始化。由于 S3C2410含有两个USB接口,可以配置成2个USB主控接口或1个主控接口、一个设备接口的形式,需要在初始化程序中配置S3C2410的USB接 口的工作方式。之后需要在系统注册一个OHCI标准的USB主控设备,创建一个ohci_hcd 数据结构,该结构包含了OHCI标准定义的操作寄存器、HCCA、各种数据链表等信息。

ohci_hcd创建之后,需要调用USBD中的函数usb_alloc_bus请求系统分配相应的USB总线资源,并给主机控制器分配内存。然后设置各种OHCI控制器、设置总线操作、开启中断,并连接虚根集线器。设置函数定义为hc_start,其具体代码定义如下:

static int hc_start (ohci_t * ohci)

{ ……

//向OHCI寄存器中写入控制、批量链表的表头

writel (0, &ohci->regs->ed_controlhead);

……

//启动控制器操作

ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;

ohci->disabled = 0;

writel (ohci->hc_control, &ohci->regs->control);

//开启中断

mask = OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_WDH |

OHCI_INTR_SO;

writel (mask, &ohci->regs->intrenable);

……

//连接虚根集线器

……

usb_connect (usb_dev);

……

return 0;

}

2.为USBD层提供相应的接口函数

USB主机控制器驱动为USB核心驱动屏蔽了硬件操作,完成了USB底层数据传输,它为上层驱动提供了简单的软件接口,定义了usb_operations数据结构,该数据结构中定义了5个函数供USB总线驱动调用。usb_operations数据结构定义如下:

struct usb_operations sohci_device_operations = {

allocate: sohci_alloc_dev, //分配USB设备资源

deallocate: sohci_free_dev, //收回USB设备资源

get_frame_number: sohci_get_current_frame_number, //取当前帧号

submit_urb: sohci_submit_urb, //提交USB请求块

unlink_urb: sohci_unlink_urb, //撤消USB请求块

};

USB 总线上的所有传输都是由函数sochi_submit_urb发起的。该函数根据URB定位相关端点的ED,将ED添加到相应类型的传输链表。函数为 URB中的数据生成TD队列,并将TD队列链接到相应ED。如果URB指示的传输类型是中断或等时传输,还需要为传输分配所需的带宽。 sohci_submit_urb函数实现过程如下:

static int sohci_submit_urb (struct urb * urb, int mem_flags)

{ ......

//每一个端点都有ED,定位该ED并将URB中的相关信息填充到ED中,然后将该ED添加至相应的管道。

if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1, mem_flags))) {...... }

//根据传输管道类型确定TD的大小。

switch (usb_pipetype (pipe)) { ...... }

//将传输事件分成若干个TD

......

//为中断和等时传输分配所需的带宽

......

bustime = usb_check_bandwidth (urb->dev, urb);

……

usb_claim_bandwidth (urb->dev, urb, bustime, usb_pipeisoc (urb->pipe))

//将ED链接到ED链表上

if (ed->state != ED_OPER) ep_link (ohci, ed);

//填充TD,并将TD链接到ED上

td_submit_urb (urb);

//使ED可用,至此主机控制器就可以处理这个传输事务了。

…….

return 0;

}

sohci_unlink_urb用于取消一个urb的数据请求处理。函数调用ep_rm_ed函数停止控制器对该URB对应的ED处理,并将该ED从对相应链表卸除,继而停止TD队列的处理。

3.链表处理及资源调度

USB 主机控制器完成的所有USB数据传输,都是围绕着OHCD所建立的ED链表和TD队列进行的。如前所述,当USB上层驱动发起一个USB总线请求 时,sohci_submit_urb会调用ep_add_ed等函数对ED链表和TD链表进行插入、删除等操作。这些函数的功能如下述:

ep_add_ed函数,用于创建一个ED。函数首先要判断端点的类型,然后为端点创建一个新的ED,并将ED插入对应与其端点类型相同的ED链表。

ep_link用于完成ED链接到ED链表的操作,对于不同的ED,链接处理是不相同的。对于批量和控制传输的端点来说,直接选定链表,将ED插入链表即可。对于周期性端点的ED来说,需要根据端点的访问周期决定将ED插入到哪个链表当中。

ep_rm_ed用于从链表上删除一个ED。函数首先定位ED是否属于控制ED链表和批量ED链表,如果属于这两种链表,首先停止对这两种链表的处理,然后再将ED从链表上删除。

td_submit_urb 函数根据从URB中获得的数据包的信息,将数据包划分成若干的TD,并形成TD链表。TD的划分需要根据USB协议对不同传输类型的数据传输包尺寸的限制 来进行。对于输出操作来说,要根据各种传输类型限制的最大包长度以及数据缓冲区中剩余的数据长度来决定TD中数据包的尺寸。对输入操作而言,由端点的需求 来决定。如对于控制传输,设定数据包的最大长度为8字节,则每个TD中包含一个最长为8字节的数据包。

4.虚拟根集线器

在OHCI中,根集线器是HC的一个重要组成部分,它和HC的通信不需要经过USB的总线传输,只要通过读取主机控制器硬件中与根集线器相关的寄存器就可以实现。

在 Linux中专门为根集线器编写了标准的USB集线器驱动程序,HCD只要把对根集线器的管理,交给USB集线器驱动统一管理,然后通过专门的函数来模拟

执行从USB集线器驱动程序发来的总线请求即可。HCD对虚拟根集线器管理的函数主要有rh_submit_urb、rh_int_timer_do等。 rh_submit_urb函数来模拟执行集线器驱动程序发来的总线请求。rh_int_timer_do函数以查询的方式循环读每个根端口的状态,并保 存在集线器寄存器中。USB主机控制器把从根集线器寄存器读来的数据送回,这样集线器驱动就会根据端口状态的变化判断设备的插入和拔出。

5 结束语

本文软件上采用Linux操作系统,硬件上采用32位RISC处理器S3C2410。由于S3C2410处理器内部集成了USB主机控制器,省去了CPU和USB主机控制器芯片的接口电路设计,极大的简化了系统的设计,可以为同类嵌入式USB主机系统开发所借鉴。

本文作者创新点:在嵌入式系统开发中,Linux操作系统被广泛的应用,基于Linux操作系统进行USB主机系统的开发,将简化系统的设计,必将广泛应用于工业数据采集、医疗监护、移动数码存储等领域。

参考文献

[1] Universal Serial Bus Specification Revision 1.1, September

23,://;

[2] Compaq, Microsoft, National, Semiconductor. Open Host Controller Interface

Specification for USB Release 1.0a. ;

[3] 孙天泽等.嵌入式设计及LINUX驱动开发指南—基于ARM9处理器[M].北京:电子工业出版社.2005;

[4]李信利,吕月娥.基于S3C4510B的嵌入式USB的设计与实现[J]. 微计算机信息,2007,5-2,161-162,165.

发布评论

评论列表 (0)

  1. 暂无评论