cmd52命令发送 mmc_乾坤合一~Linux SD/MMC/SDIO驱动分析(上)
一、SD/MMC/SDIO概念區(qū)分
SD(SecureDigital)與 MMC(MultimediaCard)
SD 是一種 flash memory card 的標(biāo)準(zhǔn),也就是一般常見的 SD 記憶卡,而 MMC 則是較早的一種記憶卡標(biāo)準(zhǔn),目前已經(jīng)被 SD 標(biāo)準(zhǔn)所取代。在維基百科上有相當(dāng)詳細(xì)的 SD/MMC 規(guī)格說明:
SDIO(SecureDigital I/O)
SDIO 是目前我們比較關(guān)心的技術(shù),SDIO 故名思義,就是 SD 的 I/O 接口(interface)的意思,不過這樣解釋可能還有點(diǎn)抽像。更具體的說明,SD 本來是記憶卡的標(biāo)準(zhǔn),但是現(xiàn)在也可以把 SD 拿來插上一些外圍接口使用,這樣的技術(shù)便是 SDIO。
所以 SDIO 本身是一種相當(dāng)單純的技術(shù),透過 SD 的 I/O 接腳來連接外部外圍,并且透過 SD 上的 I/O 數(shù)據(jù)接位與這些外圍傳輸數(shù)據(jù),而且 SD 協(xié)會(huì)會(huì)員也推出很完整的 SDIO stack 驅(qū)動(dòng)程序,使得 SDIO 外圍(我們稱為 SDIO 卡)的開發(fā)與應(yīng)用變得相當(dāng)熱門。
現(xiàn)在已經(jīng)有非常多的手機(jī)或是手持裝置都支持 SDIO 的功能(SD 標(biāo)準(zhǔn)原本就是針對(duì) mobile device 而制定),而且許多 SDIO 外圍也都被開發(fā)出來,讓手機(jī)外接外圍更加容易,并且開發(fā)上更有彈性(不需要內(nèi)建外圍)。目前常見的 SDIO 外圍(SDIO 卡)有:Wi-Fi card(無線網(wǎng)絡(luò)卡)
CMOS sensor card(照相模塊)
GPS card
GSM/GPRS modem card
Bluetooth card
Radio/TV card(很好玩)
SDIO 的應(yīng)用將是未來嵌入式系統(tǒng)最重要的接口技術(shù)之一,并且也會(huì)取代目前 GPIO 式的 SPI 接口。
SD/SDIO 的傳輸模式
SD 傳輸模式有以下 3 種:SPI mode(required)
1-bit mode
4-bit mode
SDIO 同樣也支持以上 3 種傳輸模式。依據(jù) SD 標(biāo)準(zhǔn),所有的 SD(記憶卡)與 SDIO(外圍)都必須支持 SPI mode,因此 SPI mode 是「required」。此外,早期的 MMC 卡(使用 SPI 傳輸)也能接到 SD 插糟(SD slot),并且使用 SPI mode 或 1-bit mode 來讀取。
Secure digital I/Ocard,pin out
SD 的 MMCMode
SD 也能讀取 MMC 內(nèi)存,雖然 MMC 標(biāo)準(zhǔn)上提到,MMC 內(nèi)存不見得要支持 SPI mode(但是一定要支持 1-bit mode),但是市面上能看到的 MMC 卡其實(shí)都有支持 SPI mode。因此,我們可以把 SD 設(shè)定成 SPI mode 的傳輸方式來讀取 MMC 記憶卡。
SD 的 MMC Mode 就是用來讀取 MMC 卡的一種傳輸模式。不過,SD 的 MMC Mode 雖然也是使用 SPI mode,但其物理特性仍是有差異的:MMC 的 SPI mode 最大傳輸速率為 20 Mbit/s;
SD 的 SPI mode 最大傳輸速率為 25 Mbit/s。
為避免混淆,有時(shí)也用 SPI/MMC mode 與 SPI/SD mode 的寫法來做清楚區(qū)別。
參考網(wǎng)站:
二、MMC子系統(tǒng)介紹
MMC代碼分布
MMC子系統(tǒng)代碼主要在drivers/mmc目錄下,共有三個(gè)目錄:Card:存放閃存卡(塊設(shè)備)的相關(guān)驅(qū)動(dòng),如MMC/SD卡設(shè)備驅(qū)動(dòng),SDIOUART;
Host:針對(duì)不同主機(jī)端的SDHC、MMC控制器的驅(qū)動(dòng),這部分需要由驅(qū)動(dòng)工程師來完成;
Core:整個(gè)MMC的核心層,這部分完成不同協(xié)議和規(guī)范的實(shí)現(xiàn),為host層和設(shè)備驅(qū)動(dòng)層提供接口函數(shù)。
MMC子系統(tǒng)框架
Linux MMC子系統(tǒng)主要分成三個(gè)部分:MMC核心層:完成不同協(xié)議和規(guī)范的實(shí)現(xiàn),為host層和設(shè)備驅(qū)動(dòng)層提供接口函數(shù)。MMC核心層由三個(gè)部分組成:MMC,SD和SDIO,分別為三類設(shè)備驅(qū)動(dòng)提供接口函數(shù);
Host 驅(qū)動(dòng)層:針對(duì)不同主機(jī)端的SDHC、MMC控制器的驅(qū)動(dòng);
Client 驅(qū)動(dòng)層:針對(duì)不同客戶端的設(shè)備驅(qū)動(dòng)程序。如SD卡、T-flash卡、SDIO接口的GPS和wi-fi等設(shè)備驅(qū)動(dòng)。
三、SD 總線協(xié)議
SD總線通信是基于指令和數(shù)據(jù)比特流,起始位開始和停止位結(jié)束。SD總線通信有三個(gè)元素:Command:由host發(fā)送到卡設(shè)備,使用CMD線發(fā)送;
Response:從card端發(fā)送到host端,作為對(duì)前一個(gè)CMD的相應(yīng),通過CMD線發(fā)送;
Data:即能從host傳輸?shù)絚ard,也能從card傳輸?shù)絟ost,通過data線傳輸。
Commands
以下是四種用于控制卡設(shè)備的指令類型,每個(gè)command都是固定的48位長度:
1、broadcast commands(bc), no response:廣播類型的指令,不需要有響應(yīng);
2、broadcast commands with response(bcr):廣播類型的指令且需要響應(yīng);
3、addressed(point-to-point) commands(ac):由HOST發(fā)送到指定的卡設(shè)備,沒有數(shù)據(jù)的傳輸;
4、address(point-to-point) data transfercommands(adtc):由HOST發(fā)送到指定的卡設(shè)備且伴隨有數(shù)據(jù)傳輸。
指令格式:Card register
幾個(gè)主要的寄存器:OCR,CID,CSD,RCA和SCR。
Operation condition register(OCR):32位的OCR包含卡設(shè)備支持的工作電壓表;
Card identification number register (CID):包含用于在卡識(shí)別階段的卡信息,包括制造商ID,產(chǎn)品名等;
Card specific data register(CSD):CSD寄存器提供了如何訪問卡設(shè)備的信息,包括定義了數(shù)據(jù)格式,錯(cuò)誤校驗(yàn)類型,最大訪問次數(shù),數(shù)據(jù)傳輸率等;
Relative card address register(RCA):存放在卡識(shí)別階段分配的相對(duì)卡地址,缺省相對(duì)卡地址為0000h;
SD card configuration register(SCR):SCR是一個(gè)配置寄存器,用于配置SD memory card的特殊功能。
Response
所有的response都通過CMD線發(fā)送到host端,R4和R5響應(yīng)類型是SDIO中特有的:
1、R1(normal response command):用來響應(yīng)常用指令;
2、R2(CID,CSD register):用來響應(yīng)CMD2和CMD10或CMD9,并把CID或CSD寄存器作為響應(yīng)數(shù)據(jù);
3、R3(OCR register):用來響應(yīng)ACMD41指令,并把OCR寄存器作為響應(yīng)數(shù)據(jù);
4、R6(published RCA response):分配相對(duì)卡地址的響應(yīng);
5、R7(card interface condition):響應(yīng)CMD8,返回卡支持的電壓信息;
6、R4(CMD5):響應(yīng)CMD5,并把OCR寄存器作為響應(yīng)數(shù)據(jù);
7、R5(CMD52):CMD52是一個(gè)讀寫寄存器的指令,R5用于CMD52的響應(yīng);
Response 格式:
***詳情請(qǐng)參考spec***
四、SD初始化流程
當(dāng)host上電后,使所有的卡設(shè)備處于卡識(shí)別模式,完成設(shè)置有效操作電壓范圍,卡識(shí)別和請(qǐng)求卡相對(duì)地址等操作。
1、發(fā)送指令CMD0使卡設(shè)備處于idle狀態(tài);
2、發(fā)送指令CMD8,如果卡設(shè)備有response,說明此卡為SD2.0以上;
3、發(fā)送指令CMD55+ACMD41,該指令是用來探測卡設(shè)備的工作電壓是否符合host端的要求;在發(fā)送ACMD41這類指令之前需要先發(fā)送CMD55指令,在SDIO中ACMD41指令被CMD5替代。
4、發(fā)送指令CMD11轉(zhuǎn)換工作電壓到1.8V;
5、發(fā)送指令CMD2獲取CIA;
6、發(fā)送指令CMD3獲取RCA(relative card address)
SD初始化分析
系統(tǒng)上電時(shí),SDI控制器會(huì)去掃描總線上的所有設(shè)備,然后對(duì)掛在總線上卡設(shè)備進(jìn)行初始化。進(jìn)行掃描和初始化工作都是由mmc_scan函數(shù)來完成,以下是Linux驅(qū)動(dòng)中初始化流程圖(感謝同事Linkin的圖)。SDIO、SD和MMC這三者的初始化流程稍有不同,是向下兼容的。
五、SD卡調(diào)試關(guān)鍵點(diǎn):
1. 上電時(shí)要延時(shí)足夠長的時(shí)間給 SD 卡一個(gè)準(zhǔn)備過程,在我的程序里是 5 秒,根據(jù)不同的卡設(shè)置不同的延時(shí)時(shí)間。SD 卡初始化第一步在發(fā)送 CMD 命令之前,在片選有效的情況下首先要發(fā)送至少 74 個(gè)時(shí)鐘,否則將有可能出現(xiàn) SD 卡不能初始化的問題。
2. SD 卡發(fā)送復(fù)位命令 CMD0 后,要發(fā)送版本查詢命令 CMD8 ,返回狀態(tài)一般分兩種,若返回 0x01 表示此 SD 卡接受 CMD8, 也就是說此 SD 卡支持版本 2 ;若返回 0x05 則表示此 SD 卡支持版本 1 。因?yàn)椴煌姹镜?SD 卡操作要求有不一樣的地方,所以務(wù)必查詢 SD 卡的版本號(hào),否則也會(huì)出現(xiàn) SD 卡無法正常工作的問題。
3. 理論上要求發(fā)送 CMD58 獲得 SD 卡電壓參數(shù),但實(shí)際過程中由于事先都知道了 SD 卡的工作電壓,因此可省略這一步簡化程序。協(xié)議書上也建議盡量不要用這個(gè)命令。
4. SD 卡讀寫超時(shí)時(shí)間要按照協(xié)議說明書書上的給定值 ( 讀超時(shí):100ms ;寫超時(shí):250ms) ,這個(gè)值要在程序中準(zhǔn)確計(jì)算出來,否則將會(huì)出現(xiàn)不能正常讀寫數(shù)據(jù)的問題。我自己定義了一個(gè)計(jì)算公式:超時(shí)時(shí)間 =( 8/clk )*arg
5. 2GB 以內(nèi)的 SD 卡 ( 標(biāo)準(zhǔn)卡 ) 和 2GB 以上的 SD 卡 ( 大容量卡 ) 在地址訪問形式上不同,這一點(diǎn)尤其要注意,否則將會(huì)出現(xiàn)無法讀寫數(shù)據(jù)的問題。如標(biāo)準(zhǔn)卡在讀寫操作時(shí),對(duì)讀或?qū)懨盍钆飘?dāng)中的地址域符初值 0x10 ,表示對(duì)第 16 個(gè)字節(jié)以后的地址單元進(jìn)行操作 ( 前提是此 SD 卡支持偏移讀寫操作 ) ,而對(duì)大容量卡讀或?qū)懨盍钆飘?dāng)中的地址域符初值 0x10 時(shí),則表示對(duì)第 16 塊進(jìn)行讀寫操作,而且大容量卡只支持塊讀寫操作,塊大小固定為 512 字節(jié),對(duì)其進(jìn)行字節(jié)操作將會(huì)出錯(cuò)。
6. 對(duì)某一塊要進(jìn)行寫操作時(shí)最好先執(zhí)行擦出命令,這樣寫入的速度就能大大提高。進(jìn)行擦除操作時(shí)不管是標(biāo)準(zhǔn)卡還是大容量卡都按塊操作執(zhí)行,也就是一次擦除至少 512 字節(jié)。
7. 對(duì)標(biāo)準(zhǔn)卡進(jìn)行字節(jié)操作時(shí),起始和終止必須在一個(gè)物理扇區(qū)內(nèi),否則將不能進(jìn)行讀寫操作。實(shí)際操作過程中建議用塊操作以提高效率。不管是標(biāo)準(zhǔn)卡還是大容量卡一個(gè)讀寫命令只能對(duì)一個(gè)塊進(jìn)行操作,不允許跨物理層地址操作。
8. 在寫數(shù)據(jù)塊前要先寫入若干個(gè) dummy data 字節(jié),寫完一個(gè)塊數(shù)據(jù)時(shí),主機(jī)要監(jiān)測 MISO 數(shù)據(jù)線,如果從機(jī)處于忙狀態(tài)這根數(shù)據(jù)線會(huì)保持低電平,這樣主機(jī)就可以根據(jù)這根數(shù)據(jù)線的狀態(tài)以決定是否發(fā)送下一個(gè)命令,在從機(jī)沒有釋放 MISO 數(shù)據(jù)線之前,主機(jī)絕對(duì)不能執(zhí)行其他命令,否則將會(huì)導(dǎo)致寫入的數(shù)據(jù)出錯(cuò),而且從機(jī)也不會(huì)響應(yīng)主機(jī)的命令。
9. 在 SPI 模式下, CRC 校驗(yàn)是被忽略的,但依然要求主從機(jī)發(fā)送 CRC 碼,只是數(shù)值可以是任意值,一般主機(jī)的 CRC 碼通常設(shè)為 0x00 或 0xFF 。
讀多塊操作和寫多塊操作的傳輸停止形式不一樣,讀多塊操作時(shí)用用命令 CMD12 終止傳輸,而寫多塊操作時(shí)用 Stop Tran Token( 停止傳輸令牌,值為 0xFD) 終止傳輸。
1、初始化步驟:
(1)延時(shí)至少 74clock,等待SD卡內(nèi)部操作完成,在MMC協(xié)議中有明確說明。
(2)CS低電平選中SD卡。
(3) 發(fā)送 CMD0 ,需要返回 0x01 ,進(jìn)入 Idle 狀態(tài)
(4) 為了區(qū)別SD卡是2.0還是1.0,或是MMC卡,這里根據(jù)協(xié)議向上兼容的原理,首先發(fā)送只有SD2.0才有的命令CMD8,如果CMD8返回?zé)o錯(cuò)誤,則初步判斷為2.0卡,進(jìn)一步發(fā)送命令循環(huán)發(fā)送 CMD55+ACMD41 ,直到返回 0x00 ,確定SD2.0卡初始化成功,進(jìn)入Ready 狀態(tài),再發(fā)送CMD58命令來判斷是HCSD還是SCSD,到此SD2.0卡初始化成功 。如果CMD8返回錯(cuò)誤則進(jìn)一步判斷為1.0卡還是MMC卡,循環(huán)發(fā)送CMD55+ACMD41 ,返回?zé)o錯(cuò)誤,則為SD1.0卡,到此SD1.0卡初始成功,如果在一定的循環(huán)次數(shù)下,返回為錯(cuò)誤,則進(jìn)一步發(fā)送CMD1進(jìn)行初始化,如果返回?zé)o錯(cuò)誤,則確定為MMC卡,如果在一定的次數(shù)下,返回為錯(cuò)誤,則不能識(shí)別該卡,初始結(jié)束。
(5)CS拉高。
2、讀步驟:
(1) 發(fā)送 CMD17 (單塊)或 CMD18 (多塊)讀命令,返回 0x00
(2) 接收數(shù)據(jù)開始令牌 0xfe (或 0xfc ) + 正式數(shù)據(jù) 512Bytes + CRC 校驗(yàn) 2Bytes, 默認(rèn)正式傳輸?shù)臄?shù)據(jù)長度是 512Bytes ,可用 CMD16 設(shè)置塊長度。
3、 寫步驟:
(1) 發(fā)送 CMD24 (單塊)或 CMD25 (多塊)寫命令,返回 0x00
(2) 發(fā)送數(shù)據(jù)開始令牌 0xfe (或 0xfc ) + 正式數(shù)據(jù) 512Bytes + CRC 校驗(yàn) 2Bytes
4、 擦除步驟:
(1) 發(fā)送 CMD32 ,跟一個(gè)參數(shù)來指定首個(gè)要擦除的起始地址( SD 手冊(cè)上說是塊號(hào))
(2) 發(fā)送 CMD33, ,指定最后的地址
(3) 發(fā)送 CMD38 ,擦除指定區(qū)間的內(nèi)容
此 3 步順序不能顛倒。
六、SD卡的命令格式及解析
1.SD卡命令組成
SD卡的指令由6字節(jié)(Byte)組成,如下:
Byte1:0 1 x x x x x x(命令號(hào),由指令標(biāo)志定義,如CMD39為100111即16進(jìn)制0x27,那么完整的CMD39第一字節(jié)為01100111,即0x27+0x40)
Byte2-5:Command Arguments,命令參數(shù),有些命令沒有參數(shù)
Byte6:前7位為CRC(Cyclic Redundacy Check,循環(huán)冗余校驗(yàn))校驗(yàn)位,最后一位為停止位0
2.SD卡的命令
SD卡命令共分為12類,分別為class0到class11,不同的SDd卡,主控根據(jù)其功能,支持不同的命令集,如下:
Class0 :(卡的識(shí)別、初始化等基本命令集)
CMD0:復(fù)位SD 卡.
CMD1:讀OCR寄存器.
CMD9:讀CSD寄存器.
CMD10:讀CID寄存器.
CMD12:停止讀多塊時(shí)的數(shù)據(jù)傳輸
CMD13:讀 Card_Status 寄存器
Class2 (讀卡命令集):
CMD16:設(shè)置塊的長度
CMD17:讀單塊.
CMD18:讀多塊,直至主機(jī)發(fā)送CMD12為止 .
Class4(寫卡命令集) :
CMD24:寫單塊.
CMD25:寫多塊.
CMD27:寫CSD寄存器 .
Class5 (擦除卡命令集):
CMD32:設(shè)置擦除塊的起始地址.
CMD33:設(shè)置擦除塊的終止地址.
CMD38: 擦除所選擇的塊.
Class6(寫保護(hù)命令集):
CMD28:設(shè)置寫保護(hù)塊的地址.
CMD29:擦除寫保護(hù)塊的地址.
CMD30: Ask the card for the status of the write protection bits
class7:卡的鎖定,解鎖功能命令集
class8:申請(qǐng)?zhí)囟罴?。
class10 -11 :保留
3.有關(guān)sd卡驅(qū)動(dòng)和fat fs的實(shí)現(xiàn)用了3個(gè)文件來實(shí)現(xiàn)。
sdboot.c為sd的驅(qū)動(dòng)(可理解為pdd)層,主要實(shí)現(xiàn)一些對(duì)sd控制器的配置以及一些基本sd命令的實(shí)現(xiàn)和對(duì)sd 卡的操作。
sdmmc.c實(shí)現(xiàn)了從sd卡讀取nk并跳到內(nèi)存去運(yùn)行的代碼(基本可以理解為sd驅(qū)動(dòng)的mdd層)。
sdfat.c文件就是實(shí)現(xiàn)fat fs的。mdd層通過fatfs來對(duì)pdd層操作以實(shí)現(xiàn)讀取文件。
在整個(gè)過程中遇到了很多問題,現(xiàn)在列舉如下:
1)sd卡初始化問題
配置gpio有關(guān)sd的功能:SDCMD, SDDAT[3:0]。
使能CLKCON中的SDI位。
時(shí)鐘以及計(jì)算公式:SDIPRE = PCLK/(CLK)-1;INICLK=300000;SDCLK=24000000;MMCCLK= 15000000
cmd0-cmd55-cmd41-cmd2-cmd3-cmd7-cmd6-cmd17
2)對(duì)sd卡操作問題
SD卡包括:一個(gè)標(biāo)識(shí)寄存器CID,一個(gè)相應(yīng)地址寄存器RCA,一個(gè)其他參數(shù)寄存器CSD。
對(duì)sd卡的操作是驅(qū)動(dòng)通過sd controller來發(fā)相應(yīng)的命令以達(dá)到讀寫等操作 的:發(fā)送命令通過SDICmdCon[7:0]的除了開始2bit:CmdIndex放置要發(fā)送的命令號(hào);SDICmdCon[8]開始發(fā)送命令來完成的。
檢測卡的插入,直接用中斷引腳的電平來判斷。
判斷插入的卡是否是sd卡,用命令cmd55和cmd41,因?yàn)閙mc卡對(duì)cmd55不做回應(yīng)。
命令9 就是獲取sd卡中csd寄存器的值的,該值包括很多sd卡的信息,其中就有sd卡的容量。這個(gè)值在sd卡接收到cmd9之后會(huì)以response的形式存放在sd控制器的SDI Response Register[0,1,2,3]中。在執(zhí)行cmd9,cmd10等這樣的命令的時(shí)候,卡的狀態(tài)應(yīng)該是不選中的,或直接在執(zhí)行它們之前發(fā)送 cmd7(0)不選中卡,不然的話會(huì)timeout。
用cmd17 來讀取單個(gè)block的數(shù)據(jù),該命令要帶地址參數(shù)(該參數(shù)通過cmd3命令來獲取),然后根據(jù)SDIDSTA和SDIFSTA狀態(tài)值來從sd 控制器的SDIDAT寄存器中讀出要讀的數(shù)據(jù)。該命令與cmd9相反,在執(zhí)行它之前要選中卡。讀完一個(gè)block之后要做一些善后工作,為下次讀取做好準(zhǔn)備,不然的話checkcmdend就要一直循環(huán)了。因?yàn)橛玫氖敲看味甲x一個(gè)block,并地址要以block對(duì)齊,這樣就要考慮要讀取的地址是否是 block對(duì)齊的,長度是否夠一個(gè)block。
SDIDCON這個(gè)數(shù)據(jù)控制寄存器也很重要,一些對(duì)數(shù)據(jù)的操作形式就是在這里設(shè)置的。
3)fat文件系統(tǒng)問題
根據(jù)MBR找到分區(qū)表,根據(jù)分區(qū)表找到該分區(qū)MBR[446B+4個(gè)分區(qū)表(每個(gè)16B)+2B結(jié)束符)
分區(qū)表中的第9-12字節(jié)為該分區(qū)的啟始地址(單位沒sector),第13-16字節(jié)為分區(qū)的長度(單位也是sector)
總結(jié)
以上是生活随笔為你收集整理的cmd52命令发送 mmc_乾坤合一~Linux SD/MMC/SDIO驱动分析(上)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python漏洞检测脚本_URL重定向漏
- 下一篇: begintrans返回值_SQL事务回