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。
3.1.2 UsbMassStorage_Stop
Mass Storage功能停止函数。该函数先关闭时钟中断函数及自己定义的USB接口,最后恢复默认USB接口(即UsbDefaultConfiguration)。
函数原型:int UsbMassStorage_Stop();
返 回 值:0。
3.2 P/Invoke接口
考虑到用户也可以自由开启和关闭Mass Storage功能,所以为用户提供了P/Invoke接口。该接口文件位于:\Solutions\DM335\DeviceCode目录下,其实该程序通用,可以放在PAL层。包括两部分代码,一是托管代码,二是本地代码。
接口声明如下,函数功能同PAL层接口。
namespace YFSoft
{
public static class MassStorage
{
[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static public int Start(UInt32 value);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static public int Stop();
}
}
注意:用户在调用MassStorage.Start()函数之前,先执行以下代码,以使磁盘缓存中的内容真实写入存储设备。
VolumeInfo[] vis = VolumeInfo.GetVolumes();
foreach (VolumeInfo vi in vis)
{
vi.FlushAll();
}
4.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状态块即可。
分享到:
相关推荐
《玩转.NET Micro Framework移植-基于STM32F10x处理器》源程序
The Microsoft .NET Micro Framework is a small and efficient .NET runtime environment used to run managed code on devices that are too small and resource constrained for Windows CE and the Compact ...
.NET Micro Framework 电子书
.net micro framework关于文件操作的例子,非常详细。还包括了点击等东西
《玩转.NET Micro Framework 移植-基于STM32F10x处理器》一书所有的源代码。其它更多的资源可以访问我的blog:http://blog.csdn.net/norains 谢谢!
expert .net micro frameworkexpert .net micro frameworkexpert .net micro framework
.NET Micro Framework自动化测试工具,需.NET Micro Framework3.0和.NET Micro Framework Test Kit支持...
Microsoft .NET Micro Framework 2.5 SDK。 这个我暂时没用,权当放在这里存放,需要的,自己动手。
.NET Micro Framework for Windows 7(X64) USB驱动安装说明,包含相应的驱动程序
近来有些刚入门的用户,不太了解.NET Micro Framework开发板的使用,所以写了这篇文档,以期缩短用户对开发板的熟悉时间。
micro framework 4.0 SDK,最新开发工具包
这是我自己改造的.Net Micro Framework模拟器,比windows自带的漂亮多了。 覆盖该目录下的同名文件(路径以实际开发包安装位置为准)即可。 C:\Program Files\Microsoft .NET Micro Framework\v2.0.3036\Tools 支持...
.NET Micro Framework 电子书
http://item.taobao.com/item.htm?id=7117999726 .NET Micro Framework开发板的Key文件的部署说明。
《精通.NET Micro Framework》 英文PDF + 源码
.NET Micro Framework开发板原理图(红牛开发板)
.NET Micro Framework开发板使用手册(红牛开发板)
如何顺利编译.Net Micro Framework Porting Kit 4.1 安装路径不能有空格
注:比上一个模拟器多了支持方向键控制 这是我自己改造的.Net Micro Framework模拟器,比windows自带的漂亮多了。 覆盖该目录下的同名文件(路径以实际开发包安装位置为准)即可。 C:\Program Files\...