USB Mass Storage学习笔记-STM32+FLASH实现U盘
- 格式:pdf
- 大小:372.04 KB
- 文档页数:15
用STM32CubeMX快速生成一个U盘模拟程序前提:默认已经装好MDK V5和STM32CubeMX。
Step1.新建工程选择芯片型号。
Step2.配置时钟引脚。
Step3.配置USB引脚。
Step4.配置USB设备类。
Step5.配置时钟树,USB模块输入要求为48MHz时钟。
Step6.配置USB设备描述符。
此处默认即可。
Step7.生成MDK工程及代码。
特别注意,一定要加大堆栈大小,否则USB设备无法启动。
Step8.打开MDK工程。
Step9.选择芯片型号。
Step10.编译工程。
Step11.编译下载运行。
运行程序后,通过USB线链接电脑,将出现如下提示信息。
查看“设备管理器”,可以看到USB MSC设备。
“我的电脑”界面下可以可移动磁盘。
但是,双击无法打开,出现格式化提示。
进入格式化对话框,可以看到磁盘总容量是32MB。
实际上无法进行格式化操作。
Step12.修改代码。
只需修改usbd_storage_if.c文件。
将60行的宏定义改为200,即将要模拟的U盘有200个扇区。
61行是扇区大小定义512。
用60,61行的宏,定义一个二维数组,这个数组就是将要模拟的U盘的实际存储空间。
因此该U盘总容量为100KB。
然后为两个函数添加功能,一个是读块,一个是写块。
他们是对msc_data数组的读写操作。
操作规则就和SD卡一样,按照512字节为一个扇区进行整体的读/写。
Step13.再次编译下载运行。
运行程序后,通过USB线链接电脑,不再像前一次一样出现很多提示信息,只是在任务栏最右边出现U盘插入的图标。
在“我的电脑”界面下可以看到“可移动磁盘”。
双击无法打开,提示进行格式化,点“是”进入格式化窗口。
可以看到U盘容量为100KB。
勾选“快速格式化”,点击“格式化”按钮。
不支持普通格式化,我也没弄清楚原因。
格式化完成后,就可以双击打开这个“U盘”了,这是一个可以进行读写的U盘。
将这个U盘弹出,然后断开USB链接线,然后再重新连接,就可以被360 U盘助手发现了。
基于STM32的USB学习总结第一章基础之简析USB协议1、USB包的分类USB包主要有以下几种:令牌包、数据包、握手包,其他包暂时用不到先不提。
1.1、令牌包顾名思义,这个类型的包是用来发布命令的,我们知道USB协议是典型的主从结构的协议,主设备就是用来发送令牌包,从设备是接收令牌后执行相应的命令的设备。
而令牌包下面又分了几种类型的令牌,他们分别带表了不同命令。
令牌包可分为SETUP包、IN包、OUT包、SOF包,其中SETUP包、IN包、OUT包结构构如下:其中同步域是用来同步主机和从机的,8位PID号分别代表了不同的包,其中低4位代表PID,高4位是用来取反的。
USB协议也是靠不同的PID来区别不同类型的包的。
我们先列下令牌包的几种包的PID以及各1.2、数据包用来代表这个包是用来装载用户传输的数据,包的长度大小和设备的属性有关,第一个数据包总是跟在令牌的后面,有了令牌包才会有数据包。
DAET0和DATE1都是用来传送数据,那为什么要2个不同的包呢?因为在USB协议里,每次成功传送一次数据后,都会进行数据类型的反转,即从DATE0到DATE1或者DATE1到DATE0。
举例说明:如果传送不成功主句不会收到ACK,那么他就会以原来的数据包PID进行发送数据,这样从机接收到新的PID和自己的是一样的,会保存数据;另外一种情况是,从机保存了数据并进行了数据类型反转,然后向主机发送了ACK,但主机没收到,主机也会按原来的PID数据包从新发送,当从机接收到了数据包后发现与将要接收的PID类型不一样,则不会保存数据。
1.3、握手包这种包是用来进行确认消息是否有效或者消息是否发送成功的,握手包可以分为ACK,NAK,STALL和ACK,NAK,STALL和NYET包的PID如下表:2、USB 事务USB 事务也可以称为USB 事件,每次事件的发生必定会存在3种包:令牌包---用来发送指令,数据包---用来传送数据,握手包-----用来确认操作。
如何实现Linux下的U盘(USB Mass Storage)驱动How to Write Linux USB MSC (Mass Storage Class) Driver版本: 0.4作者: crifan联系方式:green-waste (at) 版本历史目录1正文之前 (6)1.1本文目的 (6)1.2阅读此文所需要的前提知识 (7)1.3声明 (7)2USB基本知识 (8)2.1USB的硬件 (8)2.2USB相关的协议 (8)2.3USB相关的软件实现 (8)3USB Mass Storage大容量存储的基本知识 (9)3.1USB Mass Storage相关的协议 (13)3.1.1USB Mass Storage相关协议简介 (14)3.1.1.1USB MSC Control/Bulk/Interrupt (CBI) Transport (14)3.1.1.2USB MSC Bulk-Only (BBB) Transport (15)3.1.1.2.1为何USB MSC中Bulk-only Transport被叫做 BBB (15)3.1.1.2.2为何已经有了CBI,又再弄出个BBB (15)3.1.1.3USB MSC UFI Command Specification (16)3.1.1.4USB MSC Bootability Specification (16)3.1.1.5USB MSC Compliance Test Specification (17)3.1.1.6USB Lockable Storage Devices Feature Specification (17)3.1.1.7USB MSC USB Attached SCSI Protocol (UASP) (17)3.1.1.7.1已有SCSI协议,为何还要再弄一个UASP (17)3.1.2USB MSC的各个协议之间关系总结 (19)3.1.3U盘与USB中的Class,Subclass和Protocol的对应关系 (20)3.1.3.1bInterfaceClass=0x08=Mass Storage (21)3.1.3.2bInterfaceSubClass=0x06=SCSI Transparent (21)3.1.3.3bInterfaceProtocol=0x50=Bulk Only Transport (21)3.2USB Mass Storage相关的软件实现 (22)4实现U盘驱动的整个流程是什么样的 (23)5Linux系统下,USB驱动的框架已经做了哪些事情 (24)6Linux下实现U盘驱动,自己需要做哪些事情以及如何做 (25)7引用文章 (26)图表图表 1 U盘 (6)图表 2 USB Mass Storage Framework (9)图表 3 PC和U盘 (10)图表 4 PC和U盘的芯片内部结构 (10)图表 5 PC和U盘的内部逻辑框图 (11)图表 6 PC和USB MSC设备 (12)图表 7 USB MSC的分类 (12)图表 8 USB Storage Class Protocol Relation (19)图表 9 SubClass Codes Mapped to Command Block Specifications (21)图表 10 Mass Storage Transport Protocol (21)图表 11 USB数据流向图 (23)缩写1 正文之前1.1 本文目的关于U盘,估计大家都用过。
USB Mass Storage学习笔记-STM32+FLASH实现U盘一、内容概述采用STM32内部自带USB控制器外加大页NAND FLASH K9F1G08U0A实现一个128M的U盘。
1、STM32的USB控制器STM32F103的MCU自带USB从控制器,符合USB规范的通信连接;PC 主机和微控制器之间的数据传输是通过共享一专用的数据缓冲区来完成的,该数据缓冲区能被USB外设直接访问。
这块专用数据缓冲区的大小由所使用的端点数目和每个端点最大的数据分组大小所决定,每个端点最大可使用512字节缓冲区,最多可用于16个单向或8个双向端点。
USB模块同PC主机通信,根据USB规范实现令牌分组的检测,数据发送/接收的处理,和握手分组的处理。
整个传输的格式由硬件完成,其中包括CRC的生成和校验。
每个端点都有一个缓冲区描述块,描述该端点使用的缓冲区地址、大小和需要传输的字节数。
当USB模块识别出一个有效的功能/端点的令牌分组时,(如果需要传输数据并且端点已配置)随之发生相关的数据传输。
USB模块通过一个内部的16位寄存器实现端口与专用缓冲区的数据交换。
在所有的数据传输完成后,如果需要,则根据传输的方向,发送或接收适当的握手分组。
在数据传输结束时,USB模块将触发与端点相关的中断,通过读状态寄存器和/或者利用不同的中断来处理。
USB的中断映射单元:将可能产生中断的USB事件映射到三个不同的NVIC 请求线上:(1)USB低优先级中断(通道20):可由所有USB事件触发(正确传输,USB复位等)。
固件在处理中断前应当首先确定中断源。
(2)USB高优先级中断(通道19):仅能由同步和双缓冲批量传输的正确传输事件触发,目的是保证最大的传输速率。
(3)USB唤醒中断(通道42):由USB挂起模式的唤醒事件触发。
图 1、USB设备框图2、大页NAND K9F1G08Nand flash 以页为单位读写数据,而以块为单位擦除数据。
Keil移植stm32的usb及usb massStorage步骤1.将STM32的usb的库文件拷贝到Src\Libraries下并在工程中添加STM32_USB-FS-Device_Driver全部源文件;在工程属性c++选项include Path 添加STM32_USB-FS-Device_Driver\inc路径2.将本目录的Mass_Storage文件夹拷贝到Src\Usr文件下并在工程中添加Mass_Storage\src全部源文件;在工程属性c++选项include Path 添加Mass_Storage\inc路径3.将下面三个头文件和两个函数加到stm32f10x_it.c中#include "usb_lib.h"#include "usb_istr.h"#include "usb_pwr.h"void USB_HP_CAN1_TX_IRQHandler(void){CTR_HP();}void USB_LP_CAN1_RX0_IRQHandler(void){USB_Istr();}6.对Mass_Storage\src下的usb_hw_config.c文件下其中2个函数void USB_Disconnect_Config(void) [注意:此处的IO口设置为推挽输出]void USB_Cable_Config (FunctionalState NewState)重新按照自己硬件改写Mass_Storage\inc下的usb_hw_config.h文件三个定义#define USB_DISCONNECT GPIOA#define USB_DISCONNECT_PIN GPIO_Pin_8#define RCC_APB2Periph_GPIO_DISCONNECT RCC_APB2Periph_GPIOA关于usb的使能IO 按照自己硬件改写7.在\Src\Usr\Mass_Storage\mass_mal.c文件中A:添加存储器驱动文件相关函数的头文件B:填写四个函数,均为存储器的相关驱动函数在unsigned short int MAL_Init(unsigned char lun)中添加存储器初始化函数在unsigned short int MAL_Write(unsigned char lun, unsigned int Memory_Offset, unsigned int *Writebuff, unsigned short int Transfer_Length) 中添加存储器写缓存函数在unsigned short int MAL_Read(unsigned char lun, unsigned int Memory_Offset, unsigned int *Readbuff, unsigned short int Transfer_Length) 中添加存储器读缓存函数在unsigned short int MAL_GetStatus (unsigned char lun)中添加存储器容量的函数8.使用方法:包含头文件#include "usb_lib.h"#include "usb_hw_config.h"#include "usb_pwr.h"调用函数:MassStorageInit(); //IO相关初始化Set_USBClock(); //USB时钟初始化USB_Interrupts_Config(); //USB通信中断配置USB_Init(); //USB初始化9.吴青松2012-3-15。
usb mass storage大容量存储的基本知识-回复USB Mass Storage(简称USB存储)是指使用通用串行总线(USB)接口的设备来存储和传输大容量数据的技术。
USB存储设备通常包括闪存驱动器、外部硬盘和光盘驱动器等。
本文将一步一步回答关于USB存储的基本知识。
1. 什么是USB存储?USB存储是一种用于存储和传输大容量数据的技术方法,通过USB接口连接计算机设备。
USB存储设备可以是可携带的闪存驱动器、外部硬盘、光盘驱动器等,可以在不同设备之间快速、方便地存储和传输数据。
2. USB存储的工作原理是什么?USB存储设备通过USB接口连接到计算机设备,其内部包含一个控制器芯片,用于处理数据传输和设备管理。
当将USB存储设备连接到计算机时,操作系统会识别设备并安装相应的驱动程序。
通过USB接口,计算机可以读取和写入存储设备中的数据。
3. USB存储设备有哪些类型?USB存储设备的类型多种多样,常见的包括:- 闪存驱动器(USB闪盘):这是一种使用闪存芯片进行数据存储的便携式设备,具有小巧轻便,容量可大可小的特点。
- 外部硬盘驱动器:这种存储设备使用类似于计算机硬盘的旋转硬盘或固态硬盘进行数据存储,能够提供较大的存储容量。
- 光盘驱动器:这种设备用于读取和写入光盘(如CD、DVD)中的数据,可以用于存储和传输大容量数据。
4. USB存储设备的优势是什么?USB存储设备的优势包括:- 便携性:USB存储设备通常小巧轻便,方便携带。
用户可以随时将数据放入存储设备并随身携带,无需依赖网络或其他外部存储设备。
- 大容量:随着技术的发展,USB存储设备的存储容量不断增加,从几GB到几TB不等。
用户可以选择适合自己需求的存储容量。
- 兼容性:USB存储设备在不同的计算机和操作系统上具有广泛的兼容性。
几乎所有的现代计算机都具备USB接口,因此用户可以轻松连接到各种设备上。
5. 如何使用USB存储设备?使用USB存储设备非常简单,只需按照以下步骤操作:- 将USB存储设备插入计算机的可用USB接口中。
基于STM32的USB枚举过程学习笔记(四)前几篇介绍中,USB 主机完成了获取设备的描述符,现在进入第二步,设置设备的地址阶段。
该阶段是一个无数据过程的控制传输。
首先,在建立过程中USB 主机往设备的端点0 发出一个设置地址的请求,新地址在建立过程的数据包中。
该事务的结构包括:SETUP0 令牌包+SET_ADDRESS 数据包+ 握手包。
在建立过程之后直接进入到的状态过程,因为设置地址阶段是一个无数据过程的控制传输。
在状态过程,设备等待主机请求状态返回(即等待主机发送一个IN 令牌包),收到IN 令牌包后,设备就返回一个0 长度的数据包,如果主机确认该数据包已经正确收到,就会发送应答包ACK 给设备,设备收到ACK 之后,就要启动新的设备地址,这样设备就分配到了一个唯一的设备地址。
接下来将这段设置地址的过程通过USB 分析仪捕捉分析如下接着分析STM32 USB_HID 例子中的枚举过程的设置地址阶段。
同样在接收到主机的setup0 令牌后,STM32 USB 进入中断处理函数Setup0_Process(),由于是没有数据过程的控制传输,接着进入NoData_Setup0()函数,函数最后通过USB_StatusIn()等待主机的IN 令牌,即状态阶段。
主机发IN 令牌进入到状态阶段,USB 中断函数中执行In0_Process()函数,该函数把在建立过程函数Setup0_Process()中保存在pInformation 的地址信息,通过SetDeviceAddress()函数,配置新的设备地址。
串口的调试信息如下至此,设备新的地址设置成功,这里设置成0x6,之后的过程将使用这个新。
0、友情提示《零死角玩转STM32》系列教程由初级篇、中级篇、高级篇、系统篇、四个部分组成,根据野火STM32开发板旧版教程升级而来,且经过重新深入编写,重新排版,更适合初学者,步步为营,从入门到精通,从裸奔到系统,让您零死角玩转STM32。
M3的世界,与野火同行,乐意惬无边。
另外,野火团队历时一年精心打造的《STM32库开发实战指南》将于今年10月份由机械工业出版社出版,该书的排版更适于纸质书本阅读以及更有利于查阅资料。
内容上会给你带来更多的惊喜。
是一本学习STM32必备的工具书。
敬请期待!6、UsbDevice(模拟U盘)6.1 实验描述及工程文件清单实验描述这是一个USB Mass Storage 实验,用USB线连接PC机与开发板,在电脑上就可以像操作普通U盘那样来操作开发板中的MicroSD卡,并在超级终端中打印出相应的调试信息。
在这里野火用的MicroSD卡的容量是1G。
硬件连接PE3-USB-MODE (PE3为普通I/O)PA11-USBDM(D-)PA12-USBDP(D+)用到的库文件startup/start_stm32f10x_hd.cCMSIS/core_cm3.cCMSIS/system_stm32f10x.cFWlib/stm32f10x_gpio.cFWlib/stm32f10x_rcc.cFWlib/stm32f10x_usart.cFWlib/misc.cFWlib/stm32f10x_dma.cFWlib/stm32f10x_sdio.cFWlib/stm32f10x_flash.c用户编写的文件USER/main.cUSER/stm32f10x_it.cUSER/usart1.cUSER/sdcard.cUSER/usb_istr.cUSER/usb_prop.cUSER/usb_pwr.cUSER/hw_config.cUSER/memory.cUSB文件usb_core.cusb_init.cusb_mem.cusb_regs.cusb_bot.cusb_scsi.cusb_data.cusb_desc.cusb_endp.c其中USER文件夹下红色标注的5个c文件也是USB库文件,只因为我们需要修改它们才没有把它们放在USBLIB目录下。
对USB的初步了解:1、USB的优点:可以热插拔,即插上后可以自动识别;系统总线供电,USB共有四根线,一根电源线,一根地线,一根D+线,一根D-线,D+和D-线是差分输入线;可以支持多种设备,且扩展容易,通过HUB可以再一个主机上连接多个设备传输数据的速度快,最快可达480Mbit/s方便的设备互联:在没有主机的情况下,实现点到点的通信(还可以实现主从互换)(USB OTG)2、USB的基本规范:USB1.0/1.1 低速情况下1.5Mbit/s:键盘、鼠标等全速情况下12Mbit/s:U盘、CD-ROMUSB2.0 高速达到480Mbit/s:音频设备、显示器等USB OTG 设备到设备的传输3、USB设备类规范:大容量存储设备类(Mass Storage Device)U盘、CD-ROM等人机交互设备类(Human Interface Device)键盘、鼠标、游戏手柄语音设备类(Audio Device)麦克风、音响等通信设备类(Communication Device)电话、调制解调器等打印机设备类(Printer Device)打印机监视设备类(Monitor Device)显示器、摄像头等4、USB逻辑上分为3:信号层,协议层,数据传输层协议层:包是USB系统中信息传输的基本单位,所有的数据都是经过打包后在总线上传输的。
包由6部分组成:同步字段(SYNC);包标识符(PID);地址字段(ADDR);数据字段(DA TA);检验字段(CRC);包结束(EOP)包标识符(PID):令牌包(Token)(输出,输入,帧起始,建立),数据包(DA TA)(数据,数据1),握手包(Handsnake)(确认,不确认,停止),专用包(Special)(前同步)5、USB协议提供4种数据传输方式:控制传输:突发,非周期性,由主机发起,用于命令和状态的传输同步传输:周期性,持续性的传输,用于传输与时效相关的信息,并且在数据中保存时间戳的信息中断传输:周期性,低频率,允许有限延迟的通信大容量的数据传输:非周期性,大容量突发数据的通信6、USB描述符:1)设备描述符:描述设备的类型、厂商信息、USB的协议类型、端点的报数据的最大长度等,每个USB设备只有一个Device Descriptor2)配置描述符:每个配置描述符提供了设备特定的配置,描述了设备的接口和端点的性质、供电模式、设备的耗电3)接口描述符:描述了设备的不同接口的特性,例如,一个设备U盘的功能,又有键盘的功能,用两个接口描述符分别描述两个功能4)字符串描述符:描述了设备制造商、设备名称、何序列号等信息基于STM32制作USB的过程STM32的USB模块特性:遵循USB2.0全速设备标准支持双向8个端点,8个IN端点和8个OUT端点(每个端点最大可使用512字节)[ 每个端点都有一个缓冲区描述块,描述该端点使用的缓冲区地址、大小和需要传输的字节数]硬件实现CRC自动生成/校验,NRZI编码/解码和bit-stuffing(位插入,位填充)支持控制传输、中断传输、大容量传输和同步传输四种传输方式支持USB的挂起和/唤醒***USB设备的实现过程***一、系统初始化1、初始化系统时钟,设置USB时钟2、配置USB中断,选择通道,设置优先级,使能中断3、配置GPIO4、USB的初始化,对描述符、设备的端点接口等的初始化5、FLASH的初始化二、USB的枚举枚举过程就相当于主机和设备建立连接的过程(接头),Host向Device询问一些东西,Device将自身的设备类型,如何进行通信报告给Host,这样,Host就知道怎么对Device 进行操作。
USB Mass Storage学习笔记-STM32+FLASH实现U盘一、 内容概述采用STM32内部自带USB控制器外加大页NAND FLASH K9F1G08U0A实现一个128M的U盘。
1、STM32的USB控制器STM32F103的MCU自带USB从控制器,符合USB规范的通信连接;PC主机和微控制器之间的数据传输是通过共享一专用的数据缓冲区来完成的,该数据缓冲区能被USB外设直接访问。
这块专用数据缓冲区的大小由所使用的端点数目和每个端点最大的数据分组大小所决定,每个端点最大可使用512字节缓冲区,最多可用于16个单向或8个双向端点。
USB模块同PC主机通信,根据USB 规范实现令牌分组的检测,数据发送/接收的处理,和握手分组的处理。
整个传输的格式由硬件完成,其中包括CRC的生成和校验。
每个端点都有一个缓冲区描述块,描述该端点使用的缓冲区地址、大小和需要传输的字节数。
当USB模块识别出一个有效的功能/端点的令牌分组时,(如果需要传输数据并且端点已配置)随之发生相关的数据传输。
USB模块通过一个内部的16位寄存器实现端口与专用缓冲区的数据交换。
在所有的数据传输完成后,如果需要,则根据传输的方向,发送或接收适当的握手分组。
在数据传输结束时,USB模块将触发与端点相关的中断,通过读状态寄存器和/或者利用不同的中断来处理。
USB的中断映射单元:将可能产生中断的USB事件映射到三个不同的NVIC 请求线上:(1)USB低优先级中断(通道20):可由所有USB事件触发(正确传输,USB复位等)。
固件在处理中断前应当首先确定中断源。
(2)USB高优先级中断(通道19):仅能由同步和双缓冲批量传输的正确传输事件触发,目的是保证最大的传输速率。
(3)USB唤醒中断(通道42):由USB挂起模式的唤醒事件触发。
图 1、USB设备框图2、大页NAND K9F1G08Nand flash 以页为单位读写数据,而以块为单位擦除数据。
根据NAND 的容量等级又将NANDFLASH分为大页NAND和小页NAND;K9F1G08就是大页NAND,它的页大小为(2K+64)Byte,块大小为(128K+4K)Byte。
K9F1208U0M 为小页NAND,它的页大小为(512+16)Byte,块大小为(16K+512)Byte。
由于写数据至FLASH时,只能将指定的位变为0,而不能将指定的位变位1。
因此在写一个页的数据前,必须先擦除(将所有的位全部置1),否则写数据会失败。
在编制FLASH的读写程序时,需要传递三个参数,要操作的地址,要操作的数据缓存,要操作的数据长度;在写操作时,还要有擦写和坏块管理。
3、USB Mass storage Bulk OnlyMass Storage类支持两个传输协议:1、Bulk-Only 传输(BOT)2、Control/Bulk/Interrupt传输(CBI)Mass Storage类规范定义了两个类规定的请求:Get_Max_LUN和Mass Stor age Reset,所有的Mass Storage类设备都必须支持这两个请求。
Bulk-Only Mass Storage Reset(bmRequestType=00100001b and bReques t= 11111111b)用来复位Mass Storage设备及其相关接口。
Get_Max_LUN(bmRequestType= 10100001b and bRequest= 11111110b)用来确认设备支持的逻辑单元数。
Max LUN的值必须是0~15。
注意:LUN是从0开始的。
主机不能向不存在的LUN发送CBW。
支持BOT传输的Mass Storage设备接口描述符要求如下:接口类代码bInterfaceClass=08h,表示为Mass Storage设备;接口类子代码bInterfaceSubClass=06h,表示设备支持SCSI Primary Com mand-2(SPC-2);协议代码bInterfaceProtocol有3种:0x00、0x01、0x50,前两种需要使用中断传输,最后一种仅使用批量传输(BOT)。
支持BOT的设备必须支持最少3个endpoint:Control, Bulk-In和Bulk-O ut。
USB2.0的规范定义了控制端点0。
Bulk-In端点用来从设备向主机传送数据。
Bulk-Out端点用来从主机向设备传送数据。
Bulk-Only传输(BOT)像控制传输一样,BOT也是由Command阶段,可选的数据阶段和状态阶段组成。
所有的command请求都可能有或没有Data阶段。
下图说明了BOT的Comman d传输,Data-In,Data-Out传输及Status传输。
图2、Bulk-Only传输示意图CBW是由31个字节组成的短包。
CBW和后续的数据以及CSW都是从新封包开始的。
要注意的是所有CBW传输都是little-endian模式。
在CBW中,dCBWSignature必须是“43425355h”,表示是CBW封包。
dCBWTag是CB标签,会通过对应的CSW的标签反馈回来。
在CSW中,dCSWSignature必须是“53425355h”,表示是CSW包。
二、 系统的初始化1、初始化系统时钟,设置USB时钟为48MHz;2、USB中断配制,选择通道、设置优先级、使能中断。
3、USB初始化:连接USB、USB硬件复位、配制CNTR寄存器使能和屏蔽中断、清零中断状态寄存器。
4、FLASH初始化。
三、 USB的枚举当USB连接时,进入USB低优先级中断。
首先获取中断状态(读ISTR寄存器),在MASS STORAGE中有USB复位中断、USB挂起中断和正确的数据传输中断。
注:在usb_istr.c 的void USB_Istr(void)函数中。
1、USB总线复位:设置分组缓冲区描述表起始地址;初始化端点:端点0为控制端点、端点1、2为批量端点;设置发送和接收状态,设置发送和接收缓冲区地址。
设置CBW签名, CBW.dSignature=0x43425355;初始化BOT状态机。
注:在usb_prop.c的void MASS_Reset()函数中。
2、USB总线挂起:Xms总线上无数据传输,USB总线挂起,进入低功耗模式。
注:在usb_pwr.c的void Suspend()函数中。
3、正确的数据传输中断(usb_int.c CTR_LP();)清除中断标志;获取端点标识符;控制端点处理:读端点寄存器,用来判断是数据输入、输出还是建立包。
非控制端点处理:下一节介绍。
详见软件流程图。
图3、USB枚举软件流程图四、 非控制端点处理(usb_endp.c -> usb.bot.c)端点2输出中断:usb主机传数据或命令包至mcu。
端点1输入中断:mcu传数据或描述符至usb主机。
1、端点2输出中断(1) 将主机传过来的数据从USB端点缓存区copy至MCU内存;(2) 判断BOT状态,根据BOT状态做出相应的处理:当BOT状态位为0时,CBW包解析,并处理SCSI命令;当BOT状态为1时,表示数据输出,执行WRITE10命令处理。
2、端点1输入中断判断BOT状态,如果BOT状态为2,表示数据输入,执行READ10命令处理;如果BOT状态为4,则表示数据输入完成,则返回CSW,进行到命令状态。
3、BOT状态机软件流程图(1)端点2输出中断流程图(usb_bot.c -> Mass_Storage_Out())图4、端点2输出中断(2)CBW包解析软件流程图(usb_bot.c -> CBW_Decode())图5、CBW包解析(3)READ10命令软件流程图(usb_scsi.c -> SCSI_Read10_Cmd(lun , LBA , BlockNbr))图6、READ10命令(4)WRITE10命令软件流程图(usb_scsi.c -> SCSI_Write10_Cmd(lun , LBA , BlockNbr))(5)端点1输入中断流程图(usb_bot.c -> Mass_Storage_In())图8、端点1输入中断4、USB对Memory的操作在MASS STORAGE中,USB对MEMORY的操作是以扇区(在FAT中,一个扇区为512字节)为单位的,而USB端点的最大包长为64字节,因此要发送或接收的数据会先放到内存,假设是CPU向端点1写数据,则首先从FLASH 或SD卡中读取一扇区数据,再按最大包长分8次向USB端点发送。
如果是端点2输出数据,则CPU将收到的数据先放至内存,并累加,当是512字节的整数倍时,再将数据写入FLASH或SD,软件操作流程如下:图9、READ_MEMORY流程图在对FLASH或SD卡的读写操作中,该函数需要三个入口参数,第一个是逻辑单元号,用来告诉CPU主机是对哪个磁盘操作(假设有多个磁盘);第二个是逻辑块地址,这里是指第几个扇区,而存储器的地址为字节地址,所以这个地址需要转换;第三个为数据长度,可以是多少个扇区,也可以是多少个字节,这个可以在CBW包中获得。
当数据发送完后,BOT的状态值置为4,进入到状态阶段。
五、 FLASH读写USB对FLASH的操用是任意的,以扇区为单位,由于不是按连续地址写数据,所以FLASH的写函数中要有擦写管理。
这里我是直接移植圈圈的FLASH读写函数,所以这里引用他的说明:(以下文字出自圈圈的BLOG)由于NAND FLASH擦除时,只能按按块擦除,因此在写扇区时,首先要擦除一个块。
在擦除块前,必须将块内其他数据复制出来,由于一个块比较大(128KB),无法在MCU内开辟如此大的缓冲区。
只好借助该NAND FLASH内的页复制命令,将原来的块暂时复制到一个交换用的交换块中。
但是如果仅用一个块作为交换的话,它就会被频繁擦写,因而寿命会大大降低。
所以在该系统中,保留了10个块用来作为交换区,轮流使用。
另外对扇区的连续写进行了优化,当连续写扇区时,就不必每次重复上面的操作,只有当地址跨块时,才需要重新擦除。
连续写扇区的实现原理如下:当检测到扇区地址跨块时,就把原来的整块数据复制到交换块中,然后将该块内当前所写地址的前面部分页面复制到原来的块中,接着就从交换块中取出当前扇区地址所在页(使用页复制-随机写入命令),再把一个扇区的数据写入,并接着写入其他扇区,当扇区地址跨页时,就把该页写入到原来的块中,直到扇区被写完(当然如果写的过程中跨块了,还需要重复前面的块擦除以及复制过程)。
接着把交换块中剩余的页再复制回原来的块中,这样一个连续写过程就完成了。