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