您的位置 首页 软件

STM32 USB Mass Storage 例程调试笔记

一、问题起因近来有几个客户反映STM3210E的开发板的USBMassStorage例程有点问题,组长安排我来调试。MassStorage例程在PC上实现…

一、问题原因

近来有几个客户反映STM3210E的开发板的USB Mass Storage 例程有点问题,组长组织我来调试。Mass Storage例程在PC上完结两个U盘,一个是SD盘,一个是NAND Flash盘,把程序下载到开发板后,PC上能够检测到NAND Flash盘和SD盘,却提示磁盘要格局化,依照提示操作,格局化不成功,可用磁盘空间和已用磁盘空间都为0。

调试前的预备

二、调试前预备

  调试之前花了三天的时刻,大致的看了一下USB的结构,后来才发现,没什么必要,不过多学点常识总是好的。

1.USB只供给一个数据通道,USB总线并不知道设备详细是怎样操作,有什么状况,USB设备的状况是设备自己来决议的,这便是USB描绘符的功用了。描绘符中记录了设备的类型、厂商、产品ID、端点信息等。描绘符首要要:设备描绘符、接口描绘符、端点描绘符、字符串描绘符等。设备描绘符记录了该设备运用的USB版本号、厂商ID、产品ID、或许的装备数等与设备相关的信息;装备描绘符记录了装备包含的接口数、供电方法、是否支撑长途唤醒等;接口描绘符记录了接口的端点数、接口运用的类、协议等;端点描绘符记录了端点号、数据传输的方向、传输类型、最大包长度等;字符串描绘符记录了一些文字信息,便利客户了解。

USB协议中规则了四种传输类型:批量传输、同步传输、中止传输和操控传输

MassStorage例程中只用到了批量传输和操控传输,所以这儿只介绍这两种方法

(1)批量传输运用bulk transaction传输数据,首要应用在数据很多数据传输和承受数据上一起又没有带宽和间隔时刻要求的状况下。特色:要求确保传输。打印机、大容量存储设备和扫描仪归于这种类型这种类型的设备。适合于传输十分慢和很多被推迟的传输,能够比及一切其它类型的数据的传输完结之后再传输和接纳数据。

一次批量事物有三个阶段:令牌包阶段、数据包阶段和握手包阶段。

第一阶段 令牌包阶段
Host端宣布一个Bulk的令牌恳求、令牌包中包含了设备地址、端点号。
假如令牌是IN恳求 ,则是从Device到Host的恳求;
假如令牌是OUT恳求,则是从Host到Device端的恳求。
第二阶段 数据包阶段
依据从前恳求的令牌的类型,数据传输有或许是IN方向,也有或许是OUT方向。传输数据的时分用DATA0和DATA1令牌带着着数据替换传送。
数据传输格局DATA1和DATA0,这两个是重复数据,确保在1数据丢掉时0能够补上,不至于数据丢掉。
第三阶段 握手包阶段
假如数据是IN 方向,握手信号应该是Host端宣布;
假如数据是OUT方向,握手信号应该是Device端宣布。
握手信号能够为ACK, 一共正常呼应,
NAK, 一共没有正确传送。
STALL,一共呈现主机不行预知的过错。

(2)操控传输

  效果:USB体系用来首要进行查询装备和给USB设备发送通用的指令,它要确保数据传输进程的数据完整性。设备枚举进程中的各种设备描绘符的获取以及设置地址、设置装备都是经过操控传输来完结的。特色:操控传输是双向传输,数据量一般较小;数据传送是无损性的。
操控传输也分为三个阶段,即令牌阶段、数据传送阶段、握手阶段

2.USB协议中规则了一类大容量存储设备 mass storage device,包含u盘、移动硬盘等。大容量存储设备接口类代码(bInterfaceClass)为0x08,U盘接口子类代码(bInterfaceSubClass)运用0x06,一共运用SCSI通明指令集.协议代码(bInterfaceProtocol)有三种:0x01、0x00和0x50,前面两种需求运用中止传输,这儿运用的是终究一种协议,即协议运用仅批量传输(bulk only transport)。

  仅批量传输协议中规则了两个特别的类恳求:bulk-only Mass Storage Reset 和Get Max LUN,前者是复位到指令状况的恳求,后者是获取最大逻辑单元的恳求。
