詳解 STM32 之 SD 卡(2)
五、SD卡物理層協(xié)議
SD卡的協(xié)議相對于SPI、I2C等協(xié)議的存儲器來說相對復雜,包含SD卡物理層(機械封裝、管腳、芯片結(jié)構(gòu)、命令集等)、SD卡接口(SDIO)、SD主機控制器,甚至是軟件設計的流程,都進行了詳細的規(guī)定。
1、接口
① SDIO接口
參考《Simplified_SDIO_Card_Spec.pdf》
<1> CLK 時鐘同步線
<2> CMD 命令信號線,主機發(fā)出的命令以及從機對命令的響應都是通過這條線進行傳輸
<3> DAT[3:0] 表示4條數(shù)據(jù)線,主機和從機的數(shù)據(jù)都是從這四條數(shù)據(jù)線上傳輸
② SPI接口
2、命令格式
3、響應格式
以R1為例
4、SD卡的工作狀態(tài)
5、SD卡的兩種狀態(tài)信息
① Card Status
執(zhí)行命令過程中的狀態(tài)信息,比如地址不對齊錯誤、塊長度錯誤、卡鎖、ECC校驗錯誤等等
② SD Status
SD卡的專有特征,編程中不經(jīng)常涉及。這個狀態(tài)值有512位,不是通過命令線傳送給主機,而是通過數(shù)據(jù)線。
六、STM32與SD卡相配的外設--SDIO適配器
1、SDIO adapter 結(jié)構(gòu)圖
2、命令狀態(tài)機(CPSM)
當發(fā)送命令和接收響應時,啟動CPSM狀態(tài)機。
3、數(shù)據(jù)通道狀態(tài)機
當傳輸數(shù)據(jù)時,啟動數(shù)據(jù)通道狀態(tài)機。
4、FIFO
有關FIFO的資料參考:異步FIFO的FPGA實現(xiàn)
數(shù)據(jù)FIFO(先進先出)子單元是一個具有發(fā)送和接收單元的數(shù)據(jù)緩沖區(qū)。
FIFO包含一個每字32位寬、共32個字的數(shù)據(jù)緩沖區(qū),和發(fā)送與接收電路。因為數(shù)據(jù)FIFO工作在AHB 時鐘區(qū)域(HCLK/2),所有與SDIO時鐘區(qū)域(SDIOCLK)連接的信號都進行了重新同步。依據(jù)TXACT和RXACT標志,可以關閉FIFO、使能發(fā)送或使能接收。TXACT和RXACT 由數(shù)據(jù)通道子單元設置而且是互斥的:
─ 當 TXACT 有效時,發(fā)送 FIFO 代表發(fā)送電路和數(shù)據(jù)緩沖區(qū)
─ 當 RXACT 有效時,接收 FIFO 代表接收電路和數(shù)據(jù)緩沖區(qū)
5、SDIO的特殊功能寄存器
SDIO電源控制寄存器(SDIO_POWER)
SDIO時鐘控制寄存器(SDIO_CLKCR) : 時鐘選擇、分頻
SDIO參數(shù)寄存器(SDIO_ARG)
SDIO命令寄存器(SDIO_CMD):控制發(fā)送命令
SDIO命令響應寄存器(SDIO_RESPCMD):包含響應命令中的命令索引
SDIO響應1..4寄存器(SDIO_RESPx):包含響應命令中的卡狀態(tài)信息
SDIO數(shù)據(jù)定時器寄存器(SDIO_DTIMER)
SDIO數(shù)據(jù)長度寄存器(SDIO_DLEN):讀或者寫的長度,通常是是512的倍數(shù)
SDIO數(shù)據(jù)控制寄存器(SDIO_DCTRL):控制數(shù)據(jù)的讀寫方向、使能傳輸?shù)刃畔?/p>
SDIO數(shù)據(jù)計數(shù)器寄存器(SDIO_DCOUNT):當DPSM狀態(tài)機從Idle state切換到Wait_R或者Wait_S狀態(tài)時,SDIO_LEN的數(shù)值加載到該寄存器中
SDIO狀態(tài)寄存器(SDIO_STA)
SDIO清除中斷寄存器(SDIO_ICR)
SDIO中斷屏蔽寄存器(SDIO_MASK)
SDIO FIFO計數(shù)器寄存器(SDIO_FIFOCNT):當SDIO_DCTRL中的DTEN使能,并且DPSM處于Idle state時,SDIO_LEN/4的數(shù)值加載到該寄存器中
SDIO數(shù)據(jù)FIFO寄存器(SDIO_FIFO):讀寫數(shù)據(jù)緩沖FIFO
七、SD卡編程
SD卡的編程在STM32官方固件庫中就有例程,而且野火開發(fā)板對該例程進行了中文注釋,不必再把源碼貼入。這里著重講一下SD卡編程流程,主要包含SD卡初始化、SD卡讀、SD卡寫、SD卡擦除。
1、SD卡編程的內(nèi)容
SD卡主要就是用來存儲數(shù)據(jù)的,所以核心就是讀寫。為了實現(xiàn)這個目標,必須實現(xiàn)響應的驅(qū)動。
配置過程中,不僅要設置好SD控制器,還需要將SD卡設置到合適的狀態(tài)。在讀取狀態(tài)的時候,不僅涉及到SD控制器的狀態(tài),還涉及到SD卡的狀態(tài)。
2、SD卡初始化
① STM32外設SDIO初始化
端口配置、端口時鐘、SDIO時鐘、DMA2時鐘使能
SDIO寄存器復位
設置時鐘SDIO_CK為400KHz以下,設置數(shù)據(jù)線寬度,開啟時鐘、開啟SDIO電源
② SD卡上電初始化
上電初始化流程如上圖所示,筆者認為官方庫提供的例程沒有完全按照這個流程圖的指示去做。事實上,官方庫的程序只做了如上圖紅色方框內(nèi)的流程,之外的沒涉及。
CMD0命令復位所有的卡。
SD協(xié)議規(guī)定:在初始化的時候,使用ACMD41之前,必須先使用CMD8命令。而且ACMD41命令屬于應用命令,在使用之前需要先發(fā)送命令CMD55。
CMD8命令是為了核查電源是否匹配。ACMD41命令不斷詢問SD卡是否支持主機提供的電壓,并且詢問SD卡是否上電完成進入準備狀態(tài)。ACMD41命令還能詢問SD卡的類型(SDSC、SDHC)。
③卡進一步核查、獲取卡信息
發(fā)送命令CMD2,以獲取CID信息。
發(fā)送命令CMD3,以獲取RCA相對地址,可以通過多次發(fā)送CMD3獲取不同的RCA值,但是只有最后一次的才是有效的RCA地址。
發(fā)送命令CMD9,以獲取CSD寄存器。
④ 設置SDIO工作在數(shù)據(jù)傳輸模式
設置SDIO的時鐘為24MHz、數(shù)據(jù)線寬度為4位。
通過SD_GetCardInfo函數(shù)將之前得到CID、CSD處理成卡的信息。
通過CMD7命令選擇匹配地址的卡,而取消選擇其他的卡。
至此,初始化完成。
3、讀SD卡的一個塊
數(shù)據(jù)控制寄存器(SDIO_DCTRL)清零
發(fā)送命令CMD16,設置SD卡的Block大小
調(diào)用函數(shù)SDIO_DataConfig設置SDIO數(shù)據(jù)傳輸方式
發(fā)送命令CMD17,讀單個塊
SDIO數(shù)據(jù)傳輸結(jié)束中斷使能
SDIO的DMA傳輸功能使能
DMA設置,并使能
4、寫SD卡的一個塊
數(shù)據(jù)控制寄存器(SDIO_DCTRL)清零
發(fā)送命令CMD16,設置SD卡的Block大小
發(fā)送命令CMD24,寫單個塊
調(diào)用函數(shù)SDIO_DataConfig設置SDIO數(shù)據(jù)傳輸方式
SDIO數(shù)據(jù)傳輸結(jié)束中斷使能
DMA設置,并使能
使能SDIO的DMA傳輸功能
*博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權請聯(lián)系工作人員刪除。