[sd card] sd card初始化流程
以SD 3.0為例。
建議先參考《[sd card] SD card初始化時(shí)的總線設(shè)置》。
一、sd card初始化流程思路說明
通過《SD_Ver3.00_Final_090416》協(xié)議中“4.2 Card Identification Mode ”和“4.3 Data Transfer Mode ”來進(jìn)行說明。
1、sd card操作模式和卡狀態(tài)
通過
sd card有如上card狀態(tài)以及對(duì)應(yīng)的操作模式。
inactive mode
非激活模式。當(dāng)host提供的電壓不在card的電壓的可用范圍之內(nèi)時(shí),會(huì)進(jìn)入這種狀態(tài)。
這種狀態(tài)下,card不會(huì)響應(yīng)任何命令。card identification mode
card識(shí)別模式,host激活card和識(shí)別card的模式。
這些操作都是在card對(duì)應(yīng)的CMD線上完成,并且在card identification mode模式下的所有通訊都只能在CMD線上完成。
在卡識(shí)別的過程中,card應(yīng)該工作在f-OD的工作頻率下。data transefer mode
數(shù)據(jù)傳輸模式,在這種模式下,host和card可以根據(jù)data線來傳輸數(shù)據(jù)
2、card identification mode流程說明
整個(gè)card identification mode都是外部對(duì)于sd card的初始化過程。
如下圖所示:
- 操作條件
卡識(shí)別模式。參考《SD_Ver3.00_Final_090416》“4.2 Card Identification Mode ”
顧名思義,就是識(shí)別card的一個(gè)模式。一個(gè)mmc總線上可以接多張card,因此需要在這個(gè)模式下識(shí)別和激活對(duì)應(yīng)的card并使之進(jìn)入對(duì)應(yīng)的模式。
在卡識(shí)別模式下,host會(huì)先復(fù)位所有在Card Identification Mode下的card,驗(yàn)證操作電壓的范圍,辨認(rèn)card并且分配給其對(duì)應(yīng)的RCA地址。
這些操作都是在card對(duì)應(yīng)的CMD線上完成,并且在card identification mode模式下的所有通訊都只能在CMD線上完成。
在卡識(shí)別的過程中,card應(yīng)該工作在f-OD的工作頻率下。
通過上述表格可以看出Card Identification Mode下,時(shí)鐘頻率不能超過400kHz。
card identification mode下有如下幾種操作
card reset
GO_IDLE_STATE(CMD0)命令是軟件復(fù)位命令,并且是一個(gè)廣播指令,可以使所有的card進(jìn)入idle狀態(tài)(除了處于inactive狀態(tài)的card)。
如果是通過上電操作進(jìn)行的復(fù)位,那么所有的card都會(huì)直接進(jìn)入idle狀態(tài),也包括之前處于inactive狀態(tài)的card。
不論是CMD0或這是power-on進(jìn)行的復(fù)位,所有被復(fù)位的card的CMD線都會(huì)處于input狀態(tài),等待下一次命令的起始位。同時(shí),所有card會(huì)簡(jiǎn)單的初始化,將其RCA地址設(shè)置為0x0000,并且設(shè)置一個(gè)默認(rèn)的驅(qū)動(dòng)強(qiáng)度模式。operation condition validation
這個(gè)操作是用于驗(yàn)證card的操作條件。
在開始host和card的通訊之前,host并不知道card支持的工作電壓,并且card也不知道當(dāng)前host提供的電壓是多少。在這種情況下,host會(huì)先假設(shè)card支持某個(gè)電壓并且將card的工作電壓設(shè)置成該電壓,然后發(fā)送給card復(fù)位命令CMD0。
為了驗(yàn)證host假定的電壓是否被card支持,SD 2.0協(xié)議中定義了一個(gè)新的命令CMD8。SEND_IF_COND(CMD8)命令是用來驗(yàn)證sd card接口的操作條件。card會(huì)通過分析SEND_IF_COND(CMD8)命令的參數(shù)來判斷host的操作條件的正確性(也就是工作電壓是否在card支持的范圍之內(nèi)),card把SEND_IF_COND(CMD8)命令的參數(shù)中的VHS域(注意,同時(shí)只能有1個(gè)bit被設(shè)置成1)當(dāng)作當(dāng)前host提供的工作電壓以此來判斷是否當(dāng)前的供電電壓是否符合。如果card檢測(cè)到供電電壓符合操作條件的話,會(huì)在response中返回自己支持的工作電壓。如果不符合的話,不會(huì)返回response并且仍處于idle狀態(tài)。host也會(huì)根據(jù)SEND_IF_COND(CMD8)命令的response中的VHS域來獲取card支持的工作電壓。注意,CMD8并不會(huì)因此card狀態(tài)發(fā)生變化,這種功能也可以通過ACMD41來實(shí)現(xiàn)!!!
ocr寄存器如下,主要關(guān)注VHS域:
- card initialization
card的內(nèi)部初始化是在card處理非0參數(shù)ACMD41命令的過程中完成的。
- 首先看一下ACMD41的命令格式
- 在看一下ACMD41的response的格式
注意,host必須根據(jù)自己的狀態(tài)來設(shè)置ACMD41的參數(shù)。并且不斷發(fā)送ACMD41給card直到檢測(cè)到busy為1,此時(shí)的CCS和S18A才是可靠的。隨后,card進(jìn)入了ready state。
card bus signal voltage switch
通常card剛上電的情況下,其信號(hào)電壓一般都是處于3.3V的模式。當(dāng)card進(jìn)入ready狀態(tài)后,為了節(jié)省功耗,首先需要考慮是是否需要切換信號(hào)電壓到1.8V。
前面說過,如果host支持輸出1.8V的信號(hào)電壓的話,會(huì)將ACMD41的參數(shù)的S18R(bit24)設(shè)置為1來告訴card。當(dāng)card收到這個(gè)ACMD41時(shí),如果自己允許切換到1.8V的信號(hào)電壓模式,那么就設(shè)置response的S18A(bit24)設(shè)置為1,否則設(shè)置為0。
當(dāng)host從response的S18A(bit24)解析出1的時(shí)候,可以向card發(fā)送CMD11命令,來通知card準(zhǔn)備切換到1.8V的信號(hào)電壓模式了。隨后,host就可以將自己的輸出的信號(hào)電壓切換到1.8V了。
此時(shí),card還是處于ready state。card identification process
card識(shí)別過程。
host會(huì)向card發(fā)送ALL_SEND_CID(CMD2)命令來要求card發(fā)送它們各自獨(dú)一無二的cid寄存器的值。一旦card收到這條命令并且向host發(fā)送了自己的CID值,就會(huì)直接進(jìn)入到identification state。
隨后,host會(huì)通過SEND_RELATIVE_ADDR(CMD3)命令來要求card自己編一個(gè)RCA地址并通過response返回給host,隨后card就會(huì)進(jìn)入stand-by模式。而RCA地址則會(huì)作為在transfer mode中,該card的通訊地址。注意,如果host對(duì)于card自己發(fā)布的這個(gè)地址不滿意,可以重復(fù)發(fā)送CMD2要求card修改RCA地址直到自己滿意為止。
3、data transfer mode中和初始化相關(guān)的流程
通過identification mode之后,工作電壓和信號(hào)電壓都已經(jīng)設(shè)置完成。但是總線寬度和總線速度模式并沒有設(shè)置。剛power-on或者是剛執(zhí)行CMD0命令的card的總線寬度為1,總線速度模式為DS模式。而這部分內(nèi)容的設(shè)置則是在data transfer mode中實(shí)現(xiàn)的!!!
總線速度模式的設(shè)置
參考《SD_Ver3.00_Final_090416》協(xié)議中“4.2 Card Identification Mode ”和“4.3 Data Transfer Mode ”來進(jìn)行說明。
總線速度模式的設(shè)置主要以依賴于CMD6。說明
switch function command(CMD6)是用來切換或者擴(kuò)展card的function。當(dāng)前有四個(gè)function組定義如下:
(1)Access mode:訪問模式,用于選擇SD總線接口的速度模式(也就是我們這里的目標(biāo))
(2)Command system:命令系統(tǒng),可以通過共享命令集來擴(kuò)展和控制一個(gè)特殊的功能
(3)Driver strength:驅(qū)動(dòng)強(qiáng)度,在UHS-I模式下用于選擇一個(gè)合適的驅(qū)動(dòng)信號(hào)強(qiáng)度,取決于host的環(huán)境
(4)Current limit:電流限制,在UHS-I模式下設(shè)置card的最大電流,由host的供電屬性決定
CMD6只有在transfer state下才是可用的。一旦card復(fù)位之后,所有g(shù)roup默認(rèn)都選中function0.
card會(huì)返回R1 response(CMD線)以及512bit的狀態(tài)數(shù)據(jù)(DAT線)作為對(duì)host的CMD6的響應(yīng)。從sd傳輸標(biāo)準(zhǔn)上看,CMD6相當(dāng)于一個(gè)單塊讀命令、超時(shí)時(shí)間是100ms。
card對(duì)于對(duì)于CMD6的切換動(dòng)作會(huì)在狀態(tài)數(shù)據(jù)傳輸完之后的8個(gè)時(shí)鐘之內(nèi)完成。當(dāng)CMD6導(dǎo)致總線行為(例如總線速度模式)發(fā)生變化后,host要求至少要等CMD6傳輸完成之后的8個(gè)時(shí)鐘之后才允許使用新的總線行為進(jìn)行通訊。CMD6的模式
CMD6有兩種模式,分別是check function模式和set function模式。
(1)check function模式用來查詢card所支持的function
(2)set function模式用來切換card的functionality
狀態(tài)圖如下:
- card的group和function
sd card支持6個(gè)function group,每個(gè)group最多支持16個(gè)function。如下圖所示,
- mode 1 operation——set function
CMD6 mode 1用來切換card的functionality。
CMD6切換總線模式為HS模式的示例如下 :
綜上,可以在card處于transfer state的情況下,host向card發(fā)送CMD6命令,參數(shù)設(shè)置為“1<<31 | 0xffff00 | 總線速度模式的function”,來實(shí)現(xiàn)card的總線速度模式的切換。
- 總線寬度的設(shè)置
參考“ 4.3.1 Wide Bus Selection/Deselection ”
上電之后或者執(zhí)行CMD0命令之后,card的總線寬度模式總是默認(rèn)設(shè)置為1bit模式。
可以通過ACMD6來設(shè)置card的總線寬度模式。ACMD6要求card處于transfer state,并且處于unlock狀態(tài)。
二、在sd card初始化過程中,host要做的事情
1、命令流程
參考《SD_Ver3.00_Final_090416》協(xié)議中“3.9.4 Bus Speed Modes Selection Sequence ”
從“一、sd card初始化流程思路說明”中,可以得到host在初始化card的過程中,需要向其發(fā)送如下命令序列。
2、host流程說明
根據(jù)card的外部初始化流程,可以簡(jiǎn)單整理出host在sd各個(gè)狀態(tài)下需要做的操作流程如下(黑體部分是我們這里重點(diǎn)關(guān)心的部分):
未上電狀態(tài)
- (1)準(zhǔn)備好工作電壓、信號(hào)電壓,上電
- (2)準(zhǔn)備好時(shí)鐘(400kHz)
idle state
- (1)嘗試獲取一個(gè)合適的工作電壓
host發(fā)送CMD0命令進(jìn)行復(fù)位
host發(fā)送CMD8命令,告訴card,host可以支持SD2.0。card收到CMD8命令之后會(huì)使能自己符合SD2.0的一些新功能
host發(fā)送參數(shù)為0的ACMD41命令,提取response中的VHS,得到card支持的工作電壓范圍
host選擇一個(gè)card和host都支持的最低的工作電壓,并將host提供給card的工作電壓設(shè)置為這個(gè)值。
這個(gè)值就是合法的,后續(xù)就以這個(gè)ocr作為工作電壓重新復(fù)位開始對(duì)sd card真正的初始化過程. - (2)重新復(fù)位,完成card的內(nèi)部初始化
host發(fā)送CMD0命令進(jìn)行復(fù)位
host發(fā)送CMD8命令,告訴card,host可以支持SD2.0。card收到CMD8命令之后會(huì)使能自己符合SD2.0的一些新功能。同時(shí),獲取到ocr寄存器的值。
host根據(jù)host是否支持SDHC來設(shè)置ocr的HCS、是否支持1.8V來設(shè)置ocr的S18R,將設(shè)置好的ocr作為ACMD41的參數(shù),發(fā)送給card。
host讀取ACMD41的busy位來判斷card的內(nèi)部初始化是否完成,如果沒有完成繼續(xù)發(fā)送ACMD41
一旦card的內(nèi)部初始化完成,則card進(jìn)入ready state。
- (1)嘗試獲取一個(gè)合適的工作電壓
ready state
- (1)設(shè)置信號(hào)電壓
host根據(jù)ACMD41的response提取對(duì)應(yīng)的S18A,如果為1,說明card支持切換到信號(hào)電壓為1.8V的模式。
host發(fā)送CMD11命令,要求card切換到1.8V的信號(hào)電壓模式。
host切換提供給card的信號(hào)電壓為1.8V。 - (2)獲取card的CID值
host發(fā)送CMD2命令,要求card回復(fù)其CID寄存器的值。
一旦card返回response之后,進(jìn)入identification state。
- (1)設(shè)置信號(hào)電壓
identification state
- (1)獲取card的RCA值
host發(fā)送CMD3命令,要求card回復(fù)其RCA值。
一旦card通過response返回這個(gè)RCA之后,進(jìn)入stand-by state。
identification mode也就完成了。
- (1)獲取card的RCA值
stand-by state——》transfer state
- (1)獲取sd card的特殊數(shù)據(jù)寄存器
csd寄存器中存儲(chǔ)了sd card的一些信息。
host發(fā)送CMD9命令,要求card回去其CSD寄存器(card specific data)的值 - (2)切換到transfer state模式
后續(xù)的初始化操作需要在transfer state下進(jìn)行,所以需要發(fā)送CMD7命令選中對(duì)應(yīng)的card,將card切換到transfer state - (3)獲取sd card的配置寄存器和狀態(tài)寄存器
host發(fā)送ACMD51命令,要求card回復(fù)其SCR寄存器(SD configuration register)的值
host發(fā)送ACMD13命令,要求card回復(fù)其SSR寄存器(SD status regiter)的值 - (4)讀取card 的switch狀態(tài),也就是其支持的function
host發(fā)送CMD6命令來讀取card switch status。
通過card switch status可以得到card支持的總線速度模式以及驅(qū)動(dòng)強(qiáng)度類型。 - (5)切換總線寬度
host發(fā)送ACMD11命令,要求card將總線寬度切換到4bit模式
設(shè)置host自身的總線寬度為4bit模式 - (6)選擇合適的總線速度模式、驅(qū)動(dòng)強(qiáng)度、以及限流并進(jìn)行設(shè)置
host從host和card都支持的總線速度模式中選擇一個(gè)最優(yōu)的模式。
host根據(jù)選擇的總線速度模式,來選擇對(duì)應(yīng)的驅(qū)動(dòng)類型以及限流值,通過CMD6命令讓card進(jìn)行相應(yīng)值的切換。
host發(fā)送CMD6命令、并且mode=1、group=0、function=總線速度模式碼,card收到命令之后會(huì)切換到相應(yīng)的總線速度模式上。
設(shè)置host自身的總線速度模式(時(shí)序,timing)。 - (7)執(zhí)行tuning操作
對(duì)于UHS-I的card來說,如果處于uhs的速度模式,host需要發(fā)送CMD19執(zhí)行tuning操作以獲取一個(gè)最佳的采樣點(diǎn)。
- (1)獲取sd card的特殊數(shù)據(jù)寄存器
到此,host對(duì)于sd card的初始化就完成了。
三、host初始化sd card代碼分析
整個(gè)代碼設(shè)計(jì)是圍繞著“在sd card初始化過程中,host要做的事情”的思想來設(shè)計(jì)的。
因此,可以看代碼的過程中,回頭看看前面的設(shè)計(jì)思想。了解了上述的初始化流程之后再來看代碼會(huì)感覺比較容易理解。
對(duì)應(yīng)代碼drivers/mmc/core/sd.c、drivers/mmc/driver/core/sd-ops.c
1、mmc_rescan_try_freq
在《[mmc subsystem] mmc core(第六章)——mmc core主模塊》中已經(jīng)說明過了當(dāng)host檢測(cè)到card插入的情況下,最終會(huì)調(diào)用mmc_rescan_try_freq來識(shí)別和初始化card。
和sd相關(guān)的部分如下:
2、mmc_attach_sd
去掉無關(guān)的代碼部分如下:
int mmc_attach_sd(struct mmc_host *host) {int err;u32 ocr;int retries;/** 以下部分,連同mmc_rescan_try_freq中的mmc_go_idle和mmc_send_if_cond一起構(gòu)成了“嘗試獲取一個(gè)合適的工作電壓” 的任務(wù) **/err = mmc_send_app_op_cond(host, 0, &ocr);// host發(fā)送參數(shù)為0的ACMD41命令,提取response中的VHS,得到card支持的工作電壓范圍mmc_sd_attach_bus_ops(host); // 設(shè)置bus操作集為mmc_sd_ops_unsafe或者mmc_sd_ops,mmc subsystem的內(nèi)容,這里我們不關(guān)心if (host->ocr_avail_sd)host->ocr_avail = host->ocr_avail_sd;host->ocr = mmc_select_voltage(host, ocr);// host選擇一個(gè)card和host都支持的最低的工作電壓,并將host提供給card的工作電壓設(shè)置為這個(gè)值。// 后續(xù)就以host->ocr作為工作電壓對(duì)sd card進(jìn)行初始化retries = 5;while (retries && !host->rescan_disable) { /** 上述已經(jīng)完成了card的識(shí)別操作,并且為card選擇了一個(gè)合適的工作電壓 **/ /** 后續(xù)調(diào)用mmc_sd_init_card對(duì)sd card進(jìn)行初始化,也就是代碼核心 **/err = mmc_sd_init_card(host, host->ocr, NULL);if (err) {retries--;mmc_power_off(host); // 如果初始化失敗的情況下,需要重新掉電并上電,再嘗試進(jìn)行初始化usleep_range(5000, 5500);mmc_power_up(host);mmc_select_voltage(host, host->ocr);continue;}break;}mmc_release_host(host);err = mmc_add_card(host->card);mmc_claim_host(host);mmc_init_clk_scaling(host);return 0; }3、mmc_sd_init_card
mmc_sd_init_card是在已經(jīng)確定了host提供給card的工作電壓值的情況下,用來對(duì)sd card進(jìn)行初始化的操作。
* 結(jié)合第二節(jié),可以知道m(xù)mc_sd_init_card主要有如下工作(黑體的部分是我們重點(diǎn)關(guān)心的部分):
- 重新復(fù)位,完成card的內(nèi)部初始化
- 設(shè)置信號(hào)電壓,包括card和host的設(shè)置
- 獲取card的CID值
- 獲取card的RCA值
- 獲取sd card的特殊數(shù)據(jù)寄存器
- 切換到transfer state模式
- 獲取sd card的配置寄存器和狀態(tài)寄存器
- 讀取card 的switch狀態(tài),也就是其支持的function
- 切換總線寬度,包括card和host的設(shè)置
- 選擇合適的總線速度模式、驅(qū)動(dòng)強(qiáng)度、以及限流并進(jìn)行設(shè)置,包括card和host的設(shè)置
- 執(zhí)行tuning操作
- 代碼如下:
4、mmc_sd_get_cid
在上面mmc_sd_init_card中被調(diào)用。從idle state到identification state的一個(gè)過程。
* 在mmc_sd_get_cid中的重要工作如下
- 重新復(fù)位,完成card的內(nèi)部初始化
- 設(shè)置信號(hào)電壓,包括card和host的設(shè)置
- 獲取card的CID值
- 代碼如下:
5、mmc_sd_init_uhs_card
在上面mmc_sd_init_card中被調(diào)用。用來初始化uhs card的總線工作模式。
主要工作如下:
- 切換總線寬度,包括card和host的設(shè)置
- 選擇合適的總線速度模式、驅(qū)動(dòng)強(qiáng)度、以及限流并進(jìn)行設(shè)置,包括card和host的設(shè)置
- 執(zhí)行tuning操作
代碼如下:
以上總線設(shè)置部分的詳細(xì)內(nèi)容建議參考《[sd card] SD card初始化時(shí)的總線設(shè)置》
總結(jié)
以上是生活随笔為你收集整理的[sd card] sd card初始化流程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PyTorch线程池泄露Leaking
- 下一篇: 我和CSDN的故事(CDSN成立20周年