| 步驟 | 標準 AMD/Intel CFI | SST39VF1601 (舊版 CFI) |
| 1 | Reset (0xF0) | Reset (0xF0) |
| 2 | Write 0x98 to 0x55 (或 0x555/0x5555) | Write 0x98 to 0x55 |
| 3 | 讀取 "QRY" 成功 → 完成 | 讀取 "QRY" 失敗 |
| 4 | — | Reset → Write 0x98 to 0x555 |
| 5 | — | 讀取 "QRY" 失敗 |
| 6 | — | Reset → Write 0xAA/0x55 to 0x5555/0x2AAA → Write 0x98 to 0x5555 |
| 7 | — | 讀取 "QRY" 成功 → 完成 |
SST 老舊芯片需多達 4 組解鎖地址/命令序列嘗試,標準驅動僅嘗試 2 組(FLASH_OFFSET_CFI、FLASH_OFFSET_CFI_ALT)。
關鍵代碼修改點 (Patch 解讀)
1. 新增 SST 命令集常數
// include/mtd/cfi_flash.h
#define CFI_CMDSET_SST_OLD 0x701 // SST 老版本命令集 ID
2. 重構 CFI Query 模式進入邏輯
// 核心函數:嘗試多種解鎖序列進入 Query 模式
static int __cfi_qry_mode_on(flash_info_t *info) {
// 嘗試序列 1: offset 0x55
flash_write_cmd(info, 0, 0, AMD_CMD_RESET); // 0xF0
flash_write_cmd(info, 0, 0x55, FLASH_CMD_CFI); // 0x98
if (__cfi_qry_present(info)) { info->cfi_offset = 0x55; return 1; }
// 嘗試序列 2: offset 0x555
flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); // 0xFF
flash_write_cmd(info, 0, 0x555, FLASH_CMD_CFI);
if (__cfi_qry_present(info)) { info->cfi_offset = 0x555; return 1; }
// 嘗試序列 3: offset 0x5555 (標準 AMD)
flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
flash_write_cmd(info, 0, 0x5555, FLASH_CMD_CFI);
if (__cfi_qry_present(info)) { info->cfi_offset = 0x5555; return 1; }
// 嘗試序列 4: 完整 AMD 解鎖序列 0x5555/0x2AAA/0x5555
flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
flash_write_cmd(info, 0, 0x5555, 0xAA);
flash_write_cmd(info, 0, 0x2AAA, 0x55);
flash_write_cmd(info, 0, 0x5555, FLASH_CMD_CFI);
if (__cfi_qry_present(info)) { info->cfi_offset = 0x5555; return 1; }
// 嘗試序列 5: 縮短解鎖 0x555/0x2AA/0x555
flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
flash_write_cmd(info, 0, 0x555, 0xAA);
flash_write_cmd(info, 0, 0x2AA, 0x55);
flash_write_cmd(info, 0, 0x555, FLASH_CMD_CFI);
if (__cfi_qry_present(info)) { info->cfi_offset = 0x555; return 1; }
return 0; // 所有嘗試失敗
}
3. 識別到 SST 命令集時設置專用解鎖地址
if (le16_to_cpu(get_unaligned(&qry->p_id)) == CFI_CMDSET_SST_OLD) {
info->addr_unlock1 = 0x5555;
info->addr_unlock2 = 0x2AAA;
}
4. 寫入/擦除/檢測流程中註冊 SST 命令集分支
flash_write_cfiword:新增 case CFI_CMDSET_SST_OLD: 分支,使用 addr_unlock1 解鎖寫入。
flash_erase:新增 SST 分支,解鎖序列 + AMD_CMD_ERASE_START + 扇區擦除命令。
flash_get_size:將 SST 歸入 AMD 標準初始化流程 cmdset_amd_init。
Mini2440 配置確認
// include/configs/mini2440.h
#define CONFIG_SYS_FLASH_CFI
#define CONFIG_FLASH_CFI_DRIVER
#define CONFIG_SYS_FLASH_CFI_WIDTH FLASH_CFI_16BIT
工程經驗總結
- CFI 標準不完全統一:早期廠商(SST、AMD 舊版)有私有解鎖序列,驅動需兼容多序列嘗試。
- QRY 字串檢測是金標準:只識別 "Q""R""Y" 三字節,不依賴廠商 ID。
- 解鎖地址與命令序列要查數據手冊:SST39VF1601 需 0x5555/0x2AAA 解鎖,而非標準 0x555/0x2AA/0x555。
- Patch 核心思想:將「嘗試進入 Query 模式」抽離為獨立函數,內部按優先級順序嘗試所有已知序列,成功即返回,失敗則嘗試下一組,極大提升驅動通用性。
總結
本次移植通過擴展 U-Boot CFI 驅動的 Query 模式進入邏輯、註冊 SST 專用命令集與解鎖地址,成功支援 Mini2440 上的 SST39VF1601 Nor Flash。該 Patch 體現了嵌入式驅動開發中「兼容多廠商異構序列、以 QRY 檢測為準、優先級嘗試策略」的核心工程智慧,可作為同類 Flash 移植的參考範本。
- 上一篇文章: 哈希表(散列表)核心原理:散列函數構造與衝突解決全解析
- 下一篇文章: C 語言 static 關鍵字深度解析:三大用法與底層存儲機制
Copyright ©
程式碼之家 All Rights Reserved