大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是超級下載演算法開發筆記(4)之輪詢Flash配置引數。
文接上篇 《超級下載演算法(RT-UFL)開發筆記(3) - 統一FlexSPI驅動訪問》,現在超級下載演算法中已經整合了BootROM版本的統一FlexSPI驅動,原則上BootROM能支援啟動的所有序列NOR Flash型號,超級下載演算法都可以對其進行擦寫操作。BootROM雖然可以支援很多種不同的Flash,但其需要依賴使用者提供一個名為FDCB的配置結構體放置在Flash固定偏移處,BootROM先配置FlexSPI為1bit SDR低速模式去訪問Flash獲取到FDCB,然後從FDCB中得到當前Flash的全部屬性再去重新初始化FlexSPI外設。然而超級下載演算法沒法從使用者處獲取到Flash的資訊,只能自力更生,使用輪詢的方法去不斷嘗試,直到試出合適的配置引數。
本篇是開發筆記第四篇,我們們就重點聊聊如何讓超級下載演算法適用不同廠商生產的不同屬性序列NOR Flash。
一、BootROM對Flash的支援(FDCB)
前言裡講了BootROM對Flash的支援是靠不同的FDCB結構體配置值來實現的,這個FDCB一共512bytes,原型及各byte定義在i.MXRT1xxx參考手冊System Boot章節裡 Serial NOR configuration block (512 bytes) 一小節有詳細介紹。這個FDCB主要是用於配置FlexSPI外設的,我們們超級下載演算法的 flexspi_nor_flash_init() 函式的一個主要引數 flexspi_nor_config_t 其實就是FDCB。
status_t flexspi_nor_flash_init(uint32_t instance, flexspi_nor_config_t *config);
關於這個FDCB具體如何賦值,恩智浦官網有一些應用筆記,這些應用筆記介紹了一些典型的Flash型號應該匹配什麼樣的FDCB值,從這些應用筆記裡我們可以大概瞭解FDCB用法。
上面的應用筆記裡列舉了一些BootROM支援的Flash型號,這些型號僅僅是恩智浦工程師驗證過的型號,而客戶在實際專案中用到的Flash型號遠遠不止這些。從Flash型號本身角度來看,不同廠商的不同型號是獨特且唯一的,但從FDCB角度而言,很多同型別Flash型號其實是一樣的配置值。
二、快速生成FDCB的方法(config option)
那麼我們現在是不是直接在超級下載演算法中窮舉不同的FDCB值去輪詢呢?要知道FDCB有512bytes,這是個不小的結構體,輪詢一遍太費時且低效了。我們需要進一步提煉FDCB,將其精簡一下,只輪詢那些跟Flash型別緊密相關的引數。這個工作其實也不需要我們做了,恩智浦ROM研發小組已經做好了,那便是8bytes的config option配置結構體,這個配置結構體也是超級下載演算法的 flexspi_nor_get_config() 函式的一個主要引數 serial_nor_config_option_t。
status_t flexspi_nor_get_config(uint32_t instance, flexspi_nor_config_t *config, serial_nor_config_option_t *option);
其實這個神奇的8bytes的config option配置結構體不止一次地出現過痞子衡之前的文章裡:《導致序列NOR Flash在i.MXRT下無法正常下載/啟動的常見因素之SFDP》、《導致序列NOR Flash在i.MXRT下無法正常下載/啟動的常見因素之QE bit》、《FlexSPI NOR啟動時間(RT1170)》、《MCUBootUtility v2.3釋出,這次不再放過任何一款Flash》,它非常精煉地概括了市面上主要的序列NOR Flash特性(都要符合JESD216規範),只要你提供config option,經過 flexspi_nor_get_config() 函式執行後便可以自動生成相對應的完整FDCB。
在i.MXRTxxx參考手冊Non-Secure Boot ROM章節裡你可以找到如下典型Flash型號對應的參考config option值:
三、利用config option來做輪詢
直接利用512bytes的FDCB去輪詢太難,但利用8bytes的config option去輪詢就簡單多了。我們順著上文中提及的ufl_target_desc_t結構體,在其中新增幾個成員(FlexSPI外設編號/基址/對映地址,config option),其中輪詢主要跟config option有關。
typedef struct _target_desc
{
uint32_t imxrtChipId;
uint32_t flexspiInstance; // 新增
uint32_t flexspiBaseAddr; // 新增
uint32_t flashBaseAddr; // 新增
serial_nor_config_option_t configOption; // 新增
flexspi_nor_flash_driver_t flashDriver;
flexspi_bsp_driver_t flexspiBsp;
} ufl_target_desc_t;
然後我們定義一個config option型的陣列 s_flashConfigOpt[],裡面存放一些經典的config option值。當前痞子衡的設計是僅輪詢這些經典的config option值,並沒有窮舉config option,這也是從超級下載演算法的執行效率角度考慮,這些經典的config option值足以覆蓋80%以上的Flash型號了(後期如果要提高Flash覆蓋率,會考慮轉到窮舉法的)。
static const serial_nor_config_option_t s_flashConfigOpt[] = {
// For Normal Quad, eg. IS25LP064A, GD25LB256E
{.option0.U = 0xc0000001, .option1.U = 0x00000000},
// For Normal Octal, eg. MX25UM51345G
{.option0.U = 0xc0403001, .option1.U = 0x00000000},
{.option0.U = 0xc1503051, .option1.U = 0x20000014},
// For Normal HyperBus, eg. S26KS512S, IS26KS512S
{.option0.U = (0xc0233000 + kSerialNorCfgOption_MaxFreq), .option1.U = 0x00000000},
// For Normal Octal, eg. MX25UM51245G
{.option0.U = 0xc0403031, .option1.U = 0x00000000},
// For Normal Octal, eg. MT35X
{.option0.U = 0xc0603001, .option1.U = 0x00000000},
// For Normal Octal, eg. ATXP032
{.option0.U = 0xc0803001, .option1.U = 0x00000000},
// For Normal 1-bit SDR
{.option0.U = FLASH_CONFIG_OPT_1BIT_SDR, .option1.U = 0x00000000},
};
關於具體輪詢操作,原始碼在 RT-UFL 專案中的ufl_auto_probe_flash.c 檔案裡,痞子衡就不再貼出了,只講一下幾個要點:
- 要點 1: 對於一些SIP版本的i.MXRT型號,沒有必要再輪詢了,直接給預設的config option值即可。
- 要點 2: config option引數輪詢成功的判斷標準是,執行初始化->擦->寫操作均正常(或許還要加入回讀校驗)。
- 要點 3: 當前config option引數輪詢失敗進到下一個option值前需要對FlexSPI外設進行復位(有條件的話還要對Flash進行復位)。
- 要點 4: 不同Flash型號支援的最大速度不同,輪詢時總是先從最低速開始,慢慢增速到最大支援的速度(當前是100MHz,後期會調整)。
- 要點 5: 為了照顧沒有SFDP表的Flash(或不符合JESD216規範),輪詢過程裡增加了一個1bit SDR屬性的FDCB表作為最後一個保底輪詢。
至此,超級下載演算法開發筆記(4)之輪詢Flash配置引數痞子衡便介紹完畢了,掌聲在哪裡~~~
歡迎訂閱
文章會同時釋出到我的 部落格園主頁、CSDN主頁、知乎主頁、微信公眾號 平臺上。
微信搜尋"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。