USB枚举代码添加

Mass Storage类规范定义了两个请求:Get_Max_LUN和Mass Storage Reset,所有的Mass Storage类设备都必须支持这两个请求。

处理GET MAX LUN命令时,我们返回实际的逻辑单元(LUN:0~15)个数即可,由于我们的Mass Storage驱动仅支持一个存储设备,所以直接返回0即可。其实该命令也可以不应答,这时PC会重试三次,不过重试过程比较缓慢,用户体验体验很不好。

对于Mass Storage Reset命令,由于我们目前没有任何工作可做,所以直接返回空数据即可。

相关代码如下:

if(len>0)

{

USB_SETUP_PACKET* Setup= (USB_SETUP_PACKET*)State->Data;

//GET MAX LUN

if(Setup->bmRequestType == 0xA1 && Setup->bRequest == 0xFE)

{

*(volatile UINT8 *)((UINT32)&usb.FIFO[0]) = 0;

usb.Indexed.PERI_CSR0=DM335_USB_Indexed::PERI_CSR0_TXPKTRDY | DM335_USB_Indexed::PERI_CSR0_DATAEND;

return;

}

//Mass Storage Reset

if(Setup->bmRequestType == 0x21 && Setup->bRequest == 0xFF)

{

usb.Indexed.PERI_CSR0=DM335_USB_Indexed::PERI_CSR0_TXPKTRDY | DM335_USB_Indexed::PERI_CSR0_DATAEND;

return;

}

}

该部分代码直接添加在"DeviceCode"Targets"Native"DM335"DeviceCode"DM335_USB.cpp中

的DM335_USB_Driver::EP0_ISR()函数即可。

5. Mass Storage功能实现

其实只要实现了标准的USB驱动接口,在此基础上实现Mass Storage功能应该算不太难,这里不打算详细介绍Mass Storage功能的方方面面,这会涉及到太多的相关知识,我这里只是从我们实际的这部分功能出发,简明扼要地介绍一下Mass Storage功能实现的原理。

这里需要特别指出的是,Bulk-only transport协议,仅需要USB驱动提供两个端点即可,一个是端点1(输入端点),一个是端点2(输出端点),两者的类型都为BULK模式。很幸运的是

我们的.Net Micro Framework的标准驱动和这个要求是一致的。

5.1 命令/数据/状态

Mass Storage设备枚举成功后,PC会通过端点2向Mass Storage设备发送各种命令,

Mass Storage设备根据相应的命令,进行不同的应答。

其命令、数据、状态相关的流程图如下:

PC机发送的数据必须符合CBW格式(31byte,小端模式),而Mass Storage设备的应答,其格式必须符合CSW格式(13byte,小端模式)。至于中间过程传输的数据,根据不同的命令,格式也有不同地要求。

5.1.1 CBW命令块(Command Block Wrapper)

表3 CBW命令块

dCBWSignature:常数0x43425355,标识为CBW命令块。

dCBWTag: 由主机发送的CBW标签。设备应该在相关的CSW的dCSWTag以相同的值应

答主机。

dCBWDataTransferLength: 在本命令执行期间,主机期望通过Bulk-In或Bulk-Out端点传输的

数据长度。如果为0,则表示这之间没有数据传输。

