Linux MMC原理及框架詳解

目錄

1. 背景

1.1基本概念

1.2 規範簡介

1.2.1 卡的規範

1.2.2 總線規範

2. eMMC原理介紹

2.1 eMMC內部結構簡介

2.1.2 Flash Controller

2.1.3 Host Interface

2.2分區管理

2.3總線協議

3. Linux MMC軟件框架流程

3.1軟件架構

3.2工作流程

參考文檔


本文參考資料主要來源於網絡,原文網址會在文末附上。整理本文的原因,一是爲了自己學習記錄;二也是爲了分享出來幫助別人。如有打擾,盡請諒解。

1. 背景

1.1基本概念

MMC是MultiMediaCard的簡稱,從本質上看,它是一種用於固態非易失性存儲的內存卡(memory card)規範,定義了諸如卡的形態、尺寸、容量、電氣信號、和主機之間的通信協議等方方面面的內容。

從1997年MMC規範發佈至今,基於不同的考量(物理尺寸、電壓範圍、管腳數量、最大容量、數據位寬、clock頻率、安全特性、是否支持SPI mode、是否支持DDR mode、等等),進化出了MMC、SD、microSD、SDIO、eMMC等不同的規範(如下面圖片1所示)。雖然亂花迷人,其本質終究還是一樣的,絲毫未變,這就是Linux kernel將它們統稱爲MMC的原因。

圖1.MMC/SD/SDIO演進圖

 

關於該圖片,這裏強調幾點(其它的,大家可參考[1][2],不再詳細介紹):

  • MMC、SD、SDIO的技術本質是一樣的(使用相同的總線規範,等等),都是從MMC規範演化而來;
  • MMC強調的是多媒體存儲(MM,MultiMedia);
  • SD強調的是安全和數據保護(S,Secure);
  • SDIO是從SD演化出來的,強調的是接口(IO,Input/Output),不再關注另一端的具體形態(可以是WIFI設備、Bluetooth設備、GPS等等)。

1.2 規範簡介

MMC分別從卡(Card Concept)、總線(Bus Concept)以及控制器(Host Controller)三個方面,定義MMC system的行爲,如下所示:

圖2.MMC/SD/SDIO硬件框圖

1.2.1 卡的規範

卡的規範主要規定卡的形狀、物理尺寸、管腳,內部block組成、寄存器等等,以eMMC爲例[3]:

圖3.Card Concept(eMMC)

1)有關形狀、尺寸的內容,這裏不再介紹,感興趣的同學可參考[1]。

2)卡的內部由如下幾個block組成:

  • Memory core,存儲介質,一般是NAND flash、NOR flash等;
  • Memory core interface,管理存儲介質的接口,用於訪問(讀、寫、擦除等操作)存儲介質;
  • Card interface(CMD、CLK、DATA),總線接口,外界訪問卡內部存儲介質的接口,和具體的管腳相連;
  • Card interface controller,將總線接口上的協議轉換爲Memory core interface的形式,用於訪問內部存儲介質;
  • Power模塊,提供reset、上電檢測等功能;
  • 寄存器(圖片3中位於Card interface controller的左側,那些小矩形),用於提供卡的信息、參數、訪問控制等功能。

3)卡的管腳有VDD、GND、RST、CLK、CMD和DATA等,VDD和GND提供power,RST用於復位,CLK、CMD和DATA爲MMC總線協議(具體可參考下一小節)的物理通道:

  • CLK有一條,提供同步時鐘,可以在CLK的上升沿(或者下降沿,或者上升沿和下降沿)採集數據;
  • CMD有一條,用於傳輸命令(CMD)及響應(Response)。
  • DATA用於傳輸雙向的數據,根據MMC的類型,可以有一條(1-bit)、四條(4-bit)或者八條(8-bit)。

4)以eMMC爲例,規範定義了OCR, CID, CSD, EXT_CSD, RCA 以及DSR 6組寄存器,具體含義請參考手冊[3]。

1.2.2 總線規範

前面我們提到過,MMC的本質是提供一套可以訪問固態非易失性存儲介質的通信協議,從產業化的角度看,這些存儲介質一般集成在一個獨立的外部模塊中(卡、WIFI模組等),通過物理總線和CPU連接。對任何有線的通信協議來說,總線規範都是非常重要的。關於MMC總線規範,簡單總結如下:

1)物理信號有CLK、CMD和DATA三類。

