s3c2440的USB主机控制器
时间:11-19
来源:互联网
点击:
s3c2440提供了USB主机接口,它与OHCI v1.0完全兼容。要使用该功能,就必须熟悉OHCI v1.0规范;而要熟悉OHCI v1.0规范,那么还必须先熟悉USB v1.1协议。因此涉及到该部分的内容较多,要想正确使用s3c2440所提供的USB主机接口也不是一件容易的事情。在这里,我主要介绍USB设备枚举过程中所涉及到的一些知识,并给出具体的实现程序。
OHCI(Open HCI)是目前使用比较广泛的三种USB主机控制器规范之一。USB体系结构是由四个主要部分组成:客户软件/USB驱动,主机控制器驱动(HCD),主机控制器(HC)和USB驱动。前两者由软件实现,后两者由硬件实现。而OHCI就是规范了主机控制器驱动和主机控制器之间的接口,以及它们的基本操作。在主机控制器驱动和主机控制器之间,有两个通信通道,第一个是应用位于HC的一套可操作寄存器,它们包括控制寄存器、状态寄存器和列表指针寄存器;另一个通道是应用称为主机控制器通信域(HCCA)的共享内存。
USB定义了四种数据传输类型:控制传输、批量传输、中断传输和同步传输。在OHCI规范中把数据传输类型分为两类:周期传输和非周期传输。同步传输和中断传输属于周期传输,控制传输和批量传输属于非周期传输。USB定义了每帧的周期为1.0毫秒,为了保证每一帧都能发生周期传输和非周期传输,一般地,OHCI把每一帧的带宽分为四个部分,首先是发送SOF,然后是非周期传输,紧接着是周期传输,如果周期传输完毕后,还有时间,则剩余的时间仍然留给非周期传输。
端点描述符(ED)和传输描述符(TD)是两个最基本的通信模块。ED包含了一个端点的信息,它被HC用来管理使用端点。ED的典型参数包括端点地址、传输速度、最大数据包大小,另外ED还提供了TD链表的停靠地(锚点)。TD是一个依赖于ED的内存缓存区,用于与端点之间进行数据传输。当HC存取一个ED,并且找到一个有效的TD地址时,则HC就完成了一个简单的与端点之间的传输任务,这个端点是由ED确定,而所存取的数据内存地址由TD指定。当所有的被TD所定义的数据传输完毕后,TD就从ED中解链出来,并链接到完成列表中。这个完成列表能够被HCD所处理,以提供一些完成信息。
ED的数据结构长度为16字节,它的数据域有:
FA:USB的功能地址;
EN:USB功能内的端点地址;
D:数据流的传输方向,是IN,OUT,还是有TD来决定传输方向;
S:速度,全速还是低速;
K:用于设置跳过当前ED;
F:链接于ED的TD的形式,是通用TD格式还是同步TD格式;
MPS:数据传输的最大字节大小;
TailP:TD列表的尾指针;
H:用于停止当前TD列表的处理;
C:数据翻转进位位;
HeadP:TD列表的头指针;
NextED:下一个要处理的ED指针。
根据上述说明,我们可以定义ED为下面的数据类型:
typedef struct _ED {
volatile unsigned int Control;
volatile unsigned int TailP;
volatile unsigned int HeadP;
volatile unsigned int NextEd;
} ED, *P_ED;
由于ED必须是16字节地址对齐形式,因此我们必须用下面的形式来声明它的变量:
__align(16) ED ed;
我们可以用下面的函数来创建一个ED:
__inline void CreateEd(
unsigned int EDAddr,//ED地址指针
unsigned int MaxPacket,//MPS
unsigned int TDFormat,//F
unsigned int Skip,//K
unsigned int Speed,//S
unsigned int Direction,//D
unsigned int EndPt,//EN
unsigned int FuncAddress,//FA
unsigned int TDQTailPntr,//TailP
unsigned int TDQHeadPntr,//HeadP
unsigned int ToggleCarry,//C
unsigned int NextED)//NextED
{
P_ED pED = (P_ED) EDAddr;
pED->Control = (MaxPacket < 16) | (TDFormat < 15) |(Skip < 14) | (Speed < 13)
| Direction < 11) | (EndPt < 7) | FuncAddress;
pED->TailP = (TDQTailPntr & 0xFFFFFFF0);
pED->HeadP = (TDQHeadPntr & 0xFFFFFFF0) | (ToggleCarry < 1);
pED->NextEd = (NextED & 0xFFFFFFF0);
}
TD共有两种类型:通用TD和同步TD。通用TD用于中断、控制和批量端点,同步TD用于同步传输。在这里,我们只给出通用TD的数据结构和定义。
通用TD的数据结构长度也是16字节,它的数据域有:
R:缓存凑整,用于设置是否需要最后一个数据包的长度与所定义的长度一致;
DP:方向,是IN,OUT,还是SETUP;
DI:延时中断;
T:数据翻转;
EC:传输错误计数;
CC:条件码,为上一次企图传输的状态;
CBP:将要被传输的数据内存物理地址;
NextTD:下一个TD;
BE:将要被传输的数据内存物理末字节地址;
根据上述说明,我们可以定义通用TD为下面的数据类型:
typedef struct _TD {
volatile unsigned int Control;
volatile unsigned int CBP;
volatile unsigned int NextTD;
volatile unsigned int BE;
} TD, *P_TD;
由于通用TD必须是16字节地址对齐形式,因此我们必须用下面的形式来声明它的变量:
__align(16) TD td[4];
我们可以用下面的函数来创建一个通用TD:
__inline void CreateGenTd(
unsigned int GenTdAddr,//TD地址指针
unsigned int DataToggle,//T
unsigned int DelayInterrupt,//DI
unsigned int Direction,//DP
unsigned int BufRnding,//R
unsigned int CurBufPtr,//CBP
unsigned int NextTD,//NextTD
unsigned int BuffLen)//被传输的数据长度,由该变量可以得到BE
{
P_TD pTD = (P_TD) GenTdAddr;
pTD->Control = (DataToggle < 24) | (DelayInterrupt < 21)
| (Direction < 19) | (BufRnding < 18);
pTD->CBP = CurBufPtr;
pTD->NextTD = (NextTD & 0xFFFFFFF0);
pTD->BE = (BuffLen) ? CurBufPtr + BuffLen - 1 : CurBufPtr;
}
下面我们给出HCCA的数据结构,它的长度为256字节,包括128字节的HCCA中断表,2字节的HCCA帧数,2字节的HCCA便签(表示HC是否正在更新HCCA帧数),4字节的HCCA完成队列头指针,以及116字节的保留区。根据上述说明,我们可以定义HCCA为下面的数据类型:
typedef struct _HCCA {
volatile unsigned int HccaInterruptTable[32];
volatile unsigned short HccaFrameNumber;
volatile unsigned short HccaPad1;
volatile unsigned int HccaDoneHead;
volatile unsigned char reserved[116];
} HCCA, *P_HCCA;
由于HCCA必须是256字节地址对齐形式,因此我们必须用下面的形式来声明它的变量:
__align(256) HCCA hcca;
OHCI是基于寄存器层描述的USB主机控制器的规范,因此HC包含了一些片内可操作寄存器,这些寄存器同样可以被HCD所使用。下面我们就简单介绍OHCI中的寄存器。
HcRevision:HCI规范版本;
HcControl:HC的操作模式,CBSR——在非周期队列中,被服务的控制ED与批量ED之间的比例;CLE——下一帧控制队列处理使能;HCFS——USB主机控制器功能状态,包括复位、重新开始、操作和中止;
HcCommandStatus:HC接收来至HCD的命令,也可反映HC的当前状态,HCR——软件复位HC;CLF——确定是否有控制队列TD;
HcInterruptStatus:提供各种能够触发硬件中断事件的状态;
HcInterruptEnable:使能用于控制产生硬件中断事件的位;
HcInterruptDisable:无效用于控制产生硬件中断事件的位
HcHCCA:HCCA的物理地址;
HcPeriodCurrentED:当前同步或中断ED的物理地址;
HcControlHeadED:控制队列的第一个ED的物理地址;
HcControlCurrentED:当前控制对立ED的物理地址;
HcBulkHeadED:批量队列的第一个ED的物理地址;
HcBulkCurrentED:当前批量对立ED的物理地址;
HcDoneHead:被添加在完成队列中的最近一个TD的物理地址;
HcFmInterval:包含一个14位的FI——用于表示一帧之内所占用的比特时间,2个连续的SOFs,和一个15位PSMPS——用于表示在没有引发调度溢出下可发送或接收全速最大包大小,FI,PSMPS的推荐值为0x2EDF和0x2778。
HcFmRemaining:14位的倒计数器,以表示当前帧所剩时间;
HcFmNumber:16位计数器,以提供时序参考;
HcPeriodicStart:14位
OHCI(Open HCI)是目前使用比较广泛的三种USB主机控制器规范之一。USB体系结构是由四个主要部分组成:客户软件/USB驱动,主机控制器驱动(HCD),主机控制器(HC)和USB驱动。前两者由软件实现,后两者由硬件实现。而OHCI就是规范了主机控制器驱动和主机控制器之间的接口,以及它们的基本操作。在主机控制器驱动和主机控制器之间,有两个通信通道,第一个是应用位于HC的一套可操作寄存器,它们包括控制寄存器、状态寄存器和列表指针寄存器;另一个通道是应用称为主机控制器通信域(HCCA)的共享内存。
USB定义了四种数据传输类型:控制传输、批量传输、中断传输和同步传输。在OHCI规范中把数据传输类型分为两类:周期传输和非周期传输。同步传输和中断传输属于周期传输,控制传输和批量传输属于非周期传输。USB定义了每帧的周期为1.0毫秒,为了保证每一帧都能发生周期传输和非周期传输,一般地,OHCI把每一帧的带宽分为四个部分,首先是发送SOF,然后是非周期传输,紧接着是周期传输,如果周期传输完毕后,还有时间,则剩余的时间仍然留给非周期传输。
端点描述符(ED)和传输描述符(TD)是两个最基本的通信模块。ED包含了一个端点的信息,它被HC用来管理使用端点。ED的典型参数包括端点地址、传输速度、最大数据包大小,另外ED还提供了TD链表的停靠地(锚点)。TD是一个依赖于ED的内存缓存区,用于与端点之间进行数据传输。当HC存取一个ED,并且找到一个有效的TD地址时,则HC就完成了一个简单的与端点之间的传输任务,这个端点是由ED确定,而所存取的数据内存地址由TD指定。当所有的被TD所定义的数据传输完毕后,TD就从ED中解链出来,并链接到完成列表中。这个完成列表能够被HCD所处理,以提供一些完成信息。
ED的数据结构长度为16字节,它的数据域有:
FA:USB的功能地址;
EN:USB功能内的端点地址;
D:数据流的传输方向,是IN,OUT,还是有TD来决定传输方向;
S:速度,全速还是低速;
K:用于设置跳过当前ED;
F:链接于ED的TD的形式,是通用TD格式还是同步TD格式;
MPS:数据传输的最大字节大小;
TailP:TD列表的尾指针;
H:用于停止当前TD列表的处理;
C:数据翻转进位位;
HeadP:TD列表的头指针;
NextED:下一个要处理的ED指针。
根据上述说明,我们可以定义ED为下面的数据类型:
typedef struct _ED {
volatile unsigned int Control;
volatile unsigned int TailP;
volatile unsigned int HeadP;
volatile unsigned int NextEd;
} ED, *P_ED;
由于ED必须是16字节地址对齐形式,因此我们必须用下面的形式来声明它的变量:
__align(16) ED ed;
我们可以用下面的函数来创建一个ED:
__inline void CreateEd(
unsigned int EDAddr,//ED地址指针
unsigned int MaxPacket,//MPS
unsigned int TDFormat,//F
unsigned int Skip,//K
unsigned int Speed,//S
unsigned int Direction,//D
unsigned int EndPt,//EN
unsigned int FuncAddress,//FA
unsigned int TDQTailPntr,//TailP
unsigned int TDQHeadPntr,//HeadP
unsigned int ToggleCarry,//C
unsigned int NextED)//NextED
{
P_ED pED = (P_ED) EDAddr;
pED->Control = (MaxPacket < 16) | (TDFormat < 15) |(Skip < 14) | (Speed < 13)
| Direction < 11) | (EndPt < 7) | FuncAddress;
pED->TailP = (TDQTailPntr & 0xFFFFFFF0);
pED->HeadP = (TDQHeadPntr & 0xFFFFFFF0) | (ToggleCarry < 1);
pED->NextEd = (NextED & 0xFFFFFFF0);
}
TD共有两种类型:通用TD和同步TD。通用TD用于中断、控制和批量端点,同步TD用于同步传输。在这里,我们只给出通用TD的数据结构和定义。
通用TD的数据结构长度也是16字节,它的数据域有:
R:缓存凑整,用于设置是否需要最后一个数据包的长度与所定义的长度一致;
DP:方向,是IN,OUT,还是SETUP;
DI:延时中断;
T:数据翻转;
EC:传输错误计数;
CC:条件码,为上一次企图传输的状态;
CBP:将要被传输的数据内存物理地址;
NextTD:下一个TD;
BE:将要被传输的数据内存物理末字节地址;
根据上述说明,我们可以定义通用TD为下面的数据类型:
typedef struct _TD {
volatile unsigned int Control;
volatile unsigned int CBP;
volatile unsigned int NextTD;
volatile unsigned int BE;
} TD, *P_TD;
由于通用TD必须是16字节地址对齐形式,因此我们必须用下面的形式来声明它的变量:
__align(16) TD td[4];
我们可以用下面的函数来创建一个通用TD:
__inline void CreateGenTd(
unsigned int GenTdAddr,//TD地址指针
unsigned int DataToggle,//T
unsigned int DelayInterrupt,//DI
unsigned int Direction,//DP
unsigned int BufRnding,//R
unsigned int CurBufPtr,//CBP
unsigned int NextTD,//NextTD
unsigned int BuffLen)//被传输的数据长度,由该变量可以得到BE
{
P_TD pTD = (P_TD) GenTdAddr;
pTD->Control = (DataToggle < 24) | (DelayInterrupt < 21)
| (Direction < 19) | (BufRnding < 18);
pTD->CBP = CurBufPtr;
pTD->NextTD = (NextTD & 0xFFFFFFF0);
pTD->BE = (BuffLen) ? CurBufPtr + BuffLen - 1 : CurBufPtr;
}
下面我们给出HCCA的数据结构,它的长度为256字节,包括128字节的HCCA中断表,2字节的HCCA帧数,2字节的HCCA便签(表示HC是否正在更新HCCA帧数),4字节的HCCA完成队列头指针,以及116字节的保留区。根据上述说明,我们可以定义HCCA为下面的数据类型:
typedef struct _HCCA {
volatile unsigned int HccaInterruptTable[32];
volatile unsigned short HccaFrameNumber;
volatile unsigned short HccaPad1;
volatile unsigned int HccaDoneHead;
volatile unsigned char reserved[116];
} HCCA, *P_HCCA;
由于HCCA必须是256字节地址对齐形式,因此我们必须用下面的形式来声明它的变量:
__align(256) HCCA hcca;
OHCI是基于寄存器层描述的USB主机控制器的规范,因此HC包含了一些片内可操作寄存器,这些寄存器同样可以被HCD所使用。下面我们就简单介绍OHCI中的寄存器。
HcRevision:HCI规范版本;
HcControl:HC的操作模式,CBSR——在非周期队列中,被服务的控制ED与批量ED之间的比例;CLE——下一帧控制队列处理使能;HCFS——USB主机控制器功能状态,包括复位、重新开始、操作和中止;
HcCommandStatus:HC接收来至HCD的命令,也可反映HC的当前状态,HCR——软件复位HC;CLF——确定是否有控制队列TD;
HcInterruptStatus:提供各种能够触发硬件中断事件的状态;
HcInterruptEnable:使能用于控制产生硬件中断事件的位;
HcInterruptDisable:无效用于控制产生硬件中断事件的位
HcHCCA:HCCA的物理地址;
HcPeriodCurrentED:当前同步或中断ED的物理地址;
HcControlHeadED:控制队列的第一个ED的物理地址;
HcControlCurrentED:当前控制对立ED的物理地址;
HcBulkHeadED:批量队列的第一个ED的物理地址;
HcBulkCurrentED:当前批量对立ED的物理地址;
HcDoneHead:被添加在完成队列中的最近一个TD的物理地址;
HcFmInterval:包含一个14位的FI——用于表示一帧之内所占用的比特时间,2个连续的SOFs,和一个15位PSMPS——用于表示在没有引发调度溢出下可发送或接收全速最大包大小,FI,PSMPS的推荐值为0x2EDF和0x2778。
HcFmRemaining:14位的倒计数器,以表示当前帧所剩时间;
HcFmNumber:16位计数器,以提供时序参考;
HcPeriodicStart:14位
s3c2440USB主机控制 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)