打算用三篇文章总结一下玩过的用C8051F320和NandFlash 实现U盘:
1、设备枚举
2、文件系统
3、NandFlash驱动
最后上传实现U盘的原理图和源代码
首先总结一下USB传输的基本内容.
一USB传输的要件
USB主控制器: USB主机负责管理USB通讯
USB设备: 符合USB规范可以被USB主机访问的设备,设备有低速,全速和高速之分.USB低速设备在USB的D-线上有1.5Kohm的上拉电阻,全速或高速设备在D+线上有上拉电阻. 设备插入USB接口后,如果D-线被拉高,主机认为是低速设备,如果D+线被拉高主机会认为设备是全速设备. 主机人出全速设备后会发送交替的K, J脉冲,如果设备没响应,主机就认定为全速设备,否则认定为高速设备.
端点: USB所有的传输都是从一个设备端点发出或者把数据传送到一个端点. 端点的物理表现为一块存储区域,通常会是一块FIFO Memory.根据系统的要求可以将这块FIFO配置为单缓冲或者双缓冲方式,双缓冲的方式允许两个数据包的同时存在.一个全速的USB设备可以有31个端点, 端点0无论在任何情况下都在为控制端点, 控制端点是双向的负责建立和配置总线, 端点1到端点30, 是15对, 有1IN, 1OUT, 2IN, 2OUT 等组成. 端点的方向是针对主机而言的, 比如1IN 是指数据由设备流向主机, 1OUT 是指数据由主机发给设备.下面的表格是C8051F320 的所有端点的描述.
如图
管道: 管道是设备端点和USB主机控制器的软件之间的连接.主机控制器会轮询是否有新的设备连接到总线上,如果有则会建立一个管道,管道建立后,主机可以通过端点0来获知设备的能力.如果是同步传输或者中断传数, 主机在建立管道前会计算是否有足够的带宽来保证同步传输或这中断传输的最大延时时间.试想如果没有足够的带宽,即使主机为你建立了连接, 听音乐不流畅, 点了N多次鼠标系统也没有反应也是很痛苦的.
事务: USB协议将事务定义成,将一个服务传送到一个端点.服务可以是主机把数据发送给设备,也可以是设备响应主机的要求将数传送给主机.
传输: 一个或多个事务构成一个USB传输.对于控制传输来说, 它永远都有多个事务,因为控制传输分设置, 数据,联络三个阶段.
祯/微祯: 对于低速或全速的设备USB主机将传输分割成1mS的祯, 对于高速的设备主机又将一个祯分割成8个125uS的微祯.
相位: USB事务中的一个组成部分. 一个事物可以有三个相位: 令牌相位, 数据相位, 联络相位. 令牌相位可以指示当前的传输是端点0的控制传输还是其他端点的输入或输出传输. 数据相位是真正要传输的数据. 联络相位总线上的握手信号. 例如主机发送一个输出事务,主机首先发送输出事务令牌,然后发送数据给设备,设备接受的数据后发送ACK给主机,如果此时设备还没准备好,设备发NAK给主机.
二USB传输类型
USB支持四种传输类型: 控制传输,中断传输, 批量传输, 实时传输. 但是所有的USB设备都必须支持控制传输, 因为主机需要通过控制传输来了解设备的能力.不同的传输类型和不同的设备速度能力,支持传输的最大信息包的大小也不同. 比如对于USB 全速的设备来说, 全速设备上的控制传输和批量传输的信息包最大可以是64字节,在一个祯内的19个64字节的批量传输可以达到 19*64*1000*8 = 9.728Mb/S, 而USB 1.1定义的总带宽为12Mb/S, 这样就有大约19%左右的带宽可以用来做其他类型的传输,如中断传输。
控制传输是最为复杂的传输类型,它包含三个阶段:设置阶段,数据阶段,联络阶段。数据阶段是选择性的,可有可无。每个阶段都包含一个或多个事务,故控制传输永远有多个事务。在数据阶段,OUT事务是由主机发出输出设置令牌,随后主机发送数据到设备,如果设备正确接收数据发送ACK给主机,如果尚未准备好发送NAK给主机,如果不支持此类传输则发送STALL。状态阶段包含一个输入或输出事务是对上一个传输阶段是否成功的确认。(不是对一个事物的确认,事务是靠联络信息包确认的),状态阶段的数据信息包的来源是上个阶段的数据的接收者,主机发送零长度的数据表示上个阶段的控制读取传输成功,设备发送零长度的数据包表示上个阶段的控制写入传输成功。对大多数传输而言发送零长度的数据包表传输成功,要求已经执行,例外的是Set_Address 要求,必须等到状态阶段完成后才会执行。
传输模型如下图,H代表主机,D代表设备。
H to D H to D D to H
输出设置——〉 数据 ——〉ACK/NAK/STALL
数据阶段的控制写入传输
H to D D to H H to D
输入设置——〉 数据 ——〉 ACK
/|\ D to H
|______NAK/STALL
数据阶段的控制读取传输
H to D D to H H to D
输出设置——〉零长度数据 ——〉ACK/NAK/STALL
/|\ D to H
|______NAK/STALL
状态阶段的控制写入传输
H to D H to D D to H
输出设置——〉 数据 ——〉ACK/NAK/STALL
状态阶段的控制读取传输
三枚举过程
枚举的过程就是主机识别设备能力的过程,主机通过发送一些USB标准要求来获得设备能力,设备在接收到主机的要求后,分析要求,返回相应的描述符给主机,这些描述符描述了设备的能力。枚举的过程,设备会经历下面的四个状态:开机(powered),默认(default)地址(address),配置(configured)。
如下图所示设备开始时处于连接状态,此时集线器还没有给设备提供电源,集线器提供电源后设备处在开机状态,进入powered , default, address ,configured 四种状态之以后如果3秒内无动作,设备进入挂起状态suspend state. 在开机状态下集线器重置设备后识别设备是全速或高速设备然后进入默认状态, 在默认状态下,设备使用默认地址0 和主机通讯, 主机会要求64个字节,在状态阶段完成后,集线器会重置USB设备. 然后主机在Sset address 要求中送出一个随机的地址给设备, 设备必须在读取地址后返回一个确认信号,然后存储新的地址,设备进入地址状态,以后所有的传输用新的地址.在地址状态下, 主机会先要求设备的设备描述符, 然后要求配置描述符的前9个字节,接下来用获得的配置描述符的总长度来要求完整的配置描述符.然后主机会选择一个设备驱动程序加载, 如果成功我的电脑的设备管理里会出现Mass Storage Device,最后主机会发出Set Configuration 和 Set Interface 要求, 设备响应后, 设备进入配置状态,以后的传输不再使用端点0了.
下面是用Bushound工具取得的数据,分析枚举的过程如下:
Device Phase Data Description Cmd. Phase.Ofs(rep)
------ ----- ------------------------ ---------------- -----------------------------------------------------
21.0 CTL 80 06 00 01 00 00 12 00 GET DESCRIPTOR 1.1.0
Get_Descriptor 的数据结构: LSB[7:0] MSB[15:8]
———————|——————|————————|——————|——————|—————|
要求类型 | 要求码 | 描述符偏移量 | 描述符类型 | 语言ID | 长度 |
———————|——————|————————|——————|——————|—————|
此控制传输的令牌阶段中的数据信息包里包含了请求得到配置描述符的信息,其中:01表示请求的是配置描述符,请求的数据长度的0X12,既是18个字节。
21.0 DI 12 01 00 02 00 00 00 40 .......@ 1.2.0
71 04 46 11 01 00 01 03 q.F..... 1.2.8
04 01 .. 1.2.16
在控制传输的数据阶段的数据信息包里包含了请求的18个字节
设备描述符中的这18个字节内容是:
bLength 0x12 配置描述符的长度
bDescriptorType 0x01 描述符类型
bcdUSB 0x0200 USB协议版本号
bDeviceClass 0x00 设备类别
bDeviceSubClass 0x00 子类别
bDeviceProtocal 0x00 协议码
bMaxPacketSize 0x40 控制端点最大信息包长度为64
VID 0x0471
PID 0x1146
bcdDevice 0x0001 设备版本号
iManufacture 0x01 Optional
iProduct 0x03 Optional
iSerialNumber 0x04 Opt
bNumConfigurations 0x01 支持的配置数
21.0 CTL 80 06 00 02 00 00 09 00 GET DESCRIPTOR 2.1.0
21.0 DI 09 02 20 00 01 01 00 c0 .. ..... 2.2.0
fa . 2.2.8
要求配置描述符;第一次要求时只要求9个字节,这9个字节仅仅是Config_Descriptor
自身的9个字段。
Config_Descriptor:
bLength 0x09 描述符长度
bDescriptorType 0X02 类型
wTotalLength 0X0020 设备回传得字节数(Config + Interface + EndPoint)
bNumInterfaces 0x01 接口数目
bConfigValue 0x01 Set_Config or Get_config 要求的值,若为0,设备进入无配置状态
iConfig 0X00 OPT
bmAttributes 0XC0 设备是自身电源BIT6 为 1 ,支持远 程唤醒BIT5为 1,BIT7 must be 1
MaxPower 0XFA 总线所需电流, I = 2 * 0XFA mA = 500mA
21.0 CTL 80 06 00 02 00 00 20 00 GET DESCRIPTOR 3.1.0
21.0 DI 09 02 20 00 01 01 00 c0 . . ..... 3.2.0
fa 09 04 00 00 02 08 06 ........ 3.2.8
50 00 07 05 81 02 00 02 P ....... 3.2.16
00 07 05 01 02 00 02 00 ........ 3.2.24
设备回传了所有的Config_Descriptor, Interface_Descripotr, EndPoint_Descriptor
前9个字节为配置描述符,接下来9个字节是接口描述符,最后14个字节是端点描述符
解析下输出端点 1
OutPut Endpoint 1
bLength 0x07 端点描述符长度
bDescriptorType 0x05 类型
bEndpointAddr 0x01 BIT7控制方向1 为IN,0 为 OUTBIT3—BIT0 FOR ADDR
bmattribute 0x02 0—控制,1—实时,2—批量,3—中断
wMaxPacketSize 0x0200 USB20 批量传输必须以512字节传
bInterval 0x00 全速的批量去控制传输可忽略
21.0 CTL 80 06 00 03 00 00 02 00 GET DESCRIPTOR 4.1.0
21.0 DI 04 03 .. 4.2.0
HOST 要求Strings_Descriptor, 要求2 个字节
21.0 CTL 80 06 00 03 00 00 04 00 GET DESCRIPTOR 5.1.0
21.0 DI 04 03 09 04 .... 5.2.0
HOST 要求字符传描述符,要求4个字节,0904是语言ID
21.0 CTL 80 06 04 03 09 04 02 00 GET DESCRIPTOR 6.1.0
21.0 DI 22 03 ". 6.2.0
字符串描述符
21.0 CTL 80 06 04 03 09 04 22 00 GET DESCRIPTOR 7.1.0
21.0 DI 22 03 30 00 31 00 32 00 ".0.1.2. 7.2.0
33 00 34 00 35 00 36 00 3.4.5.6. 7.2.8
37 00 38 00 39 00 41 00 7.8.9.A. 7.2.16
42 00 43 00 44 00 45 00 B.C.D.E. 7.2.24
字符串描述符;0,1,2,3 to E, F
21.0 CTL 00 09 01 00 00 00 00 00 SET CONFIG 8.1.0
设置配置Set_Config 要求
21.0 CTL 01 0b 00 00 00 00 00 00 SET INTERFACE 9.1.0
设置接口 Set_Interface 要求
文章评论(0条评论)
登录后参与讨论