2)電壓範圍爲1.65V和3.6V(參考上面圖片2),根據工作電壓的不同,MMC卡可以分爲兩類:

  • High Voltage MultiMediaCard,工作電壓爲2.7V~3.6V。
  • Dual Voltage MultiMediaCard,工作電壓有兩種,1.70V~1.95V和2.7V~3.6V,CPU可以根據需要切換。

3)數據傳輸的位寬(稱作data bus width mode)是允許動態配置的,包括1-bit (默認)模式、4-bit模式和8-bit模式。

注:不使用的數據線,需要保持上拉狀態,這就是圖片2中的DATA中標出上拉的原因。另外,由於數據線寬度是動態可配的,這要求CPU可以動態的enable/disable數據線的那些上拉電阻

4)MMC規範定義了CLK的頻率範圍,包括0-20MHz、0-26MHz、0-52MHz等幾種,結合數據線寬度,基本決定了MMC的訪問速度。

5)總線規範定義了一種簡單的、主從式的總線協議,MMC卡爲從機(slave),CPU爲主機(Host)。

6)協議規定了三種可以在總線上傳輸的信標(token):

  • Command,Host通過CMD線發送給Slave的,用於啓動(或結束)一個操作(後面介紹);
  • Response,Slave通過CMD線發送給Host,用於迴應Host發送的Command;
  • Data,Host和Slave之間通過數據線傳輸的數據。方向可以是Host到Slave,也可以是Slave到Host。數據線的根數可以是1、4或者8。在每一個時鐘週期,每根數據線上可以傳輸1bit或者2bits的數據。

7)一次數據傳輸過程,需要涉及所有的3個信標。一次數據傳輸的過程也稱作Bus Operation,根據場景的不同,MMC協議規定了很多類型的Bus Operation(具體可參考相應的規範)。

2. eMMC原理介紹

2.1 eMMC內部結構簡介

eMMC 是 embedded MultiMediaCard 的簡稱。MultiMediaCard,即 MMC, 是一種閃存卡(Flash Memory Card)標準,它定義了 MMC 的架構以及訪問 Flash Memory 的接口和協議。而 eMMC 則是對 MMC 的一個拓展,以滿足更高標準的性能、成本、體積、穩定、易用等的需求。

eMMC 的整體架構如下圖片所示:

圖4. eMMC 整體框圖

eMMC 內部主要可以分爲 Flash Memory、Flash Controller 以及 Host Interface 三大部分。

2.1.1 Flash Memory

Flash Memory 是一種非易失性的存儲器,通常在嵌入式系統中用於存放系統、應用和數據等,類似與 PC 系統中的硬盤。

目前,絕大部分手機和平板等移動設備中所使用的 eMMC 內部的 Flash Memory 都屬於 NAND Flash。eMMC 標準中,將內部的 Flash Memory 劃分爲 4 類區域,最多可以支持 8 個硬件分區,如下圖所示:

圖5.eMMC分區圖

  • BOOT Area Partition 1 & 2
    此分區主要是爲了支持從 eMMC 啓動系統而設計的。
    該分區的數據,在 eMMC 上電後,可以通過很簡單的協議就可以讀取出來。同時,大部分的 SOC 都可以通過 GPIO 或者 FUSE 的配置,讓 ROM 代碼在上電後,將 eMMC BOOT 分區的內容加載到 SOC 內部的 SRAM 中執行。
  • RPMB Partition
    RPMB 是 Replay Protected Memory Block 的簡稱,它通過 HMAC SHA-256 和 Write Counter 來保證保存在 RPMB 內部的數據不被非法篡改。
    在實際應用中,RPMB 分區通常用來保存安全相關的數據,例如指紋數據、安全支付相關的密鑰等。
  • General Purpose Partition 1~4
    此區域則主要用於存儲系統或者用戶數據。 General Purpose Partition 在芯片出廠時,通常是不存在的,需要主動進行配置後,纔會存在。
  • User Data Area
    此區域則主要用於存儲系統和用戶數據。
    User Data Area 通常會進行再分區,例如 Android 系統中,通常在此區域分出 boot、system、userdata 等分區。

2.1.2 Flash Controller

NAND Flash 直接接入 Host 時,Host 端通常需要有 NAND Flash Translation Layer,即 NFTL 或者 NAND Flash 文件系統來做壞塊管理、ECC等的功能。

