天天看點

Linux MMC原理及架構詳解1. 背景2. eMMC原理介紹3. 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的原因。

Linux MMC原理及架構詳解1. 背景2. eMMC原理介紹3. Linux 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的行為,如下所示:

Linux MMC原理及架構詳解1. 背景2. eMMC原理介紹3. Linux MMC軟體架構流程

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

1.2.1 卡的規範

卡的規範主要規定卡的形狀、實體尺寸、管腳,内部block組成、寄存器等等,以eMMC為例[3]:

Linux MMC原理及架構詳解1. 背景2. eMMC原理介紹3. Linux MMC軟體架構流程

圖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 的整體架構如下圖檔所示:

Linux MMC原理及架構詳解1. 背景2. eMMC原理介紹3. Linux MMC軟體架構流程

圖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 個硬體分區,如下圖所示:

Linux MMC原理及架構詳解1. 背景2. eMMC原理介紹3. Linux MMC軟體架構流程

圖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 要好很多。

Linux MMC原理及架構詳解1. 背景2. eMMC原理介紹3. Linux MMC軟體架構流程

圖6. Flash Controller圖

2.1.3 Host Interface

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

Linux MMC原理及架構詳解1. 背景2. eMMC原理介紹3. Linux MMC軟體架構流程

圖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所示:

Linux MMC原理及架構詳解1. 背景2. eMMC原理介紹3. Linux MMC軟體架構流程

圖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:

Linux MMC原理及架構詳解1. 背景2. eMMC原理介紹3. Linux MMC軟體架構流程

圖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、分區管理以及檔案系統初始化等後續工作

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

Linux MMC原理及架構詳解1. 背景2. eMMC原理介紹3. Linux MMC軟體架構流程

圖10. Linux MMC協定架構probe流程圖

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

Linux MMC原理及架構詳解1. 背景2. eMMC原理介紹3. Linux MMC軟體架構流程

圖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