STM32 USB Mass Storage 例程调试笔记

发布者:bln898最新更新时间:2016-04-25 来源: eefocus关键字:STM32  USB  Mass  Storage  调试笔记 手机看文章 扫描二维码
随时随地手机看文章
一、问题起因

     近来有几个客户反映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 the corresponding CBW.
dCBWDataTransferLength:
The number of bytes of data that the host expects to transfer on the Bulk-In or Bulk-Out endpoint (as indicated by the Direction bit) during the execution of this command. If this field is zero, the device and the 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,卡的总容量不变,程序运行后,一切正常了。

关键字:STM32  USB  Mass  Storage  调试笔记 引用地址:STM32 USB Mass Storage 例程调试笔记

上一篇:在ARM上安装minicom及“error: conflicting types for 'getline'”解决
下一篇:STM32 ADC时钟配置

推荐阅读最新更新时间:2024-03-16 14:51

基于STM32的多通道锂电池充放电测试系统
本文设计了一个拥有多通道的锂电池充放电测试系统,以STM32F429为主控芯片,配合双量程的电流采集、充放电控制、双探测器的温度检测以及电压检测等电路,实现了同时对多个串联动力锂电池组的充放电测试及保护。在测试过程中,通过上位机程序,可对多个锂电池组的充放电测试过程进行监视,并将锂电池充放电测试数据实时显示。 1、系统的硬件设计 本系统采用STMicroelectronics公司所生产的高性能、低功耗、高性价比的STM32F429作为整个系统的核心控制器,通过SPI(serialperipheralin-terface)总线以及SMBus(systemmanagementbus)总线分别与电流、温度、电压检测模块通信,通过普通
[单片机]
基于<font color='red'>STM32</font>的多通道锂电池充放电测试系统
STM32数模转换器(DAC)简析
STM32F4xx系列提供的DAC模块是12 位电压输出数模转换器。DAC可以按 8 位或 12 位模式进行配置,并且可与DMA控制器配合使用。在 12 位模式下,数据可以采用左对齐或右对齐。DAC有两个输出通道,每个通道各有一个转换器。在DAC双通道模式下,每个通道可以单独进行转换;当两个通道组合在一起同步执行更新操作时,也可以同时进行转换。可通过一个输入参考电压引脚VREF+(与ADC共享)来提高分辨率。 DAC通道框图 DAC引脚 DAC通道使能 将 DAC_CR 寄存器中的相应 ENx 位置 1,即可接通对应 DAC 通道。经过一段启动时间tWAKEUP 后,DAC 通道被真正使能。 注意:ENx 位只会使能模
[单片机]
<font color='red'>STM32</font>数模转换器(DAC)简析
采用3mm x 4mm 紧凑封装的高效率USB电源管理器和电池充电器
2007 年 4 月 10 日 - 北京 - 凌力尔特公司( Linear Technology Corporation )推出独立型高效率电源管理器、理想二极管控制器和电池充电器 LTC4088 ,该器件用于便携式 USB 装置。 LTC4088 的前端开关拓扑具有 PowerPath TM 控制,这优化了通过 USB 端口获得电源以对电池充电,并以最低功耗为应用装置供电。这个特点有助于减轻空间受限的媒体播放器、数码相机、 PDA 、 GPS 单元和智能电话的热量管理问题。该集成电路还允许负载电流大于从 USB 端口吸取的电流,
[新品]
基于CH371的USB接口虚拟示波器设计
作者Email: violit@netease.com 摘要:本文介绍一款USB接口的虚拟示波器的设计方案,重点介绍了USB总线接口芯片CH371的原理及应用,降低了USB系统开发的门槛,并达到令人满意的效果。 关键词:USB接口,虚拟示波器,CH371,高速数据采集 一、引言 对于学校教学实验以及某些特定需求来说,目前市场上的模拟及数字示波器也许并不适用,价格高昂、体积较大且很多专业功能并不实用。而现在电脑的普及程度也达到了相当的规模,利用电脑以及附加的数采模块实现一个灵活便捷的虚拟示波器能够满足大多数的工作、学习和开发需要,并且可以通过较低代价的硬件和软件升级实现相当复杂的信号处理功能,能够以较低的成本、较
[应用]
一款基于STM32的便携式二氧化碳监测仪设计
CO2浓度的检测方法大致分化学方法和物理方法。CO2浓度检测方法有滴定法、热催化法、气敏法、电化学法,这些属于化学方法,这些方法普遍存在价格贵,普适性差等问题,且测量精度较低。而物理的方法有超声波法、气相色谱法以及众多借助于光学来实现检测的方法。也有像光声光谱法这种化学和物理结合的方法。吸收光谱法的依据是不同化学结构的气体分子对不同波长的辐射的吸收程度不同,CO2气体分子对特定波长的红外光有强烈的吸收。   目前各种检测用的CO2传感器主要有固体电解质式、钛酸钡复合氧化物电容式、电导变化型厚膜式等,这些传感器存在对气体的选择性差、易出现误报、需要频繁校准、使用寿命较短等不足。而红外吸收型CO2传感器具有测量范围宽、灵敏度高、响应
[医疗电子]
一款基于<font color='red'>STM32</font>的便携式二氧化碳监测仪设计
STM32中DMA模块的使用
DMA(Direct Memory Access)常译为“存储器直接存取”。早在Intel的8086平台上就有了DMA应用了。 一个完整的微控制器通常由CPU、存储器和外设等组件构成。这些组件一般在结构和功能上都是独立的,而各个组件的协调和交互就由CPU完成。如此一来,CPU作为整个芯片的核心,其处理的工作量是很大的。如果CPU先从A外设拿到一个数据送给B外设使用,同时C外设又需要D外设提供一个数据。。。这样的数据搬运工作将使CPU的负荷显得相当繁重。 严格的说,搬运数据只是CPU的比较不重要的一种工作。CPU最重要的工作室进行数据运算,从加减乘除到一些高级的运算,包括浮点、积分、微分、FFT等。CPU还需要负责复杂的中断
[单片机]
<font color='red'>STM32</font>中DMA模块的使用
完成stm32 上HID的应用
这个是公司的项目,以前基于usb的虚拟串口来做上下位机通信,由于usb平时也就刷参数和调试之用,也不很常用,外面反应usb有时会连不上stm32控制器,心里一直认为不是大问题,后来反应的多了,就重视这个事情了,虽然usb平时不用,但是用的时候只要出现异常掉线,就再也连不上去了,特别影响用户对我们产品的信心。 在网上找了很多资料,到现在也只能隐约确定是stm32官方的虚拟串口库有问题,我发现不同的电源板都会影响到usb虚拟串口的枚举,于是下定决心使用其他方式来做上下位机的连接,排除了usb虚拟串口,眼前的选择只有两个 1)usblib,这个是针对usb的上位机库,可以玩很多的花样,但是需要开发者稍稍熟悉usb协议,而且这个需要在
[单片机]
USB-OTG总线端口ESD保护阵列[Vishay]
    宾夕法尼亚、MALVERN — 2011 年 1 月 25 日 — 日前,Vishay Intertechnology, Inc.(NYSE 股市代号:VSH)宣布,推出具有低电容和低泄漏电流的新款ESD保护阵列---VBUS053CZ-HAF,能够保护USB-OTG端口免受瞬态电压信号的影响。在5.5V的工作范围内,新的VBUS053CZ-HAF可为3条线路提供USB ESD保护,在28V工作范围内对一条VBUS线路提供保护。     VBUS053CZ-HAF采用无引线LLP75-7L封装,0.6mm的超低厚度减小了在高速数据实现主动式ESD保护所需的电路板空间,例如USB 2.0和HDTV中的HDMI,以及
[电源管理]
<font color='red'>USB</font>-OTG总线端口ESD保护阵列[Vishay]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved