<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > STM32 USB Mass Storage 例程調試筆記

STM32 USB Mass Storage 例程調試筆記

作者: 時(shí)間:2016-11-20 來(lái)源:網(wǎng)絡(luò ) 收藏
一、問(wèn)題起因

近來(lái)有幾個(gè)客戶(hù)反映STM3210E的開(kāi)發(fā)板的USB Mass Storage 例程有點(diǎn)問(wèn)題,組長(cháng)安排我來(lái)調試。Mass Storage例程在PC上實(shí)現兩個(gè)U盤(pán),一個(gè)是SD盤(pán),一個(gè)是NAND Flash盤(pán),把程序下載到開(kāi)發(fā)板后,PC上能夠檢測到NAND Flash盤(pán)和SD盤(pán),卻提示磁盤(pán)要格式化,按照提示操作,格式化不成功,可用磁盤(pán)空間和已用磁盤(pán)空間都為0。

本文引用地址:http://dyxdggzs.com/article/201611/319070.htm

調試前的準備

二、調試前準備

  調試之前花了三天的時(shí)間,大致的看了一下USB的框架,后來(lái)才發(fā)現,沒(méi)什么必要,不過(guò)多學(xué)點(diǎn)知識總是好的。

1.USB只提供一個(gè)數據通道,USB總線(xiàn)并不知道設備具體是怎么操作,有什么狀態(tài),USB設備的狀態(tài)是設備自己來(lái)決定的,這就是USB描述符的功能了。描述符中記錄了設備的類(lèi)型、廠(chǎng)商、產(chǎn)品ID、端點(diǎn)信息等。描述符主要要:設備描述符、接口描述符、端點(diǎn)描述符、字符串描述符等。設備描述符記錄了該設備使用的USB版本號、廠(chǎng)商ID、產(chǎn)品ID、可能的配置數等與設備相關(guān)的信息;配置描述符記錄了配置包含的接口數、供電方式、是否支持遠程喚醒等;接口描述符記錄了接口的端點(diǎn)數、接口使用的類(lèi)、協(xié)議等;端點(diǎn)描述符記錄了端點(diǎn)號、數據傳輸的方向、傳輸類(lèi)型、最大包長(cháng)度等;字符串描述符記錄了一些文字信息,方便客戶(hù)理解。

USB協(xié)議中規定了四種傳輸類(lèi)型:批量傳輸、同步傳輸、中斷傳輸和控制傳輸

MassStorage例程中只用到了批量傳輸和控制傳輸,所以這里只介紹這兩種方式

(1)批量傳輸使用bulk transaction傳輸數據,主要應用在數據大量數據傳輸和接受數據上同時(shí)又沒(méi)有帶寬和間隔時(shí)間要求的情況下。特點(diǎn):要求保證傳輸。打印機、大容量存儲設備和掃描儀屬于這種類(lèi)型這種類(lèi)型的設備。適合于傳輸非常慢和大量被延遲的傳輸,可以等到所有其它類(lèi)型的數據的傳輸完成之后再傳輸和接收數據。

一次批量事物有三個(gè)階段:令牌包階段、數據包階段和握手包階段。

第一階段 令牌包階段
Host端發(fā)出一個(gè)Bulk的令牌請求、令牌包中包含了設備地址、端點(diǎn)號。
如果令牌是IN請求 ,則是從Device到Host的請求;
如果令牌是OUT請求,則是從Host到Device端的請求。
第二階段 數據包階段
根據先前請求的令牌的類(lèi)型,數據傳輸有可能是IN方向,也有可能是OUT方向。傳輸數據的時(shí)候用DATA0和DATA1令牌攜帶著(zhù)數據交替傳送。
數據傳輸格式DATA1和DATA0,這兩個(gè)是重復數據,確保在1數據丟失時(shí)0可以補上,不至于數據丟失。
第三階段 握手包階段
如果數據是IN 方向,握手信號應該是Host端發(fā)出;
如果數據是OUT方向,握手信號應該是Device端發(fā)出。
握手信號可以為ACK, 表示正常響應,
NAK, 表示沒(méi)有正確傳送。
STALL,表示出現主機不可預知的錯誤。

(2)控制傳輸

  作用:USB系統用來(lái)主要進(jìn)行查詢(xún)配置和給USB設備發(fā)送通用的命令,它要保證數據傳輸過(guò)程的數據完整性。設備枚舉過(guò)程中的各種設備描述符的獲取以及設置地址、設置配置都是通過(guò)控制傳輸來(lái)實(shí)現的。特點(diǎn):控制傳輸是雙向傳輸,數據量通常較??;數據傳送是無(wú)損性的。