eMMC 則在其內部集成了 Flash Controller,用於完成擦寫均衡、壞塊管理、ECC校驗等功能。相比於直接將 NAND Flash 接入到 Host 端,eMMC 屏蔽了 NAND Flash 的物理特性,可以減少 Host 端軟件的複雜度,讓 Host 端專注於上層業務,省去對 NAND Flash 進行特殊的處理。同時,eMMC 通過使用 Cache、Memory Array 等技術,在讀寫性能上也比 NAND Flash 要好很多。

圖6. Flash Controller圖

2.1.3 Host Interface

eMMC 與 Host 之間的連接如下圖所示:

圖7. eMMC Interface

 

各個信號的用途如下所示:

  • CLK
    用於同步的時鐘信號
  • Data Strobe
    此信號是從 Device 端輸出的時鐘信號,頻率和 CLK 信號相同,用於同步從 Device 端輸出的數據。該信號在 eMMC 5.0 中引入。
  • CMD
    此信號用於傳送 Host 的 command 和 Device 的 response。
  • DAT0-7
    用於傳輸數據的 8 bit 總線。

Host 與 eMMC 之間的通信都是 Host 以一個 Command 開始發起的。針對不同的 Command,Device 會做出不同的響應。詳細的通信協議相關內容,請參考 2.3總線協議 章節。

2.2分區管理

參考“eMMC分區管理”一文。

2.3總線協議

參考“eMMC總線協議簡析”一文。

3. Linux MMC軟件框架流程

3.1軟件架構

Linux kernel的驅動框架有兩個要點:

1)抽象硬件(硬件架構是什麼樣子,驅動框架就應該是什麼樣子)。

2)向“客戶”提供使用該硬件的API(之前我們提到最多的客戶是“用戶空間的Application”,不過也有其它“客戶”,例如內核空間的其它driver、其它framework)。

MMC framework的軟件架構如下圖8所示:

圖8.Linux MMC軟件框架圖

MMC framework分別有“從左到右”和“從下到上”兩種層次結構。

1) 從左到右

MMC協議是一個總線協議,因此包括Host controller、Bus、Card三類實體(從左到右)。相應的,MMC framework抽象出了host、bus、card三個軟件實體,以便和硬件一一對應:

  • host,負責驅動Host controller,提供諸如訪問card的寄存器、檢測card的插拔、讀寫card等操作方法。從設備模型的角度看,host會檢測卡的插入,並向bus註冊MMC card設備;
  • bus,是MMC bus的虛擬抽象,以標準設備模型的方式,收納MMC card(device)以及對應的MMC driver(driver);
  • card,抽象具體的MMC卡,由對應的MMC driver驅動(從這個角度看,可以忽略MMC的技術細節,只需關心一個個具有特定功能的卡設備,如存儲卡、WIFI卡、GPS卡等等)。

2)從下到上

MMC framework從下到上也有3個層次(老生常談了):

MMC core位於中間,是MMC framework的核心實現,負責抽象host、bus、card等軟件實體,負責向底層提供統一、便利的編寫Host controller driver的API;

MMC host controller driver位於底層,基於MMC core提供的框架,驅動具體的硬件(MMC controller);

MMC card driver位於最上面,負責驅動MMC core抽象出來的虛擬的card設備,並對接內核其它的framework(例如塊設備、TTY、wireless等),實現具體的功能。

3.2工作流程

基於上圖8的軟件架構,Linux MMC framework的初始化流程如下圖9:

圖9. MMC初始化流程圖

其實,互聯網上對Linux mmc軟件框架的介紹已經非常多。本小節主要再以mmc的rescan初始化流程及request流程進行說明。參考Linux版本爲4.17,mmc host驅動爲瑞薩的rcar-M3。Block層的相關處理流程及驅動的具體實現流程本小節不涉及。

