2010/11/20
Host控制器之EHCI
一 USB的数据流模型
USB设备在工作时,从用户的角度或者说从应用的角度来看,数据流的两边分别是host和slave,或者叫做USB主机和USB设备。
但是在实际的开发过程中,却远比这要复杂,USB系统被分出若干层,不同的层负责不同的性质的工作。
比如以U盘这个mass storage类来说,主机需要通过控制器来发送接收数据,系统软件需要实现USB协议,在linux代码中叫做USB core,负责实现USB子系统的工作,这一层与
具体是什么类没有关系。客户软件并不是我们通常意义上说的比如qq这种应用软件,而是驱动软件,USB core之上我们就需要实现mass storage层的代码,这就是客户软件。
这3层分别是负责数据的基本发送、接收,USB协议层的实现(子系统的实现),驱动层的实现。
二 Host控制器(controller)
Usb的拓扑结构决定了控制器是老大,没有控制器的要求设备永远不能主动发数据。等!所以host控制器在USB的世界里扮演着重要的角色,不羡慕台前的风光,一直默默无闻的在幕后耕耘。那么在前一章中,比如说host发送tup包获取设备描述符,怎么发出去的?这个过程包含很多信息的,如何在D+,D-这两根线上传过去的、又传过来的。
这一切的工作都是控制器给我们干的。USB Host控制器的规范有很多种:这里只
介绍混得不错的EHCI和OHCI,这个EHCI主要针对高速的USB设备。如果要操作全速和低速可以考虑OHCI。
什么是USB controller?关于奋斗的作文 USB 设备和主机的接口就是host controller,一个主机可以支持多个host controller,比如分别属于不同厂商的。那么USB host controller 本身是做什么的?controller,控制器,顾名思义,用于控制,控制什么,控制所有的重庆哪里好耍usb 设备的通信。Cpu把要做的事情分配给控制器,然后自己想干什么就干什么去,控制器替他去完成剩下的事情,事情办完了再通知cpu。否则让cpu 去盯着每一个设备做每一件事情,那是不现实的
控制器的主要工作是什么?把数扔出去,把数拿回来。绝对不应该偷偷加工数据。
我们driver的工作是什么?让控制器工作起来,发挥它的潜力。
让控制器发数据、收数据,how to make it work?
比如:你要发一封快递到深圳!你会选择EMS。---------〉EHCI
发一封信件到西城!你会选择同城速递。----------〉OHCI
然后你会找前台的小姑娘要一份EMS,然后认真地填写,把东西塞进去。放在前台。等快递人员来取。
我们要做的就是准备好东西、放在指定的地方。按照快递公司的要求办事。
Uhost控制器也是一样,主要就是下面几步:
1 按照控制器的要求组织结构体
2 将结构体在合适的时间、放在合适的地方
3 trigger
4 等待完成信号
Uhost控制器driver开发过程就是上面这几步。这就是我们努力的方向,沿着这条线走,我们就能到达乐土。
三 EHCI规范
3.1 拜访结构体鲁迅先生的一生
到一个新环境、新山头,首先要拜访的就是几个占山为王、雄踞一方的结构体!EHCI
规范中这几个结构体可是重中之重。下面登场的就是几位互教法王:QH、qTD、iTD、siTD、FSTN.
1) QH (queue header )
翻译出来觉得不好听,我们就叫qh吧。Qh结构体包含着这次传输的基本信息。这次传
输是针对谁传输的?我们前面提过。端点。切记,传输是针对某个地址设备的端点进行的。想到这我觉得你应该想到这个结构体中,至少要有一个设备地址以及端点号。到这还想不明白,就不用往下看了,闭上眼睛想想前面讲的内容,设想一下如果是你,你会怎么设计这个结构体。
从qh上面几行可以看出,一个qh对应到了一个usb device的某个端点上,也就是一个qh对应一个设备的一个端点。Current qtd是当前正要执行的qTD(qTD是一个传输单元transzaction),这个并不是软件填写的,而是控制器从tranr Overlay中的next qTD中cop
y过去的,所以首次运行一个qh时需要把第一个要执行的qTD挂在qh的tranr Overlay的next下,控制器会首先从这里查看是否有满足条件的qTD传输,如果有copy到current中,执行,当执行完毕后将刚执行完毕的qTD的next以及刚才qTD的执行结果、状态回写到tranr Overlay区域,这时控制器查看刚回写到tranr Overlay中的next qTD是否满足条件,如果满足走刚才的流程,不满足执行条件,不再执行。判断是否满足执行条件肯定发生在上一个传输完成之后。
对传输成功与否有至关重要的一个参数data toggle,第一次传输该位肯定是0,之后对于该端点的传输中,qh所采用的toggle就需要从tranr Overlay中取得。
这个结构体还包含一些信息:是否为控制端点、端点最大包长度、设备地址、端点号、hub地址、hub断口号、高速还是全速设备等等。
形容美的四字词语SECOND:讨论中涉及到dtc的用法,下面是文档中的信息
当该位为0时,控制器会保留DT信息在qh中,如果该位为1,每次的DT都从qTD中取。我们程序中使用时,是采用的第二种方式。
2) qTD
挂接在QH下的基本传输单元。
从这个结构体和上面的qh都可以看出,注意看第一个WORD,地址都需要32字节对齐。因为低几位是有用的。
其中的参数:下一个qTD的地址,data toggle,要传输的数据长度,这个qTD传输完成后是否发生中断(ioc),当前的page,PID,以及状态(active ,错误信息等)。数据的buffer。
每个buffer最多是4k数据,5个buffer共计 20k。
C_Page ,当前buffer pointer的index 0~4。Current offt 是page0内的字节偏移。这个只有page0有。
QH:queue head 队列首。 qTD:队列传输元素,queue element transfer descriptor。
每一个qh横向指向下一个qh,纵向挂接qTD元素。qTD是不能独立存在的,依附在QH下。
寿司的材料
3) iTD
一月怎么读专门用在iso传输,等时同步传输,控制器眼中是周期传输,类似与中断传输。
这个是专门给iso传输用的,端点号、设备地址,为啥没有hub的信息?对比一下前面的QH,是有hub信息及port端口号的。如果你有兴趣可以看一下EHCI文档中QH这个结构体详细介绍Page48,当然仅看这个不会让你理解的更深,再看一下split transzaction (Page89).
如果你没有时间,下面是我的理解:在EHCI下,当接入的是高速设备时,hub是透明的。既然是透明的,就可以将数据完全透过,不需要hub的加工,要hub还有用么?所以在操作高速设备时,结构体中hub地址是不需要关注的。只有当使用低速/全速设备接入hub时,才会用到hub地址及端口号。这也说明上面这个结构体是针对高速iso设备的。
看下面这句实现程序:
g_FrameListBuffer[0]= (UINT32)usb_itd | EHCI_FLLP_ITD & (~EHCI_FLLP_T);
周期性的都放在frame list中,同时指名类型,并使能T位。中断传输使用的其实和bulk,control一样,通用的qTD和QH,只不过是将qh放在frame list中,而iso是不需要qh的,直接将专用的iTD放在frame list中。(这属于传输机制的范围,下面介绍)
Iso传输需要的是数据的连续性,可以设置在1个micro frame中进行mult个传输,所谓的高带宽。Iso传输不管传输是否正确都会发生传输完成中断的。
注意:mult 这个参数,当in数据时,这个代表在一个微桢内in几次数据,必须要设置,如果不设置默认为0,是非法的,执行时会发生usb err。返回的状态区status会发生传输错误标记。Out时没有这问题,因为out发送的数据长度依靠的是transaction length.
赞的图片
每个iTD可以放置8个iso传输。占掉一个ms的所有时间。每个iso传输中可以通过设置mult来控制iso传输一个micro frame进行几次传输,高带宽的意思。
物理的page是可以不连续的。3*1024*8=24k 。提供7个page来支持8个iso 传输,为什么设计时不用8个,不清楚。
3.2 周期、异步传输机制
Ehci控制器眼中的传输首先分成两种:周期性传输和异步传输。Ehci有两个寄存器PeriodicListBa和AsyncListAddr,这两个寄存器就是放置要执行的第一个iTD和QH结构体的地址。
1)周期传输
我们先引入一个periodic Frame list内存区,这个frame list放置的就是要周期传输的QH的地址,frame list的size可设置,我们以1024为例。也就是说frame list中放置的都是QH的地址,这个frame list的首地址放在了PeriodicListBa寄存器里,控制器可以看到这个寄存器,也就能够取到frame list 中的各个qh了。Frame list中放置着若干个qh,每个qh并不靠next联系,而是靠时间窗口来决定执行的,每个qh又通过next 横向挂接qh,每个qh纵向又挂接了若干个qTD元素。这有点3维的感觉,不过目前我们还是别想这么复杂。
刚才我们一直说QH,只是为了刚才表述方便,其实在周期传输中,frame list中放置的不一定是QH,还有几种情况:
也因此framelist中放置的待传输的结构地址需要32字节对齐,留出5位用作他用。
当T=1时,该地址将不被控制器采用进行传输。
2)异步传输
异步传输的理解思路和周期一样了,只不过这里没有frame list的概念,直接将要传输
的第一个QH的地址放在AsyncListAddr这个寄存器就OK了,至于这个QH后面再挂
几个qh,每个qh下又挂几个qTD就是后话了。
读一下下面的英文,还是很有感觉的,虽然有些单词不知道啥意思。
周期传输和异步传输
• One Periodic Schedule
– Maintains all Isochronous and Interrupt
• One Asynchronous Schedule
– Maintains all Bulk and Control
• Each explicitly enabled via System software
• Execution Rules
– Repeat each micro-frame:
• Periodic schedule first, then