控制傳輸也分為三個(gè)階段,即令牌階段、數據傳送階段、握手階段

2.USB協(xié)議中規定了一類(lèi)大容量存儲設備 mass storage device,包括u盤(pán)、移動(dòng)硬盤(pán)等。大容量存儲設備接口類(lèi)代碼(bInterfaceClass)為0x08,U盤(pán)接口子類(lèi)代碼(bInterfaceSubClass)使用0x06,表示使用SCSI透明指令集.協(xié)議代碼(bInterfaceProtocol)有三種:0x01、0x00和0x50,前面兩種需要使用中斷傳輸,這里使用的是最后一種協(xié)議,即協(xié)議使用僅批量傳輸(bulk only transport)。

  僅批量傳輸協(xié)議中規定了兩個(gè)特殊的類(lèi)請求:bulk-only Mass Storage Reset 和Get Max LUN,前者是復位到命令狀態(tài)的請求,后者是獲取最大邏輯單元的請求。
1.Get Max LUN的格式如下圖

usb協(xié)議中采用的是小端格式,這一點(diǎn)要格外注意,比如ASCII 0x55、0x53,用小端格式表示就是0x5355

bmRequestType為0xa1,表示它是發(fā)送到接口的類(lèi)輸入請求,bRequest為0xfe,wIndex為請求的接口號,傳輸的數據長(cháng)度為1字節,設備將在數據過(guò)程返回1字節的數據,表示設備有多少個(gè)邏輯單元,0表示1個(gè)邏輯單元,1表示有兩個(gè)。

  2.bulk-only Mass Storage Reset 的格式如下圖

bulk-only Mass Storage Reset請求是通知設備接下來(lái)的批量端點(diǎn)輸出數據為命令快封裝包CBW(Command Block Wrapper),在這個(gè)請求中,僅需要設置一下?tīng)顟B(tài),說(shuō)明接下來(lái)的數據是CBW,然后返回一個(gè)長(cháng)度為0的狀態(tài)數據包。

  3.僅批量傳輸的的數據流

  類(lèi)請求完成后,就進(jìn)入了數據傳輸過(guò)程,在僅批量數據傳輸協(xié)議中規定,數據傳輸分為三個(gè)階段:命令階段、數據階段和狀態(tài)階段。命令階段是由主機通過(guò)批量端點(diǎn)發(fā)送一個(gè)CBW(命令封裝包)的結構,在CBW中定義了要操作的命令以及傳輸數據的方向和數量,數據階段的傳輸方向由命令階段決定,而狀態(tài)階段則總是由設備返回該命令完成的狀態(tài)。

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

  定義一個(gè)緩沖區用來(lái)接收命令塊封裝包CBW,然后進(jìn)入到數據處理階段,在數據處理中,對CBW進(jìn)行解碼,返回或者接收響應的數據。數據發(fā)送或者接收完畢后,進(jìn)入到狀態(tài)階段,返回命令執行的情況,然后再次進(jìn)入命令階段,等待主機發(fā)送CBW包。

3.SCSI命令集

小型計算機系統接口(英語(yǔ):Small Computer System Interface; 簡(jiǎn)寫(xiě):SCSI),一種用于計算機和智能設備之間(硬盤(pán)、軟驅、光驅、打印機、掃描儀等)系統級接口的獨立處理器標準。 SCSI是一種智能的通用接口標準。它是各種計算機與外部設備之間的接口標準。

在U盤(pán)中經(jīng)常用到的命令有:INQUIRY、READ CAPACITY 、READ(10)、WRITE(10)命令等。

INQUIRY命令請求查詢(xún)目標設備的一些基本信息,操作碼為0x12,。

READ FORMAT CAPACITIES命令可以讓主機讀取設備各種可能的格式化容量的列表,如果設備中沒(méi)有存儲設備,則設備返回最大能夠支持的格式化容量。

讀容量命令READ CAPACITY可以讓主機讀取到當前存儲媒介的容量,操作代碼為0x25,READ CAPACITY讀取的是實(shí)際的磁盤(pán)容量。

主機使用READ(10)命令來(lái)讀取實(shí)際磁盤(pán)的數據,使用WRITE(10)來(lái)往設備中寫(xiě)入實(shí)際的磁盤(pán)數據。

4.STM32 相關(guān)知識

  STM32提供的有USB全速設備接口,支持USB全速總線(xiàn)、USB掛起/恢復操作,可以停止設備時(shí)鐘實(shí)現低功耗。USB和CAN共用一個(gè)專(zhuān)用的512字節的SRAM存儲器用于數據的發(fā)送和接收,不能同時(shí)使用USB和CAN總線(xiàn)。

