快捷搜索:

.Net Micro Framework - USB Mass Storage功能实现

1. 阐明

因为.Net Micro Framework的USB驱动架构中,没有为Mass Storage功能供给原生支持,以是除了要编写Mass Storage主体代码外,还必要在原有的USB驱动中添加部分罗列代码。着实从布局上来说,该部分代码应该添加在PAL层,不过斟酌到这层代码为.Net Micro Framework Poring Kit Rtm 3.0标准代码,以是把这部分代码添加到我们自己编写的USB驱动之中去了。

此外,因为Mass Storage功能必要赓续地检测和处置惩罚USB端口的数据,必要一个进程(或线程)去进行驱动。.Net Micro Framework在利用层仅支持一个进程(单个用户法度榜样),以是必须在利用法度榜样中专开一个线程去进行驱动,斟酌到这样实现必要用户做额外的事情,着末摒弃了这一实现。终极的做法是,在Mass Storage驱动中添加了时钟中断处置惩罚函数,Mass Storage被初始化后,该时钟中断被激活,以一个用户可设定的距离去监控和处置惩罚USB端口的数据。

在实现Mass Storage功能的代码中,并没有直接去读写相关Flash,而是借助PAL层的SectorCache模块间接造访Flash,这样有两个好处,一是读写有缓存,操作速率较快,二是法度榜样对照通用,代码在不用改动的环境下可以造访不合的Flash、SD卡等存储模块。

本Mass Storage驱动仅实现了一个功能子集,仅支持单个存储模块,不支持从PC机进行款式化(可经由过程本地供给的接口进行款式化,文件系统今朝必须是FAT32)。

2. USB Config

Mass Storage要求的USB Config和我们.Net Micro Framework的标准驱动不合,一是PID和VID不合,因为Mass Storage设备是免驱动安装的,这PID和VID应该没有多大年夜用场,然则因为曩昔PC上已经安装了该PID和VID的.Net Micro Framework驱动,以是Mass Storage设备插入时,优先去找匹配PID和VID的设备驱动(这样也可以让一些厂家有时机安装自己专门的Mass Storage设备驱动),以是对我们已有该驱动的PC,肯定会有问题,以是我们仅必要调剂一下VID的值即可。

其二我们USB接口描述类中,接口类必须为0x08(Mass storage class),子类为0x06(SCSI transparent command set)或0x04(UFI),接口协议为0x50(Bulk-only transport)。

  图片看不清楚?请点击这里查看原图(大年夜图)。

表1 子类表

  图片看不清楚?请点击这里查看原图(大年夜图)。

表2 接口协议

其它描述信息因为非关键,以是可改动,也可以不改。

3. 调用接口

Mass Storage驱动位于"DeviceCode"Drivers目录下, 属于通用驱动,其它设备都可以调用。包括如下三个文件:UsbMassStorage.h、UsbMassStorage.cpp、UsbMassStorage_config.cpp。

3.1   PAL层接口

3.1.1 UsbMassStorage_Start

Mass Storage功能初始化和启动函数。该函数履行时,先关闭本来的USB驱动接口,再用新USB Config初始化USB接口,着末启动一个准时中断函数。

函数原型:int UsbMassStorage_Start(UINT32 value);

参    数:value为时钟中断距离,单位us。

返 回 值:0。

对付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功能实现的道理。

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手册简明地多。

  图片看不清楚?请点击这里查看原图(大年夜图)。

留意数据款式为大年夜端模式。

具体阐明请拜见《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状态块即可。

您可能还会对下面的文章感兴趣: