其实这个东西做完有一段时间了,基本功能可以实现(实现为可移动磁盘,板子是自己画的),但由于采用的是端口模式,速度太慢(读/写260/210K,汗~),之后想着将它的读写速度提高了再放上来,但试了几次没有太大的效果(牵扯到重新制板),就搁下了。现在看有好几位同学都在找这方面的东西,就分享一下,省得走弯路。另外,本人水平有限,有什么不对的地方希望大家能给我提出来,有什么好的建议也希望能无私分享一下。
本例是以Cypress的bulkloop例子为基础改动而来,加入了USBJmpTb.obj和Ezusb.lib两个框架文件,另外还有多个功能文件,包括SCSI.c、SCSI.h、flash.c、flash.h以及调试用的Serial.c、Serial.h。
实现基本的U盘其实很简单,这里的基本当然不包括像坏块管理、磨损平衡等功能。在设备插入USB口后,首先要告诉主机这是一个U盘,具体实现就是修改设备描述符文件(dscr.a51),告知设备的类别、所用的协议(08、06、50)以及和主机进行块传输的端点。当然,还要指定设备的PID/VID,这里可以直接用一个买来的U盘的PID/VID,这样主机在发现我们自己的设备时可以加载通用U盘驱动。这是第一步。
第二步,进入BULK传输,其实就是通过上面声明的块端点和主机进行数据交互,遵循BULK-ONLY协议。主机有什么命令发送到OUT端点,固件对命令进行解析并响应,通过IN端点返回相应数据。个人认为,所有的命令可以分为两类:直接返回固定数据(如INQUIRY、ReadFormatCapacities等)和读写FLASH命令。命令及其响应由SCSI.C实现。
第三步,就是完成具体的读写FLASH的代码了,参见flash.c文件。这里要说明一点的是,本人的板子用的FLASH是K9K8G,它的页拷贝命令有一些特殊的限制,因此在实现读写时采用的是最笨的办法,只用了其容量的1/4,而且代码比较复杂。
关于固件干的工作,要明确的一点是:固件不会去计算读写命令的LBA(逻辑块地址),LBA都是主机的驱动计算的,固件的任务就是将LBA转换成物理地址,在FLASH读写的地址周期写入。另外,主机的读、写、格式化等命令在固件看来都只有两个命令,那就是Read和Write,所以这两个命令的处理是核心。对于逻辑地址到物理地址的转换,要分清大页(2K/page)和小页(512B/page)的区别。
Cypress的固件框架及其参考例子是基础,大家可以多看看,有条件的买一块开发板回来做做实验,上手更快(本人就是因为没有买开发板而弄了好长时间,划不来)。要看的协议:bulk-only(其实看看一些参考书或文献就可以了,说得挺详细的),另外就是芯片的数据手册了。参考书:计算机USB系统原理及其主/机设计,马伟;USB2.0原理与工程开发(第2版),李英伟等;USB应用开发技术大全。
希望大家能把自己的心得、经验、改进等拿出来分享一下,在帮助别人的同时也可以让别人发现自己没有发现的问题。本人邮箱:jinpaiyuangui@126.com
最后,祝顺利!
用户1512902 2015-1-12 15:08
用户451099 2014-9-5 00:28
用户377235 2013-9-3 23:20
请教一个问题,这样实现的U盘,怎么实现首次格式化呢?求教。邮箱地址V0860#126.com
用户429395 2013-4-1 10:31
用户306711 2012-2-23 13:01
看看拉
用户312090 2010-12-11 14:54