看到一篇寫的比較好的筆記,分享給大家
一、SD卡概述
1、定義
2、容量等級
3、SD卡框圖
4、SD卡與TF卡的區別
二、?SD卡內部結構
1、 SD卡內部結構簡圖
2、 存儲陣列結構圖
3、Buffer?
4、“存儲陣列Block”--最小的存儲單元
5、SD卡的特殊功能寄存器
四、SD卡協議的核心--數據讀、寫、擦除
1、SD卡寫數據塊
2、SD卡讀數據塊?
3、擦除SD卡
五、SD卡物理層協議
1、接口?
2、命令格式
3、響應格式
4、SD卡的工作狀態
5、SD卡的兩種狀態信息
六、STM32與SD卡相配的外設--SDIO適配器
1、SDIO adapter 結構圖?
2、命令狀態機(CPSM)
3、數據通道狀態機(DPSM)
4、SDIO的FIFO?
5、SDIO的特殊功能寄存器
七、SD卡編程?
1、SD卡編程的內容
2、SD卡初始化?
3、讀SD卡的一個塊
4、寫SD卡的一個塊?
八、SD卡疑惑
1、SD卡擦除后,其中的內容是0,還是1 ??
2、在SDIO_DCTRL中設置傳輸Block的要求
? ?3、STM32固件庫“stm32_eval_sdio_sd.c version v4.5.0”偶遇BUG
? ?4、SD卡寫Block是怎樣進行的?
九、SD卡參數測試
一、SD卡概述
1、定義
SD卡(安全數碼卡),是一種基于半導體快閃記憶器的新一代記憶設備,它被廣泛地于便攜式裝置上使用,例如數碼相機、個人數碼助理(外語縮寫PDA)和多媒體播放器等。
2、容量等級
容量等級 | 容量范圍 | 磁盤格式 |
SD | 上限至2GB | FAT 12, 16 |
SDHC | 2GB至 32GB | FAT 32 |
SDXC | 32GB至2TB | exFAT |
3、SD卡框圖
?引腳說明:
4、SD卡與TF卡的區別
TF卡又名micro SD卡,個頭是比SD卡的1/4還小,可以通過“TF轉SD卡套”轉換成SD卡。
詳細區別參考:SD卡與TF卡的區別
二、?SD卡內部結構
(摘自SanDisk Secure Digital Card Product Manual Version 1.9)
1、 SD卡內部結構簡圖
由SD卡控制器和存儲陣列組成,SD卡與外界的通訊接口是SD Bus或者SPI Bus。
2、 存儲陣列結構圖
Block: ?
讀寫時的單元(數據傳輸單元),它的單位是“字節”。
Sector:
如果CSD寄存器ERASE_BLK_EN = 0時,Sector是最小的擦除單元,它的單位是“塊”。Sector的值等于CSD寄存器中的SECTOR_SIZE的值+1。
WP Group:
最小的寫保護單元,它的單位是“扇區”。
3、Buffer
SD Card的Buffer最大容量定義在CSD寄存器的READ_BL_LEN和WRITE_BL_LEN。它們的值是一樣的,而且有可能超過512字節,盡管這樣Block還是要設置成512字節,因為512字節是數據邊界(這句話不是太理解)。也就是SD卡上有數據傳輸緩沖器Buffer,不同的產品可能不一樣,但是在使用時要將Buffer設置成512字節。
4、“存儲陣列Block”--最小的存儲單元
資料上的Block通通指的是數據傳輸時的最小單元,定義這個數值是為了數據傳輸、CRC校驗等。
存儲陣列通常采用NandFlash的結構,顯然不能按字節存取,而這里討論的“存儲陣列Block”就是指這個概念。可惜的是目前,我還沒有找到資料討論這個問題,所以這一章節是筆者自己的推測。
據我推測存儲陣列Block應該是512Byes,因為眾多的數據都圍繞著512Bytes在轉。比如說最小的擦除單元是512Byes,最小的讀寫單位應該被設置成512Bytes,那么有理由推測是這個數值。
5、SD卡特殊功能寄存器
CID: 寬度128位,卡標識號
RCA: 寬度16位,卡相對地址,在初始化的時候確定
CSD: 寬度128位,卡描述數據:卡操作條件的信息
SCR: 寬度64位,SD卡配置寄存器:SD卡特定信息數據
OCR: 寬度32位,操作條件寄存
三、SDIO接口
四、SD卡協議之數據讀、寫、擦除
1、SD卡寫數據塊
執行寫數據塊命令(CMD24-27) 時,主機把一個或多個數據塊從主機傳送到卡中,同時在每個數據塊的末尾傳送一個CRC碼。主機傳送數據,SD卡接收數據并將數據保存在Buffer中,累計接收數據達到Block長度的時候,SD卡把接下來的數據當做CRC校驗碼,并且開始數據校驗。如果CRC校驗錯誤,卡通過SDIO_D 線指示錯誤,傳送的數據被丟棄而不被寫入,所有后續(在多塊寫模式下)傳送的數據塊將被忽略。
? ? ?如果主機傳送部分數據而累計的數據長度未與數據塊對齊,當不允許塊錯位( 未設置CSD的參數WRITE_BLK_MISALIGN),卡將在第一個錯位的塊之前檢測到塊錯位錯誤( 設置狀態寄存器中的ADDRESS_ERROR 錯誤位) 。當主機試圖寫一個寫保護區域時,寫操作也會被中止,此時卡會設置WP_VIOLATION位。
數據塊Block的最大長度定義在CSD中的WRITE_BL_LEN,但是在數據傳輸時應該用CMD16指令將其設置為512Byets,不去在意WRITE_BL_LEN是1024或者2048Bytes。
另外需要注意的是,Block的長度設置還要參考CSD寄存器的WRITE_BL_PARTIAL。當WRITE_BL_PARTIAL為0時,那么么辦法Block只能設置為512Bytes;如果WRITE_BL_PARTIAL=1,那么允許將Block設置成更小的塊,比如說一個字節。協議是這樣規定的,但是據我分析如果這樣的話SD卡的制作會非常復雜(寫入的單位可以是字節),價格也會很高。筆者測試了自己的SD卡,WRITE_BL_PARTIAL 等于0,也就是不支持“塊部分寫”功能。?
2、SD卡讀數據塊
在讀數據塊模式下,數據傳輸的基本單元是數據塊Block。為保證數據傳輸的正確,傳輸一個數據塊Blcok后都有一個CRC校驗碼。筆者認為主機在累計接收到Block長度數據后,軟件可以把接下來的數據當做CRC校驗碼,并且進行校驗。
Block的最大值在CSD中(READ_BL_LEN) 給出了定義,但是在數據傳輸時應該用CMD16指令將其設置為512Byets,不去在意READ_BL_LEN是1024或者2048Bytes。
如果CSD寄存器中的READ_BL_PARTIAL等于1,可以傳送的較小數據塊,較小數據塊是指開始和結束地址完全包含在一個物理塊中。事實上,協議規定READ_BL_PARTIAL永遠等于1,也就說在任何SD卡上都允許“讀部分塊”,讀的塊的最小字節是1Bytes。使用這種功能,可以通過CMD16命令設置更小的Block(比如說等于128)。讀取的這128字節必須在512Bytes邊界內,不能跨越邊界(其實因為存儲陣列是以512Bytes為單位的,讀取“部分塊”只能在一個塊內,不允許跨塊讀)。
3、擦除SD卡
CSD寄存器ERASE_BLK_EN決定了SD卡的最小擦除單位。
當ERASE_BLK_EN等于0的時候,主機擦除的最小單位是扇區。比如一個Sector包含32個Block,擦除時的起始地址是5,而結束地址是40,那么實際擦除的塊是從0到63。
當ERASE_BLK_EN等于1的時候,主機擦除的最小單位是512 Byetes。比如擦除時的起始地址是5,而結束地址是40,那么實際擦除的塊就是從5到40。
五、SD卡物理層協議
SD卡的協議相對于SPI、I2C等協議的存儲器來說相對復雜,包含SD卡物理層(機械封裝、管腳、芯片結構、命令集等)、SD卡接口(SDIO)、SD主機控制器,甚至是軟件設計的流程,都進行了詳細的規定。
1、接口
① SDIO接口
<1> CLK 時鐘同步線
<2> CMD 命令信號線,主機發出的命令以及從機對命令的響應都是通過這條線進行傳輸
<3> DAT[3:0] 表示4條數據線,主機和從機的數據都是從這四條數據線上傳輸
② SPI接口
2、命令格式
3、響應格式
以R1為例
4、SD卡的工作狀態
5、SD卡的兩種狀態信息
① Card Status
執行命令過程中的狀態信息,比如地址不對齊錯誤、塊長度錯誤、卡鎖、ECC校驗錯誤等等
② SD Status
SD卡的專有特征,編程中不經常涉及。這個狀態值有512位,不是通過命令線傳送給主機,而是通過數據線。
六、STM32與SD卡相配的外設--SDIO適配器
?1、SDIO adapter 結構圖
2、命令狀態機(CPSM)
當發送命令和接收響應時,啟動CPSM狀態機。
3、數據通道狀態機
當傳輸數據時,啟動數據通道狀態機。
4、FIFO
有關FIFO的資料參考:異步FIFO的FPGA實現
數據FIFO(先進先出)子單元是一個具有發送和接收單元的數據緩沖區。
FIFO包含一個每字32位寬、共32個字的數據緩沖區,和發送與接收電路。因為數據FIFO工作在AHB 時鐘區域(HCLK/2),所有與SDIO時鐘區域(SDIOCLK)連接的信號都進行了重新同步。依據TXACT和RXACT標志,可以關閉FIFO、使能發送或使能接收。TXACT和RXACT 由數據通道子單元設置而且是互斥的:
─ 當 TXACT 有效時,發送 FIFO 代表發送電路和數據緩沖區
─ 當 RXACT 有效時,接收 FIFO 代表接收電路和數據緩沖區
5、SDIO的特殊功能寄存器
SDIO電源控制寄存器(SDIO_POWER)
SDIO時鐘控制寄存器(SDIO_CLKCR) : 時鐘選擇、分頻
SDIO參數寄存器(SDIO_ARG)
SDIO命令寄存器(SDIO_CMD):控制發送命令
SDIO命令響應寄存器(SDIO_RESPCMD):包含響應命令中的命令索引
SDIO響應1..4寄存器(SDIO_RESPx):包含響應命令中的卡狀態信息
SDIO數據長度寄存器(SDIO_DLEN):讀或者寫的長度,通常是是512的倍數
SDIO數據控制寄存器(SDIO_DCTRL):控制數據的讀寫方向、使能傳輸等信息
SDIO數據計數器寄存器(SDIO_DCOUNT):當DPSM狀態機從Idle state切換到Wait_R或者Wait_S狀態時,SDIO_LEN的數值加載到該寄存器中
SDIO狀態寄存器(SDIO_STA)
SDIO清除中斷寄存器(SDIO_ICR)
SDIO中斷屏蔽寄存器(SDIO_MASK)
SDIO FIFO計數器寄存器(SDIO_FIFOCNT):當SDIO_DCTRL中的DTEN使能,并且DPSM處于Idle state時,SDIO_LEN/4的數值加載到該寄存器中
SDIO數據FIFO寄存器(SDIO_FIFO):讀寫數據緩沖FIFO
七、SD卡編程
SD卡的編程在STM32官方固件庫中就有例程,而且野火開發板對該例程進行了中文注釋,不必再把源碼貼入。這里著重講一下SD卡編程流程,主要包含SD卡初始化、SD卡讀、SD卡寫、SD卡擦除。
1、SD卡編程的內容
SD卡主要就是用來存儲數據的,所以核心就是讀寫。為了實現這個目標,必須實現響應的驅動。
配置過程中,不僅要設置好SD控制器,還需要將SD卡設置到合適的狀態。在讀取狀態的時候,不僅涉及到SD控制器的狀態,還涉及到SD卡的狀態。
2、SD卡初始化
① STM32外設SDIO初始化
SDIO寄存器復位
設置時鐘SDIO_CK為400KHz以下,設置數據線寬度,開啟時鐘、開啟SDIO電源
② SD卡上電初始化
上電初始化流程如上圖所示,筆者認為官方庫提供的例程沒有完全按照這個流程圖的指示去做。事實上,官方庫的程序只做了如上圖紅色方框內的流程,之外的沒涉及。
CMD0命令復位所有的卡。
SD協議規定:在初始化的時候,使用ACMD41之前,必須先使用CMD8命令。而且ACMD41命令屬于應用命令,在使用之前需要先發送命令CMD55。
CMD8命令是為了核查電源是否匹配。ACMD41命令不斷詢問SD卡是否支持主機提供的電壓,并且詢問SD卡是否上電完成進入準備狀態。ACMD41命令還能詢問SD卡的類型(SDSC、SDHC)。
③卡進一步核查、獲取卡信息
發送命令CMD2,以獲取CID信息。
發送命令CMD3,以獲取RCA相對地址,可以通過多次發送CMD3獲取不同的RCA值,但是只有最后一次的才是有效的RCA地址。
發送命令CMD9,以獲取CSD寄存器。
④ 設置SDIO工作在數據傳輸模式
設置SDIO的時鐘為24MHz、數據線寬度為4位。
通過SD_GetCardInfo函數將之前得到CID、CSD處理成卡的信息。
通過CMD7命令選擇匹配地址的卡,而取消選擇其他的卡。
至此,初始化完成。
3、讀SD卡的一個塊
數據控制寄存器(SDIO_DCTRL)清零
發送命令CMD16,設置SD卡的Block大小
調用函數SDIO_DataConfig設置SDIO數據傳輸方式
發送命令CMD17,讀單個塊
SDIO數據傳輸結束中斷使能
SDIO的DMA傳輸功能使能
DMA設置,并使能
4、寫SD卡的一個塊
數據控制寄存器(SDIO_DCTRL)清零
發送命令CMD16,設置SD卡的Block大小
發送命令CMD24,寫單個塊
調用函數SDIO_DataConfig設置SDIO數據傳輸方式
SDIO數據傳輸結束中斷使能
DMA設置,并使能
使能SDIO的DMA傳輸功能?
八、SD卡疑惑
1、SD卡擦除后,其中的內容是0,還是1 ??
The data at the card after an erase operation is either '0' or '1', depends on the card vendor.The SCR register bit DATA_STAT_AFTER_ERASE (bit 55) defines whether it is '0' or '1'.(摘自《SD Specifications_Part_1_Physical_Layer_Specification_Ver3.00_Final_090416.pdf》)
也就是說這是芯片廠商生產工藝決定的,可以通過SCR寄存器的 DATA_STAT_AFTER_ERASE位得知。
?2、在SDIO_DCTRL中設置傳輸Block的要求
Block大小決定了主機在發送數據時,發送到什么程度時開始發送CRC校驗碼;而在接收數據時,在接收到什么程度時開始把SD卡的數據作為CRC校驗碼并進行校驗。Block還可能影響著其他的時序。在STM32的SDIO寄存器組中,SDIO_DCTRL中的位段DBLOCKSIZE決定主機Block大小。
在摘自《Simplified_SD_Host_Controller_Spec.pdf》的引文中,提到這樣的配置要求:主機的Block一定要與SD卡設置的Block一樣大小,這顯然是必要的。我們經常設置SD卡的Block大小是512Bytes,所以設置DBLOCKSIZE為9(2^9 = 512)。
?3、STM32固件庫“stm32_eval_sdio_sd.c version v4.5.0”偶遇BUG
參考網頁:http://www.cprogramdevelop.com/3742318/
?4、SD卡寫Block是怎樣進行的?
寫SD卡的單位是Block(512Bytes),再寫之前要先整塊擦除,然后才能寫。
在多塊寫操作中,可以在發送多塊寫命令CMD25之前,有選擇性的先發送命令ACMD23設置預擦除。怎樣理解呢?
既然是有選擇性的,也可以不發送ACMD23命令。在多塊寫的過程中,由于SD卡事先不知道你要寫入幾個塊(CMD25命令只告訴SD卡要寫入的起始地址),所以寫入的過程是:根據需要判斷要寫一個塊時,先擦除然后再寫,再判斷是否要寫入下一個塊,如果是就再擦除再寫。
倘若發送ACMD23命令就不一樣了,ADM23命令會在寫命令CMD25生效之前,告訴SD卡準備寫入的塊數N。這樣當CMD25命令生效的時候,SD卡會一次性先將這N個塊都擦除,然后再一個塊一個塊寫。由于擦除操作比較集中,所以整個多塊寫操作更節省時間。
九、SD卡參數測試
使用野火開發板配套例程做測試,筆者測試用的SD卡是金士頓的2G內存塊,打印SD卡的參數信息如下:
?
Card Type is :1
ManufacturerID is :2
Card device size is :3795
Card Block Size is :1024
Card device size multiplier is :7
Card Capacity is :1990197248
the maximum read date block length is :1024
partial blocks for write allowed is :0
the maximum write date block length is :1024
erase single block enable is :1
erase sector size is :127
write protect group size is :0
RCA is :4660?
?
Card Type:1 ? ? ? ? SDSC卡版本2.0
Card device size: C_SIZE(CSD),為3795
Card Block Size: max read data block length(READ_BL_LEN(CSD)) ,為1024 Bytes
Card device size multiplier is: ?C_SIZE_MULT(CSD),為7
Card Capacity: 1990197248 Bytes
計算方法(摘自《Simplified_Physical_Layer_Spec.pdf》):
memory capacity = BLOCKNR * BLOCK_LEN
?
BLOCKNR = (C_SIZE+1) * MULT ?(C_SIZE <= 4096)
MULT = 2^(C_SIZE_MULT+2) ? ? ? ?(C_SIZE_MULT < 8)
BLOCK_LEN = 2^READ_BL_LEN, ? ?(READ_BL_LEN < 12)
注意:SDSC最大為2GB。
the maximum read date block length:READ_BL_LEN(CSD)?,為1024 Bytes
partial blocks for write allowed:WRITE_BL_PARTIAL(CSD),為不支持
the maximum write date block length:WRITE_BL_LEN(CSD) ,為1024 Bytes
erase single block enable:ERASE_BLK_EN(CSD),為1,支持單塊擦除
erase sector size:SECTOR_SIZE(CSD),實際扇區擦除的block數為(SECTOR_SIZE+1),為128 Blocks
write protect group size:WP_GRP_SIZE(CSD),實際保護的扇區數為(WP_GRP_SIZE+1),為1 Sector
RCA: SD卡相對地址為4660
審核編輯:湯梓紅
評論
查看更多