Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Linux MTD/CFI 閃存驅動架構深度解析:多分區、背靠背與 CFI 探測機制

編輯:Linux 教學

Intel StrataFlash 等 NOR 閃存支援多分區操作,但在 Linux 2.4 時代常導致「Magic bitmask not found」錯誤,根因是驅動僅用單一狀態變數追蹤整顆晶片,與分區實際狀態脫節。Linux 2.6.13 後 MTD 子系統重構解決此問題。本文深入剖析 MTD/Map/Chip 三層架構、CFI 探測流程與多分區虛擬 Chip 機制。

閃存驅動編程五大關鍵點

  1. 總線位寬存取:依總線位寬(非晶片位寬)讀寫,如背靠背兩顆 16-bit 晶片掛 32-bit 總線,必須 32-bit 存取。
  2. 位址轉換:CPU 位址與晶片腳位位址不同。16-bit 晶片,CPU 0x00/0x01 為不同位元組,但晶片腳位同為位址 0(A0 懸空或接 A1)。
  3. 指令偏移計算:資料手冊偏移基於 Word,實際偏移 = 手冊偏移 × buswidth / 8。
  4. CFI 變長結構讀取:手冊長度 2 表示 16-bit 值,但需讀 2 個 Word 取低 8 位拼湊。參考 cfi_util.c 中 cfi_read_pri 實作。
  5. 背靠背互留:兩顆 16-bit 晶片組 32-bit 總線。指令/狀態碼為雙份(如 0x00FF00FF),實際偏移 = 手冊偏移 × interleave × device_type / 8,擦除區塊大小 × interleave。

Linux MTD 探測流程追蹤 (以 cfi_probe 為例)

  1. 建構 map_info 指定基址/位寬/大小,呼叫 do_map_probe("cfi_probe", ...)。
  2. do_map_probe 依名稱找到 cfi_probe.c,呼叫 cfi_probe()。
  3. cfi_probe() 呼叫 mtd_do_chip_probe(),傳入 cfi_probe_chip 函數指標。
  4. mtd_do_chip_probe() 兩階段:
    • genprobe_ident_chips() 探測晶片資訊(大小、位寬、互留數)
    • check_cmd_set() 取得並初始化指令集(含多分區初始化)
  5. genprobe_ident_chips() 呼叫 genprobe_new_chip() 枚舉各種位寬/互留組合,調用 cfi_probe_chip()。通常第一次調用成功(編譯時確定連接方式)。
  6. cfi_probe_chip() → cfi_chip_setup() 讀取 CFI 資訊(Primary/Extended Query Table)。
  7. 回到 check_cmd_set() → cfi_cmdset_0001() (Intel/Sharp 指令集):
    • read_pri_intelext() 讀取 Intel Extended Primary Table(含分區資訊)
    • cfi_intelext_setup() 初始化結構

StrataFlash 128Mb Bottom 多分區 CFI 資訊範例

區塊結構:4×32KB + 127×128KB = 16MB,共 16 分區,每分區 1MB,nb_parts=2(兩組相同分區結構)。

第 1 部分:
  NumIdentPartitions = 1      // 1 個重複分區結構
  NumBlockTypes = 2           // 2 種區塊類型
  類型 1:NumIdentBlocks=3 (4 個區塊), BlockSize=0x80 (32KB)
  類型 2:NumIdentBlocks=6 (7 個區塊), BlockSize=0x200 (128KB)

第 2 部分:
  NumIdentPartitions = 15     // 15 個重複分區結構
  NumBlockTypes = 1
  類型 1:NumIdentBlocks=7 (8 個區塊), BlockSize=0x200 (128KB)

虛擬 Chip 機制 (cfi_intelext_partition_fixup)

為支援多分區並行操作,驅動將每個分區對應一個虛擬 Chip:

  • 假設所有分區大小相同,將 cfi->chipshift 調整為 partshift (分區大小對應的位移量)。
  • 各虛擬 Chip start 設為分區基址。
  • 存取入口 cfi_varsize_frob() 依 offset 計算 chipnum = ofs >> cfi->chipshift 導向對應虛擬 Chip。
  • 此設計簡化了分區管理,但要求分區大小一致。

Lock/Unlock 舊問題 (2.6.13 仍存在)

Linux 擦寫前不先 Unlock,解法:初始化時對全晶片執行 Unlock 指令。

💡 總結: MTD 子系統透過 Map/Chip/MTD 三層抽象,配合 CFI 自動探測與虛擬 Chip 機制,優雅支援多分區、背靠背、多種位寬組合。理解五大編程要點與探測流程,有助於移植新閃存或除錯 MTD 驅動。
Copyright © Windows教程網 All Rights Reserved