如下圖16所示,在瑞薩mmc驅動在執行probe流程時,首先會通過mmc_alloc_host函數分配一個struct mmc_host結構體,並初始化相關成員。同時,還會初始化一個卡檢測任務——INIT_DELAYED_WORK(&host->detect, mmc_rescan);當有mmc卡插入時,會觸發mmc_rescan流程。另外如下圖10右面部分,當mmc的probe驅動初始化完成,調用mmc_add_host流程中也會觸發mmc_rescan流程,下面我們就來詳細分析下這個流程(忽略部分次要步驟)。

  1. mmc_rescan首先會用一些比較低的頻率來嘗試掃描mmc設備,嘗試的頻率值分別爲400KHz、300KHz、200KHz和100KHz
  2. 用每個嘗試的頻率值(如果一個嘗試成功則不進行後續更低頻率的嘗試)通過mmc_rescan_try_freq函數來具體執行rescan流程
  3. 在mmc_rescan_try_freq函數中會依次調用host驅動接口執行POWER_UP、hw_reset以及發送CMD0命令讓卡進入idle狀態
  4. 接下來會依次嘗試attach SDIO、SD和MMC三種子協議的卡,本小節以MMC子協議爲例講解具體的attach流程
  5. 發送CMD1命令,獲取OCR寄存器值。通過mmc_select_voltage函數設置OCR中引腳電平爲3.3V
  6. 通過mmc_init_card函數執行mmc卡的初始化流程,如下
  7. 再次發送CMD0命令,保證前面OCR修改後卡的狀態再次回到idle態
  8. 再次發送CMD1命令,設置卡的sector模式(>2G的高容量模式,默認是byte模式)
  9. 發送CMD2命令,獲取CID寄存器值
  10. 通過CMD3命令設置RCA(relative card address),如果MMC總線上只有一張卡則是0001
  11. 通過CMD9命令獲取CSD寄存器值
  12. 解析CSD值,獲取獲取容量、版本等信息
  13. 解析CID值,獲取卡的序列號、年份信息、oemid等
  14. 發送CMD7命令,選中該卡,準備進行升頻模式操作
  15. 通過CMD8命令,讀取ext CSD寄存器值,獲取更多卡支持的模式、時序等信息
  16. mmc_switch,通過CMD6/CMD13命令使能ERASE_GRP_DEF、power_off_notification等
  17. mmc_select_timing則開始選擇並設置高速timing interface,具體操作有如下18~21步
  18. mmc_set_signal_voltage,高速模式首先設置信號電平爲1.2V(如果支持)或者1.8Vgao
  19. mmc_select_bus_width,通過CMD6/CMD13設置總線位寬爲8bit或4bit
  20. __mmc_switch,CMD6命令切換到HS200模式,並設置時鐘頻率爲200MHz
  21. __mmc_switch_status,CMD13獲取卡設置狀態信息
  22. 接下來,如果HS200模式切換成功,則進行tuning操作(這裏會根據mmc host硬件寄存器值進行多次tuning,根據結果擇優選擇採樣點)
  23. 上面tuning成功則會嘗試切換到更高速的HS400模式,具體操作有如下24~29步
  24. __mmc_switch,CMD6命令切換到普通HS模式,並通過mmc_set_clock將時鐘頻率降低到52MHz
  25. mmc_switch_status,發送CMD13獲取卡切換狀態信息
  26. mmc_switch,CMD6/CMD13切換至DDR模式
  27. 通過CMD6切換至HS400模式
  28. mmc_set_timing,設置時鐘頻率回200MHz
  29. mmc_switch_status,通過CMD13命令獲取模式設置狀態信息
  30. 最後通過mmc_select_powerclass選擇合適的power class,完成MMC子協議的attach流程
  31. 完成attach之後通過mmc_add_card函數向mmc bus添加卡設備,觸發block層的probe、分區管理以及文件系統初始化等後續工作

上述流程爲了方便主線的描述,忽略了一些特殊場景的處理及特性的支持,大家可以結合具體代碼和下圖來進行理解。

圖10. Linux MMC協議框架probe流程圖

Request流程其實相對簡單,block層的bio轉化後封裝成request,層層調用傳遞到mmc core層的mmc_start_request,並最終調用host驅動程序註冊的request方法執行硬件操作。這中間的流程在linux的不同版本之間變動非常大,不過萬變不離其中,大的流程框架還是沒有變。

圖11. request調用流程圖

參考文檔

[1] https://en.wikipedia.org/wiki/MultiMediaCard

[2] https://en.wikipedia.org/wiki/Secure_Digital

[3] eMMC spec:http://www.jedec.org/standards-documents/results/jesd84-b51(註冊後可免費下載)。

[4] http://www.wowotech.net/basic_tech/mmc_sd_sdio_intro.html

[5] http://www.wowotech.net/basic_tech/emmc_intro.html

[6] http://www.wowotech.net/basic_tech/emmc_partitions.html

[7] http://www.wowotech.net/basic_tech/emmc_bus_protocol.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章