最近在研究STM32F4的SD卡Fatfs文件系統,官方和開發板提供的例程完全可以使用,但是缺少了理論的支持,完全看不懂。所以在網上以及《零死角玩轉STM32》上整理了一些SD卡相關的基礎知識。
SD卡的分類
目前常用的存儲卡按照尺寸可分爲SD卡和micro SD卡(TF卡)(其實種類繁多,我只接觸過這兩種),按照容量可分爲標準容量SD(不大於2GB)、高容量SDHC(大於2GB,不大於32GB)和超大容量SDXC(大於32GB,不大於2TB),還可以按照傳輸速度進行劃分,SD2.0規範中分爲Class2,Class4,Class6和Class10,SD3.01規範中分爲USH-I和USH-II。
其實,瞭解了SD卡的分類,不同速度等級的應用場景,看懂SD卡上的標識,足可以應付在生活中使用SD卡,例如:行車記錄儀要求SD卡的速度等級爲Class10。
容量等級 | 容量範圍 | 磁盤格式 |
---|---|---|
SD | 上限至2GB | FAT12、FAT16 |
SDHC | 2GB至32GB | FAT32 |
SDXC | 32GB至2TB | exFAT |
速度等級 | 速度(MB/S) | 應用範圍 |
---|---|---|
Class 0 | — | 低於Class 2和未標註Speed Class的情況 |
Class 2 | 最低寫入2.0 MB/S | 觀看普通清晰度電視,數碼相機連拍 |
Class 4 | 最低寫入4.0 MB/S | 流暢播放高清電視(HDTV),數碼相機連拍 |
Class 6 | 最低寫入6.0 MB/S | 單反相機連拍,以及專業設備的使用 |
Class 10 | 最低寫入10 MB/S | 全高清電視的錄製和播放 |
UHS-I | 寫入50 MB/S以內,讀取104 MB/S以內 | 專業全高清電視實時錄製 |
UHS-II | 寫入156 MB/S以內,讀取312 MB/S以內 | 未來世界 |
SD上常見的標識
SD卡引腳
SD卡有9個引腳,TF卡有8個引腳,引腳順序是面向卡的引腳,左側第一個是引腳1,依次類推。
CMD:命令控制線,主機通過該線發送控制命令,SD卡也是通過該線傳輸應答信息。通過管腳的名稱可以看出它的功能,下面簡單介紹了一下CMD。
SD分爲卡識別階段和數據傳輸階段,兩個階段的時鐘是有區別的:
- 識別階段時鐘頻率FOD,最高400KHz。
- 數據傳輸模式時鐘頻率FPP,默認最高25MHz
SD卡忙狀態通過把D0拉低來表示。
SD卡寄存器
SD卡內部共有8個寄存器,必須通過命令來進行訪問,SDIO定義了64個訪問SD卡的命令。
名稱 | Bit寬度 | 描述 |
---|---|---|
CID |
128 |
卡識別號(Card Identification) |
RCA |
16 |
相對卡地址(Relative Card Address) |
DSR |
16 |
驅動級寄存器(Driver Stage Register) |
CSD |
128 |
卡的特定數據(Card Specific Data) |
SCR |
64 |
SD配置寄存器(SD Configuration Register) |
OCR |
32 |
操作條件寄存器(Operation Conditions Register) |
SSR |
512 |
SD狀態寄存器(SD Status) |
CSR |
32 |
卡狀態寄存器(Card Status) |
SD卡數據包格式
SD卡有常規數據(8bit)和寬位數據(512bit)兩種格式的數據包。它先發低字節再發高字節,而每
個字節則是先發高位再發低位。
SD卡命令
SD命令格式,共計48位。依次爲:起始位、傳輸標誌、命令+地址信息/參數、CRC7校驗和終止位。
0 | 1 | CONTENT | CRC | 1 |
1 | 1 | 6+32 | 7 | 1 |
SD卡命令類型有四種:
- 無響應廣播命令(bc),發送到所有卡,不返回任務響應;
- 帶響應廣播命令(bcr),發送到所有卡,同時接收來自所有卡響應;
- 尋址命令(ac),發送到選定卡,DAT線無數據傳輸;
- 尋址數據傳輸命令(adtc),發送到選定卡,DAT線有數據傳輸;
在標準中定義了兩種類型的通用命令:特定應用命令(ACMD)和常規命令(GEN_CMD)
命令序號 |
類型 |
參數 |
響應 |
縮寫 |
描述 |
基本命令(Class 0) |
|||||
CMD0 |
bc |
[31:0]填充位 |
— |
GO_IDEL_STATE |
復位所有的卡到idle狀態 |
CMD2 |
bcr |
[31:0]填充位 |
R2 |
ALL_SEND_CID |
通知所有的卡通過CMD線返回CID值。 |
CMD3 |
bcr |
[31:0]填充位 |
R6 |
SEND_RELATIVE_ADDR |
通知所有卡發佈新RCA。 |
CMD4 |
bc |
[31:16]DSR[15:0]填充位 |
— |
SET_DSR |
編程所有卡的DSR。 |
CMD7 |
ac |
[31:16]RCA[15:0]填充位 |
R1b |
SELECT/DESELECT_CARD |
選擇/取消選擇RCA地址卡。 |
CMD8 |
bcr |
[31:12]保留位 [11:8]VHS [7:0]檢查模式 |
R7 |
SEND_IF_COND |
發送SD卡接口條件,包含主機支持的電壓信息,並詢問卡是否支持。 |
CMD9 |
ac |
[31:16]RCA[15:0]填充位 |
R2 |
SEND_CSD |
選定卡通過CMD線發送CSD內容。 |
CMD10 |
ac |
[31:16]RCA[15:0]填充位 |
R2 |
SEND_CID |
選定卡通過CMD線發送CID內容。 |
CMD12 |
ac |
[31:0]填充位 |
R1b |
STOP_TRANSMISSION |
強制卡停止傳輸。 |
CMD13 |
ac |
[31:16]RCA[15:0]填充位 |
R1 |
SEND_STATUS |
選定卡通過CMD線發送它狀態寄存器 |
CMD15 |
ac |
[31:16]RCA[15:0]填充位 |
— |
GO_INACTIVE_STATE |
使選定卡進入“inactive”狀態 |
面向塊的讀操作(Class 2) |
|||||
CMD16 |
ac |
[31:0]塊長度 |
R1 |
SET_BLOCK_LEN |
對於標準SD卡,設置塊命令的長度,對於SDHC卡塊命令長度固定爲512字節。 |
CMD17 |
adtc |
[31:0]數據地址 |
R1 |
READ_SINGLE_BLOCK |
對於標準SD卡,讀取SET_BLOCK_LEN長度字節的塊,對於SDHC卡,讀取512字節的塊。 |
CMD18 |
adtc |
[31:0]數據地址 |
R1 |
READ_MULTIPLE_BLOCK |
連續從SD卡讀取數據塊,直到被CMD12中斷。塊長度同CMD17。 |
面向塊的寫操作(Class 4) |
|||||
CMD24 |
adtc |
[31:0] 數據地址 |
R1 |
WRITE_BLOCK |
對於標準SD卡,寫入SET_BLOCK_LEN長度字節的塊,對於SDHC卡,寫入512字節的塊。 |
CMD25 |
adtc |
[31:0]數據地址 |
R1 |
WRITE _ MULTIPLE _BLOCK |
連續向SD卡寫入數據塊,直到被CMD12中斷。塊長度同CMD17。 |
CMD27 |
adtc |
[31:0] 填充位 |
R1 |
PROGRAM_CSD |
對CSD的可編程位進行編程。 |
擦除命令(Class 5) |
|||||
CMD32 |
ac |
[31:0] 數據地址 |
R1 |
ERASE_WR_BLK_START |
設置擦除的起始塊地址。 |
CMD33 |
ac |
[31:0]數據地址 |
R1 |
ERASE_WR_BLK_END |
設置擦除的結束塊地址。 |
CMD38 |
ac |
[31:0] 填充位 |
R1b |
ERASE |
擦除預先選定的塊。 |
加鎖命令(Class 7) |
|||||
CMD42 |
adtc |
[31:0]保留 |
R1 |
LOCK_UNLOCK |
加鎖/解鎖SD卡。 |
特定應用命令(Class 8) |
|||||
CMD55 |
ac |
[31:16]RCA[15:0]填充位 |
R1 |
APP_CMD |
指定下個命令爲特定應用命令,不是標準命令。 |
CMD56 |
adtc |
[31:1] 填充位 [0] 讀/寫 |
R1 |
GEN_CMD |
通用命令,或者特定應用命令中,用於傳輸一個數據塊,最低位1表示讀數據,爲0表示寫數據。 |
SD卡特定應用命令 |
|||||
ACMD6 |
ac |
[31:2] 填充位 [1:0] 總線寬度 |
R1 |
SET_BUS_WIDTH |
定義數據總線寬度(‘00’=1bit,‘10’=4bit)。 |
ACMD13 |
adtc |
[31:0] 填充位 |
R1 |
SD_STATUS |
發送SD狀態. |
ACMD41 |
bcr |
[31] 保留位 [30] HCS(OCR[30])[29:24] 保留位[23:0]VDD電壓(OCR[23:0]) |
R3 |
SD_SEND_OP_COND |
主機要求卡發送它的支持信息(HCS)和OCR寄存器內容。 |
ACMD51 |
adtc |
[31:0] 填充位 |
R1 |
SEND_SCR |
讀取配置寄存器SCR. |
響應類型
SD卡有R1、R2、R3、R6、R7這幾種響應類型,不同的命令對應的響應類型是不一樣的。
R1(正常響應命令) |
|||||||||||
描述 |
起始位 |
傳輸位 |
命令號 |
卡狀態 |
CRC7 |
終止位 |
|||||
Bit |
47 |
46 |
[45:40] |
[39:8] |
[7:1] |
0 |
|||||
位寬 |
1 |
1 |
6 |
32 |
7 |
1 |
|||||
值 |
“0” |
“0” |
X |
X |
X |
“1” |
|||||
備註 |
如果有傳輸到卡的數據,那麼在數據線可能有busy信號。 |
||||||||||
R2(CID、CSD寄存器) |
|||||||||||
描述 |
起始位 |
傳輸位 |
保留 |
[127:1] |
終止位 |
||||||
Bit |
135 |
134 |
[133:128] |
127 |
0 |
||||||
位寬 |
1 |
1 |
6 |
X |
1 |
||||||
值 |
“0” |
“0” |
“111111” |
CID或者CSD寄存器[127:1]位的值 |
“1” |
||||||
備註 |
CID寄存器內容作爲CMD2和CMD10響應,CSD寄存器內容作爲CMD9響應。 |
||||||||||
R3(OCR寄存器) |
|||||||||||
描述 |
起始位 |
傳輸位 |
保留 |
OCR寄存器 |
保留 |
終止位 |
|||||
Bit |
47 |
46 |
[45:40] |
[39:8] |
[7:1] |
0 |
|||||
位寬 |
1 |
1 |
6 |
32 |
7 |
1 |
|||||
值 |
“0” |
“0” |
“111111” |
X |
“1111111” |
“1” |
|||||
備註 |
OCR寄存器的值作爲ACMD41的響應。 |
||||||||||
R6(發佈的RCA寄存器響應) |
|||||||||||
描述 |
起始位 |
傳輸位 |
CMD3 |
RCA寄存器 |
卡狀態位 |
CRC7 |
終止位 |
||||
Bit |
47 |
46 |
[45:40] |
[39:8] |
[7:1] |
0 |
|||||
位寬 |
1 |
1 |
6 |
16 |
16 |
7 |
1 |
||||
值 |
“0” |
“0” |
“000011” |
X |
X |
X |
“1” |
||||
備註 |
專用於命令CMD3的響應。 |
||||||||||
R7(發佈的RCA寄存器響應) |
|||||||||||
描述 |
起始位 |
傳輸位 |
CMD8 |
保留 |
接收電壓 |
檢測模式 |
CRC7 |
終止位 |
|||
Bit |
47 |
46 |
[45:40] |
[39:20] |
[19:16] |
[15:8] |
[7:1] |
0 |
|||
位寬 |
1 |
1 |
6 |
20 |
4 |
8 |
7 |
1 |
|||
值 |
“0” |
“0” |
“001000” |
“00000h” |
X |
X |
X |
“1” |
|||
備註 |
專用於命令CMD8的響應,返回卡支持電壓範圍和檢測模式。 |
SD卡狀態
SD卡的操作模式和狀態如下表所示。接下來的兩張圖片也卡模式和數據傳輸模式下的狀態切換。
操作模式 | SD卡狀態 |
---|---|
無效模式(Inactive) |
無效狀態(Inactive State) |
卡識別模式(Card identification mode) |
空閒狀態(Idle State) |
準備狀態(Ready State) |
|
識別狀態(Identification State) |
|
數據傳輸模式(Data transfer mode) |
待機狀態(Stand-by State) |
傳輸狀態(Transfer State) |
|
發送數據狀態(Sending-data State) |
|
接收數據狀態(Receive-data State) |
|
編程狀態(Programming State) |
|
斷開連接狀態(Disconnect State) |
現在就可以通過SD卡的狀態、模式、命令、響應等信息來仔細閱讀STM32的sdio.c文件了。由於我也不太懂所以,還沒有具體的內容來提供。接下來我們去看看SD卡是如何Fatfs關聯上的。
文件系統Fatfs
在Fatfs下面有diskio.c這個文件,這個文件中定義了五個接口,被ff.c文件調用,ff.c文件提供了open(),close(),write(),read()等等文件系統常用的接口。Fatfs的移植就是主要是更改diskio.c這個文件,通過五個接口來適配不同的存儲介質,如SD卡、U盤、Flash等。
- DSTATUS disk_status (BYTE pdrv);
- DSTATUS disk_initialize ( BYTE pdrv );
- DRESULT disk_read (BYTE pdrv, BYTE *buff,DWORD sector, UINT count );
- DRESULT disk_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count);
- DRESULT disk_ioctl (BYTE pdrv, BYTE cmd,void *buff );
在這5個接口中,有一個共同的形參pdrv,他就是不同的存儲介質SD卡、U盤、Flash。
結語
ST的例程,開發板的例程,我們完全可以拿來稍加修改就可以使用。我們完全可以不明就裏的拿來就用,好用就行,能交差就行,但是不明不白的拿來就用使我心裏很不舒服,必須簡單的弄明白原理,弄清楚結構,這樣除了問題也能更快的定位。上面寫了那麼多,我也還是沒有完全弄明白,隨用隨學吧!