1.Get Max LUN的格局如下图

usb协议中选用的是小端格局,这一点要分外留意,比方ASCII 0x55、0x53,用小端格局一共便是0x5355

bmRequestType为0xa1,一共它是发送到接口的类输入恳求,bRequest为0xfe,wIndex为恳求的接标语,传输的数据长度为1字节,设备将在数据进程回来1字节的数据,一共设备有多少个逻辑单元,0一共1个逻辑单元,1一共有两个。

  2.bulk-only Mass Storage Reset 的格局如下图

bulk-only Mass Storage Reset恳求是告诉设备接下来的批量端点输出数据为指令快封装包CBW(Command Block Wrapper),在这个恳求中,仅需求设置一下状况,阐明接下来的数据是CBW,然后回来一个长度为0的状况数据包。

  3.仅批量传输的的数据流

  类恳求完结后,就进入了数据传输进程,在仅批量数据传输协议中规则,数据传输分为三个阶段:指令阶段、数据阶段和状况阶段。指令阶段是由主机经过批量端点发送一个CBW(指令封装包)的结构,在CBW中界说了要操作的指令以及传输数据的方向和数量,数据阶段的传输方向由指令阶段决议,而状况阶段则总是由设备回来该指令完结的状况。

CBW的结构如下图

官方文档对这些字段的介绍:

dCBWSignature:
Signature that helps identify this data packet as a CBW. The signature field shall contain the value
43425355h (little endian), indicating a CBW.
dCBWTag:
A Command Block Tag sent by the host. The device shall echo the contents of this field back to the
host in the dCSWTag field of the associated CSW. The dCSWTag positively associates a CSW with thecorresponding CBW.
dCBWDataTransferLength:
The number of bytes of data that the host expects to transfer on the Bulk-In or Bulk-Out endpoint (asindicated by the Direction bit) during the execution of this command. If this field is zero, the device andthe host shall transfer no data between the CBW and the associated CSW, and the device shall ignore
bmCBWFlags:
The bits of this field are defined as follows:
Bit 7 Direction – the device shall ignore this bit if the dCBWDataTransferLength field is
zero, otherwise:
0 = Data-Out from host to the device,
1 = Data-In from the device to the host.
Bit 6 Obsolete. The host shall set this bit to zero.
Bits 5..0 Reserved – the host shall set these bits to zero.
bCBWLUN:
The device Logical Unit Number (LUN) to which the command block is being sent. For devices that
support multiple LUNs, the host shall place into this field the LUN to which this command block is
addressed. Otherwise, the host shall set this field to zero.
bCBWCBLength:
The valid length of the CBWCB in bytes. This defines the valid length of the command block. The
only legal values are 1 through 16 (01h through 10h). All other values are reserved.
CBWCB:
The command block to be executed by the device. The device shall interpret the first bCBWCBLength
bytes in this field as a command block as defined by the command set identified by bInterfaceSubClass .
If the command set supported by the device uses command blocks of fewer than 16 (10h) bytes in
length, the significant bytes shall be transferred first, beginning with the byte at offset 15 (Fh). The
device shall ignore the content of the CBWCB field past the byte at offset (15 + bCBWCBLength – 1).

  指令封装包CSW

dCSWSignature:
Signature that helps identify this data packet as a CSW. The signature field shall contain the value
53425355h (little endian), indicating CSW.
dCSWTag:
The device shall set this field to the value received in the dCBWTag of the associated CBW.
bCSWStatus:
bCSWStatus indicates the success or failure of the command. The device shall set this byte to zero if
the command completed successfully. A non-zero value shall indicate a failure during command
execution according to the following table:
Value Description
00h Command Passed (“good status”)
01h Command Failed
02h Phase Error
03h and 04h Reserved (Obsolete)
05h to FFh Reserved

  界说一个缓冲区用来接纳指令块封装包CBW,然后进入到数据处理阶段,在数据处理中,对CBW进行解码,回来或许接纳呼应的数据。数据发送或许接纳完毕后,进入到状况阶段,回来指令碑文的状况,然后再次进入指令阶段,等候主机发送CBW包。

