指针的值继续处理,HC处理n个控制传输到1个批量传输,n值由HCD设置。
当传输描述符完成后,无论是成功还是由于发生错误,HC都将传输描述符移至完成队列。完成队列的入队实现是指把最近完成的传输描述符放在队列头部。完成队列通过HCCA从HC到HCD进行周期传输。
4 数据结构 4.1 概述
USB未对连接设备提供总线使用机制。因此,接口使用模式是由HC预言的,以及HCD软件为设备分配服务提供的职责,该职责是预言时设备所需要的。USB必然要在软件和端点(批量、控制、中断和同步)之间支持多种不同的通讯模式。在这些服务类型中总线的用法是多样的,使主机任务相当复杂。OpenHCI使用的方法是在端点中有两个层次的仲裁可供选择。第一层仲裁是在列表层,每个端点类型需要的服务在相应的列表类型中(例:同步端点在同步列表中)以及HC选择那个列表去执行。在列表中,端点们有同等的优先权,以此来保证某一特定类型的端点具有或多或少同等执行机会。
当端点执行完成后列表等级被定期修改。在每个帧内,有一段时间保留用作处理控制和批量列表的条目。这段时间在每帧的开头。HCD设置HcPeriodicStart在帧内的时间来限制这个时间间隔,在此之后周期传输(中断和同步)具有总线的优先使用权。处理周期列表时,针对当前帧的中断列表先于同步列表处理。当周期性列表处理完成后,控制和批量列表得以继续执行。
一个端点描述符(ED)包含端点相关信息,HC使用该信息来管理端点的访问。端点地址,传输速度,和最大数据包大小是ED中的典型参数。另外,ED也是传输描述符队列的锚点。一个TD连接到一个ED上,TD定义了一个与端点传输数据的内存缓冲区。当HC访问一个端点描述符然后发现一个有效的TD地址,HC完成ED指定的端点与TD指定的内存地址之间的单一传输。
当TD定义的所有数据都传输完成,TD从ED处断开,连接到完成队列中。然后HCD处理完成队列以及向发起传输请求的软件提供完成信息。
根据以上描述的处理机制,由HC处理的内存数据结构的信息在将这个章节中详细阐述。因为数据结构都被定义在系统内存中,所以HCD对所有数据结构拥有完全的读写权限。字段描述注明了结构体中被HC修改的字段。当包含那些字段的结构体在HC当前处理的队列或列表上时,系统软件不能修改会被HC改写的字段。没有使用硬件互锁来提供互斥。
4.2 端点描述符
端点描述符长度为16字节,内存结构体,16字节对齐。HC遍历包含TD链表的ED列表,HC执行标明的传输。
4.2.1 端点描述符格式
6
注:
1、字段‘—’未被HC使用,HCD可以任意使用
2、在HC处理队列之前,字段‘0’必须由HCD写入0。如果HC对该字段有写权限,总是写0。
4.2.2 端点描述字段定义
Table 4-1:端点描述符字段定义 名称 FA EN D HC 访问权 R R R 描述 FunctionAddress 包含该ED控制端点的USB功能地址 EndpointNumber 端点地址 Direction 该2位字段指示了数据流方向(IN or OUT)。如果未定义IN或OUT,方向由TD结构体字段PID决定。该字段编码如下 S K R R Speed 表示端点速率:全速(S=0)或低速(S=1) sKip ==1时,HC直接跳至链表上的下个ED,不再防伪TD队列或者向这个端点发送任何USB令牌。 Format 这位表示了连接到ED上的TD的格式。如果是控制、批量、或者中断端点,F=0,标志着使用通用TD格式。如果是同步端点,F=1,标志着使用同步TD格式。 MaximumPacketSize 该端点所能接收、发送的单包最大长度(字节)。 TDQueueTailPointer 如果TailP等于HeadP,意味着列表不包含任何TD供HC处理。如果不相等,表示列表中含有TD需要处理。 Halted 该位由HC设置,标志着该端点上处理的TD队列被停止,通常是由于处理TD是发生错误。 toggleCarry 7
F R MPS TailP R R H R/W C
R/W 数据乒乓进位。当TD退休时,该位被置成包含来自退休TD的最后一个数据乒乓值(LSB of data Toggle字段)。 同步端点不使用该字段。 HeadP NextED R/W R TDQueueHeadPointer 指向该端点下一个待处理的TD。 NextED 如果非零,这个入口指向列表的下个ED。 4.2.3 端点描述符描述
ED连接成列表,由HC来处理。NextED字段非零时,意味着有下一个ED连接到本ED上。
当HC访问ED时,查看sKip和Halted字段是否进行更进一步处理。如果其中一个被设置,HC直接跳到链表上的下一个ED。如果两者都位设置,然后HC比较HeadP和TailP字段,如果不相等,根据HeadP指向的TD定义了一个缓冲区,HC将会从该缓冲区传入或传出一个数据包。
这个连接约定假设HCD总是添加至TD队列尾部。将新TD链接至TailP指向的地址,然后跟新TailP指向新加入的TD。
当一个TD处理完成后,HC通过将该TD从ED链表中断开并链接至已处理队列中使之“退休”。当一个TD断开链接时,将传输描述符字段NextTD赋值给端点描述符的HeadP字段。
HCD通过设置sKip位来跳过HC对该端点的处理。当HCD必须修改HeadP值时,以及从列表中删除ED被禁止时,设置sKip位通常是有需要的。
当HC在处理TD时发生错误时设置Halted位。当错误TD移到已完成队列时,HC更新HeadP值以及设置Halted位,让HC跳过ED处理直到Halted位被清除。当错误状态修正后HCD清除Halted位,端点的传输得以继续。HCD不应该去写HeadP/toggleCarry/Halted除非Halted和sKip被设置,或者ED从链表中移除。
当ED的D字段等与10b(IN),且HeadP不等于TailP,HC会向指定端点发出IN令牌。这个表示存在一个数据缓冲区,也表示端点的数据输入会与HC访问内存区中的TD同时发生。
因为ED必须16字节对齐,HC只使用了DWORD3的高28位来指向下个ED。TailP和HeadP指向TD,TD可以是16字节或32字节对齐。HC只使用DWORD1和DWORD2的高28位来指向一个16字节对齐的TD(F=0)。如果HeadP和TailP指向32字节对齐的TD(F=1),那么这些DWORD的第4位必须为0。
4.3 传输描述符
HC所使用的数据结构TD保存在系统内存中,定义了一个与端点进行数据传输的数据缓冲区。TD有两种类型:普通型和同步型。普通型TD适用于中断、控制和批量端点,同步型TD唯一适用于处理同步传输要求。两种TD类型都被系统支持,因为同步传输的特性并不适用于标准DMA缓冲格式,且缓冲区需要分包操作,因为同步传输比普通传输类型有更多限制。
普通型TD和同步型TD都提供了一种指定缓冲区的方法,长度从0-8192字节。另外,TD描述
8
的数据缓冲区能横跨两个未连接的物理页。尽管TD的离散力是有限的,但是它也消除了大部分与连续物理页强制性相关的问题,包括不必要的数据移动。
TDs连接成队列依附在EDs上。ED提供TD与端点进行数据传输的端点地址。HCD将TD加入到队列中,HC将TD从队列中移除。当HC从队列中移除一个TD后,将其连接到已完成队列。当TD从ED移除且连接至已完成队列,我们称之为“退休”。TD可以退休是因为正常完成或者发生错误。当TD退休时,一个状态码写入TD,该状态码帮助HCD确定TD退休的原因。
处理TD的细节与TD类型相关,在章节4.3.1到4.3.3.1中讨论。
4.3.1 普通型传输描述符
控制、批量和中断传输使用相同格式的传输描述符。这个普通型TD长16字节,主机内存结构体必须16字节对齐。
4.3.1.1 普通型传输描述符格式
注:
在DWORD0,是HC读写字段。字中未使用部分(表示为—)不能被HC写,后者读出来再原样写回。TD中可被HC访问的部分,HCD都不应该修改。
4.3.1.2 普通型传输描述符字段定义 Table 4-2: 普通TD的字段定义 名称 R HC访问权 R 描述 bufferRounding 如果=0,从端点传输至TD的最后一个数据包必须完全填充完已定义数据缓冲区。如果=1,最后一个数据包或许小于已定义数据缓冲区,而且TD上不产生错误状态。 Direction/PID 这2位表示数据流方向,PID被令牌使用。这个字段只和HC有关,如果ED的D字段设置成00b或者11b(表示PID的决定权交给TD)。 DP R DI R DelayInterrupt 这个字段包含这个TD的中断延时数。当TD完成后,HC可能会等待DelayInterrupt个帧之后才产生中断。如果=11b,TD完成后不产生中断。 9
T R/W DataToggle 这个2位字段用来产生/比较数据PID值(DATA0或者DATA1)。每次成功发送与接收一个数据包后跟新该值。当数据乒乓值从ED的toggleCarry字段获得时,那么这个字段的MSB=0;当数据乒乓值取自这个字段的LSB时,该字段的MSB=1。 ErrorCount 每次传输错误时,该值递增。当=2且有错误发生时,ConditionCode字段记录错误类型,然后放置该TD到已完成队列。当传输成功完成,该字段复位到0。 ConditionCode 该字段包含最后一次传输的状态。(参看章节0) CurrentBufferPointer 包含下个存储单元的物理地址,用来跟端点进行传输。0值表示0长度数据包或所有字节都已经传输完成。 NextTD 该入口指向连接到这个端点上的TD链表中的下个TD。 BufferEnd 包含这个TD缓冲区中最后一个字节物理地址。 EC R/W CC CBP R/W R/W NextTD R/W BE R
4.3.1.3 普通型传输描述符描述 4.3.1.3.1 缓冲区地址决策
普通型TD中的CurrentBufferPointer值指向数据缓冲区的地址,用来和端点传输数据包,端点地址由ED指定。当传输毫无错误的完成,HC用传输的字节数来更新该字段。
如果在数据传输中,包含在HC使用的CBP的工作拷贝中的缓冲区地址超出了4k边界,BufferEnd的高20位复制到CBP的工作值中,引起下个缓冲区地址成为相同4K页的0字节,该页包含缓冲区的最后一个字节。
4.3.1.3.2 包大小
当HC向端点写时(OUT和SETUP),发送到端点的数据包大小总是取MaximumPacketSize和缓冲区剩余数据小者。当HC从端点读时(IN),数据包大小决定于端点。
4.3.1.3.3 状态码
每次尝试传输后,普通TD的ConditionCode字段会被更新,不管成功与否。如果传输成功,该字段设置成NoError,否则设置成错误类型。
4.3.1.3.4 序列位
USB协议使用数据PID序列来保证数据包按正确顺序接收。序列机制要求数据发送器不停的使用相同数据PID(DATA0或DATA1)发送相同数据知道它决定数据包被正确接收和认可。发送数据包之后发送器收到一个ACK握手意味着数据被接收和认可。为了保证数据包不丢失,HC和端点无论开始与停止,都应保持乒乓同步。
端点初始化首先建立数据乒乓同步,与端点传输的第一个数据包使用DATA0。每个成功传输的数据包之后,数据乒乓更改。
10