PC主機和微控制器之間的數據傳輸是通過(guò)共享這一專(zhuān)用的數據緩沖區來(lái)完成的,數據緩沖區能被USB外設直接訪(fǎng)問(wèn)。這塊專(zhuān)用數據緩沖區的大小由所使用的端點(diǎn)數目和每個(gè)端點(diǎn)最大的數據分組大小所決定,每個(gè)端點(diǎn)最大可使用512 字節緩沖區,最多可用于16個(gè)單向或8 個(gè)雙向端點(diǎn)。USB模塊同PC主機通信,根據USB規范實(shí)現令牌分組的檢測,數據發(fā)送/ 接收的處理,和握手分組的處理。整個(gè)傳輸的格式由硬件完成,其中包括CRC的生成和校驗。每個(gè)端點(diǎn)都有一個(gè)緩沖區描述塊,描述該端點(diǎn)使用的緩沖區地址、大小和需要傳輸的字節數。 當USB模塊識別出一個(gè)有效的功能/ 端點(diǎn)的令牌分組時(shí),( 如果需要傳輸數據并且端點(diǎn)已配置) 隨之發(fā)生相關(guān)的數據傳輸。USB模塊通過(guò)一個(gè)內部的16位寄存器實(shí)現端口與專(zhuān)用緩沖區的數據交換。在所有的數據傳輸完成后,如果需要,則根據傳輸的方向,發(fā)送或接收適當的握手分組。在數據傳輸結束時(shí),USB模塊將觸發(fā)與端點(diǎn)相關(guān)的中斷,通過(guò)讀狀態(tài)寄存器和/ 或者利用不同的中斷處理程序,微控制器可以確定

● 哪個(gè)端點(diǎn)需要得到服務(wù)

● 產(chǎn)生如位填充、格式、CRC、協(xié)議、缺失ACK、緩沖區溢出/ 緩沖區未滿(mǎn)等錯誤時(shí),正在進(jìn)行的是哪種類(lèi)型的傳輸。

USB模塊對同步傳輸和高吞吐量的批量傳輸提供了特殊的雙緩沖區機制,在微控制器使用一個(gè)緩沖區的時(shí)候,該機制保證了USB外設總是可以使用另一個(gè)緩沖區。在任何不需要使用USB模塊的時(shí)候,通過(guò)寫(xiě)控制寄存器總可以使USB模塊置于低功耗模式(SUSPEND模式) 。在這種模式下,不產(chǎn)生任何靜態(tài)電流消耗,同時(shí)USB時(shí)鐘也會(huì )減慢或停止。通過(guò)對USB線(xiàn)上數據傳輸的檢測,可以在低功耗模式下喚醒USB模塊。也可以將一特定的中斷輸入源直接連接到喚醒引腳上,以使系統能立即恢復正常的時(shí)鐘系統,并支持直接啟動(dòng)或停止時(shí)鐘系統。

三、例程分析

  1.首先進(jìn)行系統配置,如時(shí)鐘、USB、NAND FLASH、SD卡的初始化等

2.配置中斷,本例程中使用了三個(gè)中斷通道

  USB低優(yōu)先級中斷(通道20):可由所有USB事件觸發(fā)(正確傳輸,USB復位等)。固件在處理中斷前應當首先確定中斷源。中斷處理函數為:USB_Istr,進(jìn)入中斷處理函數后會(huì )進(jìn)行usb復位操作或者usb數據傳輸(調用CTR_LP函數)。

  USB高優(yōu)先級中斷(通道19):僅能由同步和雙緩沖批量傳輸的正確傳輸事件觸發(fā),目的是保證最大的傳輸速率。它的中斷處理函數是CTR_HP。

  說(shuō)明:函數CTR_HP和CTR_LP最終都會(huì )調用Mass_Storage_In(端點(diǎn)1)和Mass_Storage_Out(端點(diǎn)2)兩個(gè)函數來(lái)和PC端的USB HOST 通信

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

  為了讓SD I/O卡能夠中斷多媒體卡/SD 模塊,在SD接口上有一個(gè)具有中斷功能的引腳——第8腳,在4 位SD模式下這個(gè)腳是SDIO_D1,卡用它向多媒體卡/SD 模塊提出中斷申請。對于每一個(gè)卡或卡內的功能,中斷功能是可選的。SD I/O的中斷是電平有效,即在被識別并得到多媒體卡/SD 模塊的響應之前,中斷信號線(xiàn)必須保持有效電平( 低) ,在中斷過(guò)程結束后保持無(wú)效電平(高)。在多媒體卡/SD 模塊服務(wù)了中斷請求后,通過(guò)一個(gè)I/O 寫(xiě)操作,寫(xiě)入適當的位到SD I/O卡的內部寄存器,即可清除中斷狀態(tài)位。所有SD I/O卡的中斷輸出是低電平有效,多媒體卡/SD 模塊在所有數據線(xiàn)(SDIO/D[3:0])上提供上拉電阻。多媒體卡/SD 模塊在中斷階段對第8 腳(SDIO_D/IRQ) 采樣并進(jìn)行中斷檢測,其它時(shí)間該信號線(xiàn)上的數值將被忽略。

  4.進(jìn)入while循環(huán),等待中斷的發(fā)生

