|
大家好,我是痞子衡,是正經(jīng)搞技術的痞子。今天痞子衡給大家介紹的是在FDCB里配置串行NOR Flash多個寄存器的注意事項。
關于使用 i.MXRT 啟動頭 FDCB 來設置 Flash 內(nèi)部寄存器,痞子衡寫過如下兩篇文章,在進入本文之前,建議大家先閱讀下這兩篇文章,有個初步了解。
《在FDCB里設置Flash的Dummy Cycle》《在FDCB里切換Flash模式至QPI/OPI》我們知道 Flash 內(nèi)部常常有多個狀態(tài)/配置寄存器,這些寄存器有些是易失性的,有些是非易失性的。當芯片被指定從 Flash 啟動的時候,我們?nèi)绻M?BootROM 能夠根據(jù)不同應用需求來提前設置好這些 Flash 寄存器,那么在應用程序里就不用再額外配置了(涉及 Flash 工作狀態(tài)變化的配置,如果是 XIP 程序去操作,需要考慮代碼重定向問題)。
對于使用 FDCB 來配置 Flash 一個寄存器的操作,相信大家都很了解,在恩智浦 SDK 包里默認 FDCB 啟動頭里都有成功示例。最近痞子衡同事嘗試使用 FDCB 去配置鎂光 MT35X 的兩個寄存器(地址為 0x000000 的寄存器切至 OPI DDR、地址為 0x000003 的寄存器設 Drive Strength)發(fā)現(xiàn)有一個寄存器設置沒生效,這是怎么回事?今天我們來聊一聊:
Note: 本文適用于 i.MXRT500/600/1010/1020/1040/1050/1060/1160/1170一、FDCB提供的Flash寄存器配置能力我們先來看一下 FDCB 結構里跟 Flash 配置相關的成員,痞子衡整理如下,簡單來說,就是有一條 deviceModeSeq 和三條 configCmdSeqs,所以最多能配置 Flash 里 4 個不同命令下對應的寄存器(有些 Flash 里一條配置命令能連續(xù)寫入多個寄存器,這種情況下就能配置不止 4 個寄存器),這對于大部分應用場景都完全夠用了。
Note 1: BootROM 執(zhí)行這四個配置的順序分別是 deviceModeSeq、configCmdSeqs[0]、configCmdSeqs[1]、configCmdSeqs[2],記住這個順序。Note 2: deviceModeSeq 與 configCmdSeq 實現(xiàn)的配置功能幾乎沒有區(qū)別,兩者能做的事情是一樣的,可以互換。//!@brief FlexSPI Memory Configuration Block
typedef struct _FlexSPIConfig
{
// ...
//!
uint8_t deviceModeCfgEnable;
//!
uint8_t deviceModeType;
//!
uint16_t waitTimeCfgCommands;
//!
flexspi_lut_seq_t deviceModeSeq;
//!
uint32_t deviceModeArg;
//!
uint8_t configCmdEnable;
//!
uint8_t configModeType[3];
//!
flexspi_lut_seq_t configCmdSeqs[3];
//!
uint32_t configCmdArgs[3];
// ...
//!
uint16_t busyOffset;
//!
uint16_t busyBitPolarity;
//!
uint32_t lookupTable[64];
// ...
} flexspi_mem_config_t;
在 《在FDCB里設置Flash的Dummy Cycle》 一文最后,痞子衡已經(jīng)分享了 BootROM 解析執(zhí)行 configCmdSeq 的代碼流程,在這個流程里我們能看到和 deviceModeType/configModeType[]、waitTimeCfgCommands 成員相關的邏輯代碼,這里有必要進一步解釋一下。
//!@brief Flash Configuration Command Type
enum
{
kDeviceConfigCmdType_Generic, //!
kDeviceConfigCmdType_QuadEnable, //!
kDeviceConfigCmdType_Spi2Xpi, //!
kDeviceConfigCmdType_Xpi2Spi, //!
kDeviceConfigCmdType_Spi2NoCmd, //!
kDeviceConfigCmdType_Reset, //!
};
當 deviceModeType/configModeType 成員被設置為 kDeviceConfigCmdType_Spi2Xpi 時;如果 FDCB 本身被獲取時 BootROM 用得是 DPI/QPI/OPI 命令(根據(jù) efuse 配置決定),那么此條 Flash 寄存器配置會被直接忽略;如果 BootROM 用得是普通一線 SPI 模式讀取的 FDCB,那么這個 Flash 寄存器配置仍然生效。
kDeviceConfigCmdType_Spi2Xpi 等三個跟 Flash 命令模式切換相關的配置類型,顧名思義就是告訴 BootROM 這三種配置會導致 Flash 工作模式變化,而一旦 Flash 工作模式發(fā)生變化,用于判斷配置是否完成的 READ_STATUS 命令也隨之變得不可用(因為 SPI 模式下與 DPI/QPI/OPI 模式下的命令序列不同),這種情況下就需要借助 waitTimeCfgCommands 成員來實現(xiàn)軟件延時以等待對 Flash 的配置真正生效(如果不等生效就直接進入后續(xù)流程,可能會導致啟動問題)。
kDeviceConfigCmdType_Generic 配置類型,則是用于跟工作模式切換無關的 Flash 寄存器配置,這種情況下 BootROM 可以使用 READ_STATUS 命令來判斷對 Flash 寄存器配置是否已經(jīng)生效,那么就不需要 waitTimeCfgCommands 實現(xiàn)的延時等待(需要查 Flash 數(shù)據(jù)手冊作相應設置,比較麻煩,而且手冊里是給了典型值和最大值,取最大值會導致啟動時間變長,典型值不能保證適用所有情況)。
二、配置Flash多個寄存器注意點Flash 配置寄存器的寫入流程通常分三步:一、WRITE_ENABLE 使能寫操作;二、具體的 CONFIG_REG 操作;三、READ_STATUS 或者軟件延時確保配置已完成。這些命令序列全部存儲在 FDCB 里的 lookupTable[64] 成員里。
關于 Flash 寄存器的配置操作,從寄存器屬性上來看,分為易失性和非易失性兩種,前者的操作一般是立即生效的,后者的操作不是立即生效(Flash 狀態(tài)寄存器 WIP 位會反映進度)。從命令模式角度來看,分為非模式切換操作(比如設置 Dummy Cycle、Drive Strength)以及切換 SPI 與 DPI/QPI/OPI 模式操作兩種,同樣前者操作是立即生效,后者操作不是立即生效。
現(xiàn)在回到文章開頭痞子衡同事遇到的問題,如果 deviceModeSeq 用于切換至 OPI DDR 模式,configCmdSeqs[0] 用于設 Drive Strength,請問哪一個操作沒有生效?這里就不賣關子了,設 Drive Strength 沒有生效,因為第一個配置是切換至 OPI DDR 模式,當 Flash 切換到該模式時,用于第二/三/四個配置的 WRITE_ENABLE 命令變得不可用了(還是因為 SPI 模式下與 DPI/QPI/OPI 模式下的命令序列不同),當然對應 Flash 寄存器設置就無效了。
那么如何避免這個問題?有一個一勞永逸的方法,那就是永遠用 configCmdSeqs[2] 去做 SPI 與 DPI/QPI/OPI 模式切換操作,這樣就不會影響前面三個配置。前面講了,此時判斷命令模式是否切換完成不能用 READ_STATUS 命令,那么就一定需要 waitTimeCfgCommands 來做軟延時,如果延時時間不夠,并且后續(xù) BootROM 執(zhí)行到驗證 IVT 頭時模式切換仍未完成,這會導致 IVT 啟動頭無法正確獲取從而導致啟動失敗。
假設 waitTimeCfgCommands 延時設置對于命令模式切換已足夠,這樣問題就一定解決了嗎?其實還不一定,如果此時已將 deviceModeSeq 用于設 Drive Strength,但是選擇得是寫入 Flash 非易失性存儲器,這需要確保 waitTimeCfgCommands 延時對于寫入非易失性寄存器也足夠。翻看 MT35X 的數(shù)據(jù)手冊可以發(fā)現(xiàn),寫入非易失性寄存器 cycle time 典型值是 0.2s,最大值是 1s。 |
|