bmCBWFlags: 定义如下(Bit7 Direction(dCBWDataTransferLength为0时,该值无意义) :

0= DataOut,数据从主机到设备

1= DataIn, 数据从设备到主机

Bit6 Obsolete 0

Bits 5..0 Reserved 0

bCBWLUN: 表示正在发送命令字的设备的逻辑单元号(LUN)。对于支持多个LUN的设备,

主机设置相对应的LUN值。否则,该值为0。

bCBWCBLength: CBWCB的有效字节长度。有效值是在1到16之间。

CBWCB: 被设备解析执行的命令块。

注:该部分是重中之重,通过对这部分的命令的解析,实现实际的Mass Storage功能。

5.1.2 CSW状态块(Command Status Wrapper)

表4 CSW状态块

dCSWSignature: 常数0x53425355,标识为CSW状态块

dCSWTag: 取相对应的CBW的dCBWTag值。

dCSWDataResidue:实际传输的数据个数和期望要传输的数据个数之差。

bCSWStatus:命令执行情况,相关值如下:

5.2 SCSI 传输协议(或UFI传输协议)

很多资料上都是把子类协议设置为0x06,也就是SCSI 传输协议,实际测试表明设置为0x04

(也就是UFI传输协议)也是可以的。实际看说明书,发现二者很多命令都是相同的,所以这

两种协议对我们来说都适合,不过我这里建议最好看UFI传输协议手册,它要比SCSI手册

简明地多。

无论是SCSI 传输协议还是UFI传输协议,其命令都是非常多的,不过对于我们的应用,

我们仅需实现如下几条指令即可。

5.2.1 INQUIRY命令

该命令询问Mass Storage设备的基本信息,如生产厂家,产品名称,产品版本等等。

详细参数说明请参见《UFI Command Specification》,比较有意思的是Peripheral Device Type

参数,如果设置为0,则表示这是一个可移动的存储设备(类似U盘),而设置为0x1F,

则表示是一个非移动设备(类似硬盘,图标在硬盘区出现)。

5.2.2 READ_FORMAT_CAPACITIES命令

该命令获取Mass Storage设备存储大小,Block长度(一般为一个扇区大小,默认为512)

等信息。

该表仅包括部分反馈信息,详细说明请参见《UFI Command Specification》。需要注意的是,

无论是块个数,还是块长度,其数据格式为大端模式。

5.2.3 READ_CAPACITY命令

该命令返回最后一个块的索引和块的长度,其实该命令可以看着是

READ_FORMAT_CAPACITIES命令的一个子集。

注意数据格式为大端模式。

详细说明请参见《UFI Command Specification》。

5.2.4 READ_10命令

该命令由PC端发出,请求Mass Storage设备发送指定扇区索引、扇区个数的数据。

这是PC机请求的命令,Mass Storage设备直接返回相应的数据即可。

详细说明请参见《UFI Command Specification》。

5.2.5 WRITE_10命令

该命令由PC端发出,CBW命令块后面紧跟的就是相应扇区的数据。

Mass Storage设备获取数据后,写到相应扇区即可。

这里需要强调的是,由于要接收的数据量有可能很大,该部分功能又是在时钟中断中实现,

所以不要试图一次获取所有的扇区数据,否则在实际的TinyCLR环境中运行是不正常的。

其实在READ_10中也存在类似问题,不过实际测试,直接发送所有数据,并没有什么问题,

这从侧面反映PC机的接收数据能力,远远大于MF设备。

5.2.6 REQUEST_SENSE命令

PC机每发送一个命令后,都会检测设备返回的CSW的状态值是否为0(Good Status),

如果不为0,则PC机马上发送REQUEST_SENSE命令,询问出错的进一步信息。

我们这里Sense Key的值直接设为0x05(ILLEGAL REQUEST)即可,主要原因是PC端会

询问各种命令,由于我们没有实现,返回的CSW状态都非Good Status而已。

详细说明请参见《UFI Command Specification》。

5.2.7 TEST_UNIT_READY命令

在没有其它命令进行操作时,PC端会每隔一定时间,就会发送该命令,主要是为了

探测Mass Storage设备是否存在(类似心跳信号)。

由于该命令没有数据交互,我们直接返回状态Good Status的CSW状态块即可。

UFI 命令 返回值(UFI Command Specification)相关推荐

  1. 与 python 中的 os.system(cmd) 返回值与linux 命令返回值对应关系

    一.python中的 os.system(cmd)的返回值与linux命令返回值(具体参见本文附加内容)的关系 大家都习惯用os.systemv()函数执行linux命令,该函数的返回值十进制数(分别 ...

  2. linux变量接收命令返回值,Linux Shell教程(一)

    函数返回值 函数返回值,可以显式增加return语句:如果不加,会将最后一条命令运行结果作为返回值. 函数返回值在调用该函数后通过 $? 来获得. 范例1 来看一个带有return语句的函数: #!/ ...

  3. c语言调用shell命令一 popen使用以及获取命令返回值

    产品升级,新增网卡,原先的产品是arm平台,新网卡是mips平台,需要开发网卡的配置程序,该程序原计划是以守护进程的形式后台执行,不过测试过程中发现系统不是特别稳定,导致程序时不时奔溃下,一时半会儿无 ...

  4. linux命令返回值的妙用

    什么是返回值 在shell终端中,你所输入的一切命令其实都有返回值,而这个返回值默认保存在"$?"中,举例看一下 [root@localhost ~]# touch 123 [ro ...

  5. bat获取命令返回值_redis中list和hash的基本命令和使用场景

    Redis的数据类型 Redis的数据类型共有五种:string,list,hash,set,zset: String 字符串相对来说做平常,key-value,类似是hashmap的用法: List ...

  6. bat获取命令返回值_全网都在找的redis字符串命令,总结在这了

    概述 redis一般用来做缓存,可能很多朋友都没有深入去学习redis的相关命令,只是涉及到安装部署而已,所以今天主要总结介绍一下redis字符串的一些命令. SET 语法:SET key value ...

  7. Linux 命令返回值

    在Linux中不管是启动桌面程序还是在控制台执行命令都会有一个返回值,可以叫做错误号(perror),在linux中执行命令后可通过命令:echo $?来查看上一条命令的返回值.要查看返回值的具体含义 ...

  8. 易语言取linux命令返回值,易语言取程序返回值写法

    公告: 为响应国家净网行动,部分内容已经删除,感谢读者理解. 话题:易语言取程序返回值写法回答:在易语言中,程序包括"处理程序"都有六部分组成.一.程序名,就是程序的名称,程序名不 ...

  9. linux中grep命令返回值,grep命令详解

    如果你是一个新手,请从头阅读这篇文章,如果你只是忘记了grep命令的一些常用选项,直接查看文章尾部的总结部分即可. 先说说grep命令能做什么? 我们可以使用grep命令在文本中查找指定的字符串,就像 ...

最新文章

  1. Leangoo_多团队,大规模敏捷开发实现过程
  2. AI时代龙争虎战 什么是传统安企“护城河”?
  3. 射灯安装方法图解_客厅适合用射灯做基础照明吗?又该如何布灯?
  4. C语言经典例39-在有序数组中插入一个数
  5. 云计算网络基础第八天
  6. netsh winsock reset什么意思_商丘耐火砖什么意思,刹车片_马达加斯加嘎瓦石墨公司...
  7. 2015/Province_C_C++_C/8/饮料换购
  8. [18]Debian Linux Install GNU GCC Compiler and Development Environment
  9. WP7中对ListBox的ItemTemplate中子元素的后台操作
  10. 小米机器狗CyberDog
  11. JS在当前页面中调用iframe中的方法
  12. TypeScript 素描-变量声明
  13. 软件基本功:一行70限制早已无效,150起步
  14. 【小项目】STM32环境监测 | MQ2可燃气体传感器+雨滴传感器+DHT11温湿度传感器+OLED屏幕
  15. 非常实用的在线工具网站清单
  16. Python基础PTA习题答案
  17. java 聊天机器人_java实现自动回复聊天机器人
  18. 信捷用c语言编写梯形图,PLC一键启停编程梯形图实例
  19. 苹果应用商店AppStore审核规则指南
  20. java绘图- 绘图用法(基于Graphics2D)

热门文章

  1. 如何用VR改变驾驶陋习?
  2. Servlet[springmvc]引发了load()异常
  3. 计算机专业怎么防止脱发,电脑工作者如何防止脱发出现
  4. flutter-isolate详解
  5. 挂载 nfs 文件系统
  6. 感觉CNZZ不行了,同一个站点,IP比百度、51LA少2万!
  7. Android 录音声音分贝获取
  8. scratch棕熊大战 电子学会图形化编程scratch等级考试四级真题和答案解析2021-12
  9. n元人民币换成1元、2元、5元的零钱,请计算共有多少种兑换方法?
  10. electron-builder打包见解