當USB主機檢測到USB設備插入后,進(jìn)入中斷,先對設備進(jìn)行復位,USB在復位后其地址為0,主機通過(guò)地址0和剛插入的設備通信,建立控制傳輸,將設備描述符發(fā)送給主機。復位的操作在MASS_Reset()函數中。

主機對設備又一次復位,這時(shí)就進(jìn)入了設置地址階段,這也是一個(gè)控制傳輸的過(guò)程,主機會(huì )分配一個(gè)唯一的地址給剛接入的設備。

主機再次獲取設備描述符。

主機獲取配置描述符,主機獲取字符串描述符。

主機發(fā)送Get Max LUN請求,獲取最大邏輯單元。

主機通過(guò)批量端點(diǎn)發(fā)送CBW包,在CBW中定義了要操作的命令以及傳輸數據的方向和數量,返回該命令完成的狀態(tài),即由設備返回CSW包,端點(diǎn)2用于輸出,端點(diǎn)1用于輸入數據至主機。CBW的標志是0x55,0x53,0x42,0x43。

在USB主機和設備的通信過(guò)程中,數據會(huì )先被放到一個(gè)大小為512字節的專(zhuān)用SRAM緩沖區里面,然后再傳輸到主機或者USB設備。

USB主機通過(guò)發(fā)送 SCSI Read10 Command和SCSI Write10 Command命令來(lái)對從機進(jìn)行讀寫(xiě),分別調用的是SCSI_Read10_Cmd和SCSI_Write10_Cmd函數,最終調用MAL_Read和MAL_Write,在這兩個(gè)函數中判斷是對SD卡還是NANDFLASH進(jìn)行讀寫(xiě)。具體的過(guò)程可以參考代碼。

四、例程問(wèn)題現象和解決方法

1.NAND FLASH盤(pán)可以被識別,格式化失敗。既然NAND FLASH盤(pán)可以被識別,那就表明USB的控制傳輸沒(méi)出現問(wèn)題,USB批量傳輸出問(wèn)題了,而且最可能的是NAND FLASH的驅動(dòng)有問(wèn)題,仔細看完代碼,發(fā)現在建立壞塊表,對Spare 區域進(jìn)行讀操作中,對NAND FLASH 有一個(gè)NAND_CMD_AREA_TRUE1命令操作,查看代碼,

#define NAND_CMD_AREA_TRUE1 ((u8)0x30)

而30H這個(gè)命令在數據手冊中找不到,在程序中把這行注釋掉,編譯代碼,下載,還是無(wú)法格式化,最后研究了一下手冊,在注釋代碼的這一行加上5微秒的延遲,然后編譯,下載,NAND FLASH可移動(dòng)磁盤(pán)可以正常的讀寫(xiě)了。

2.SD盤(pán)也能被識別,不能格式化。開(kāi)始用的是2G的SD卡,后來(lái)嘗試1G和512M的,它們都能用,也就是說(shuō),這個(gè)SD卡驅動(dòng)只識別1G和512M的SD卡。

在代碼中添加調試信息,結果是寫(xiě)入的塊長(cháng)度出錯。通過(guò)對讀SD卡信息了解到,2G的SD卡,塊大小是1024字節,其它的卡都是512字節。我在SDIO例程中設置塊大小為1024字節,讀寫(xiě)出錯,設置512字節,居然是正確的。

USB MassStorage例程中是首先從SD卡中讀取SD卡塊大小的值,按照這個(gè)值來(lái)讀寫(xiě)SD卡,而實(shí)際上2G的SD卡只能按照512字節來(lái)讀寫(xiě)。所以在讀取塊大小的值后,把塊的大小除以2,塊數目乘以2,卡的總容量不變,程序運行后,一切正常了。



關(guān)鍵詞: STM32USBMassStorage調試筆

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>