3.SCSI指令集

小型计算机体系接口(英语:Small Computer System Interface; 简写:SCSI),一种用于计算机和智能设备之间(硬盘、软驱、光驱、打印机、扫描仪等)体系级接口的独立处理器标准。 SCSI是一种智能的通用接口标准。它是各种计算机与外部设备之间的接口标准。

在U盘中经常用到的指令有:INQUIRY、READ CAPACITY 、READ(10)、WRITE(10)指令等。

INQUIRY指令恳求查询方针设备的一些基本信息,操作码为0x12,。

READ FORMAT CAPACITIES指令能够让主机读取设备各种或许的格局化容量的列表,假如设备中没有存储设备,则设备回来最大能够支撑的格局化容量。

读容量指令READ CAPACITY能够让主机读取到当时存储前言的容量,操作代码为0x25,READ CAPACITY读取的是实践的磁盘容量。

主机运用READ(10)指令来读取实践磁盘的数据,运用WRITE(10)交游设备中写入实践的磁盘数据。

4.STM32 相关常识

  STM32供给的有USB全速设备接口,支撑USB全速总线、USB挂起/康复操作,能够中止设备时钟完结低功耗。USB和CAN共用一个专用的512字节的SRAM存储器用于数据的发送和接纳,不能一起运用USB和CAN总线。

PC主机和微操控器之间的数据传输是经过同享这一专用的数据缓冲区来完结的,数据缓冲区能被USB外设直接拜访。这块专用数据缓冲区的巨细由所运用的端点数目和每个端点最大的数据分组巨细所决议,每个端点最大可运用512 字节缓冲区,最多可用于16个单向或8 个双向端点。USB模块同PC主机通讯,依据USB标准完结令牌分组的检测,数据发送/ 接纳的处理,和握手分组的处理。整个传输的格局由硬件完结,其间包含CRC的生成和校验。每个端点都有一个缓冲区描绘块,描绘该端点运用的缓冲区地址、巨细和需求传输的字节数。 当USB模块辨认出一个有用的功用/ 端点的令牌分组时,( 假如需求传输数据并且端点已装备) 随之产生相关的数据传输。USB模块经过一个内部的16位寄存器完结端口与专用缓冲区的数据交换。在一切的数据传输完结后,假如需求,则依据传输的方向,发送或接纳恰当的握手分组。在数据传输完毕时,USB模块将触发与端点相关的中止,经过读状况寄存器和/ 或许运用不同的中止处理程序,微操控器能够确认

● 哪个端点需求得到服务

● 产生如位填充、格局、CRC、协议、缺失ACK、缓冲区溢出/ 缓冲区未满等过错时,正在进行的是哪种类型的传输。

USB模块对同步传输和高吞吐量的批量传输供给了特别的双缓冲区机制,在微操控器运用一个缓冲区的时分,该机制确保了USB外设总是能够运用另一个缓冲区。在任何不需求运用USB模块的时分,经过写操控寄存器总能够使USB模块置于低功耗形式(SUSPEND形式) 。在这种形式下,不产生任何静态电流耗费,一起USB时钟也会减慢或中止。经过对USB线上数据传输的检测,能够在低功耗形式下唤醒USB模块。也能够将一特定的中止输入源直接连接到唤醒引脚上,以使体系能当即康复正常的时钟体系,并支撑直接发动或中止时钟体系。

三、例程剖析

  1.首要进行体系装备,如时钟、USB、NAND FLASH、SD卡的初始化等

2.装备中止,本例程中运用了三个中止通道

  USB低优先级中止(通道20):可由一切USB事情触发(正确传输,USB复位等)。固件在处理中止前应当首要确认中止源。中止处理函数为:USB_Istr,进入中止处理函数后会进行usb复位操作或许usb数据传输(调用CTR_LP函数)。

  USB高优先级中止(通道19):仅能由同步和双缓冲批量传输的正确传输事情触发,意图是确保最大的传输速率。它的中止处理函数是CTR_HP。

  阐明:函数CTR_HP和CTR_LP终究都会调用Mass_Storage_In(端点1)和Mass_Storage_Out(端点2)两个函数来和PC端的USB HOST 通讯

3.SD的I/O 中止(通道49)

  为了让SD I/O卡能够中止多媒体卡/SD 模块,在SD接口上有一个具有中止功用的引脚——第8脚,在4 位SD形式下这个脚是SDIO_D1,卡用它向多媒体卡/SD 模块提出中止恳求。关于每一个卡或卡内的功用,中止功用是可选的。SD I/O的中止是电平有用,即在被辨认并得到多媒体卡/SD 模块的呼应之前,中止信号线有必要坚持有用电平( 低) ,在中止进程完毕后坚持无效电平(高)。在多媒体卡/SD 模块服务了中止恳求后,经过一个I/O 写操作,写入恰当的位到SD I/O卡的内部寄存器,即可铲除中止状况位。一切SD I/O卡的中止输出是低电平有用,多媒体卡/SD 模块在一切数据线(SDIO/D[3:0])上供给上拉电阻。多媒体卡/SD 模块在中止阶段对第8 脚(SDIO_D/IRQ) 采样并进行中止检测,其它时刻该信号线上的数值将被疏忽。

  4.进入while循环,等候中止的产生

当USB主机检测到USB设备刺进后,进入中止,先对设备进行复位,USB在复位后其地址为0,主机经过地址0和刚刺进的设备通讯,树立操控传输,将设备描绘符发送给主机。复位的操作在MASS_Reset()函数中。

主机对设备又一次复位,这时就进入了设置地址阶段,这也是一个操控传输的进程,主机会分配一个仅有的地址给刚接入的设备。

主机再次获取设备描绘符。

主机获取装备描绘符,主机获取字符串描绘符。

主机发送Get Max LUN恳求,获取最大逻辑单元。

主机经过批量端点发送CBW包,在CBW中界说了要操作的指令以及传输数据的方向和数量,回来该指令完结的状况,即由设备回来CSW包,端点2用于输出,端点1用于输入数据至主机。CBW的标志是0x55,0x53,0x42,0x43。

在USB主机和设备的通讯进程中,数据会先被放到一个巨细为512字节的专用SRAM缓冲区晒干,然后再传输到主机或许USB设备。

USB主机经过发送 SCSI Read10 Command和SCSI Write10 Command指令来对从机进行读写,别离调用的是SCSI_Read10_Cmd和SCSI_Write10_Cmd函数,终究调用MAL_Read和MAL_Write,在这两个函数中判别是对SD卡仍是NANDFLASH进行读写。详细的进程能够参阅代码。

四、例程问题现象和解决方法

1.NAND FLASH盘能够被辨认,格局化失利。已然NAND FLASH盘能够被辨认,那就标明USB的操控传输没呈现问题,USB批量传输出问题了,并且最或许的是NAND FLASH的驱动有问题,细心看完代码,发现在树立坏块表,对Spare 区域进行读操作中,对NAND FLASH 有一个NAND_CMD_AREA_TRUE1指令操作,检查代码,

#define NAND_CMD_AREA_TRUE1 ((u8)0x30)

而30H这个指令在数据手册中找不到,在程序中把这行注释掉,编译代码,下载,仍是无法格局化,终究研讨了一下手册,在注释代码的这一行加上5微秒的推迟,然后编译,下载,NAND FLASH可移动磁盘能够正常的读写了。

2.SD盘也能被辨认,不能格局化。开端用的是2G的SD卡,后来测验1G和512M的,它们都能用,也便是说,这个SD卡驱动只辨认1G和512M的SD卡。

在代码中增加调试信息,结果是写入的块长度犯错。经过对读SD卡信息了解到,2G的SD卡,块巨细是1024字节,其它的卡都是512字节。我在SDIO例程中设置块巨细为1024字节,读写犯错,设置512字节,居然是正确的。

USB MassStorage例程中是首要从SD卡中读取SD卡块巨细的值,依照这个值来读写SD卡,而实践上2G的SD卡只能依照512字节来读写。所以在读取块巨细的值后,把块的巨细除以2,块数目乘以2,卡的总容量不变,程序运转后,一切正常了。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qianrushi/ruanjian/264791.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部