USB设备通过控制端口响应USB标准请求,实现主机和设备间的通信。除控制端口外,Bulk-Only传输方式还需支持Bulk-In和Bulk-Out端口。端口初始化代码如下:
void Usb_Init(void)
{
UEPNUM=0x00; UEPCONX=0x80;
//端口0,控制端口
UEPNUM=0x01; UEPCONX=0x86;
//端口1,Bulk-In端口
UEPNUM=0x02; UEPCONX=0x82;
//端口2,Bulk-Out端口
UEPRST=0x07; UEPRST= 0x00;//端口复位
UEPIEN=0x07; USBIEN|=EEOFINT;
USBADDR=FEN; //功能使能位
}
当控制端口配置成功后,主机会发出Inquiry、Mode_Sense、Read_Capacity等请求,提供闪盘基本信息,如扇区大小、簇大小、闪盘容量等,当请求结果正确后,便会发出Read(10)命令,进入文件系统识别阶段。
3.2 解析SCSI命令并处理
UFI 命令规范基于 SFF-8070i 和 SCSI-2 的规范,总共定义了19个固定12字节长度的操作命令,用于 USB主机和 USB 移动存储设备之间进行命令字CBW (Command Block Wrapper)、普通数据、状态字CSW (Command Status Wrapper)的交换。
USB移动存储设备接收到来自于USB主机Bulk-Out端口发给其的CBW命令字后,按照SCSI的命令格式进行解析,得到其中的命令信息,如:格式化设备、查询设备信息、读写设备等,对移动存储设备执行相应的命令后,向主机Bulk-In端口返回状态字 CSW,报告命令执行情况,主机根据反馈的状态字决定是否继续发送命令字或是数据。
3.3 闪存的操作实现
K9K2G08U0A芯片以页为单位来进行读写,以块为单位进行擦除。K9K2G08U0A支持的操作主要有几种:读操作(Read)、页编程(Page Program)、缓存编程(Cache Program)、块擦除(Block Erase)、块复制(Copy-Back Program)、随机数据输入(Random Data Input)、随机数据输出(Random Data Output)、复位(Reset)、读设备号(ReadID)、读状态(Read Status)等操作。在进行写操作之前,必须对写单元所在块进行擦除,因此事先需要对所擦除块内容进行保存。
如果闪存存在坏块,则在进行读、页编程、块擦除、块复制等操作时会失败,因此对坏块要进行提前检测并进行标注。芯片在出厂时,在每块的第一页和第二页的2048列的首字节做出好坏标记,如果标志位不是FFh则为坏块,基于此建立坏块列表。
基于篇幅的原因,这里以写操作过程为例描述闪存使用方法。一般闪存的使用顺序是:块擦除-编程-多次读取-块擦除…, 对K9K2G08U0A芯片进行数据写的步骤如下:(1)将写入数据扇区地址与坏块列表对照,检查错误扇区。若存在坏区,则继续检查下一扇区;(2)开辟缓冲区域,将写入数据扇区的原始数据利用Copy-Back Program方式保存到缓冲区;(3) 利用Block Erase擦除要写入的数据扇区;(4) 利用 Page Program操作将主机传输的数据写到闪存中;(5)利用Copy-Back Program操作将缓冲区的数据写入指定扇区。