大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是i.MXRTxxx系列ROM中整合的序列NOR Flash啟動SW Reset功能及其應用場合

  在序列 NOR Flash 熱啟動過程中(非首次上電覆位,而是單純系統軟復位 NVIC_SystemReset),有很多場景下均需要先復位一下 Flash ,將其恢復到預設的 Normal 模式,然後 Flash 才能被i.MXRT BootROM 正常啟動。

  《瞭解i.MXRTxxx系列ROM中靈活的序列NOR Flash啟動硬復位引腳選擇》 一文裡介紹的硬復位 Flash 的方法適用包含獨立 RESET# 引腳的 Flash,但很多 Flash 型號並不包含這個專用引腳(尤其是 SOIC-8 封裝),有沒有一種更通用的復位 Flash 方法呢?當然是有的,《序列NOR Flash的Continuous read模式下軟復位後i.MXRT無法啟動問題解決方案之SW Reset》 一文裡介紹了一種利用 Flash 裡普遍支援的 SW Reset 軟復位命令的方法,並在使用者應用程式裡給出了示例程式碼。

  我們知道大部分早期 i.MXRT1xxx 型號 BootROM 裡並沒有整合 Flash SW Reset 功能,需要使用者程式碼裡去整合這個 Flash SW Reset 命令功能,這有點不方便,因此在更新的 i.MXRTxxx 系列型號 BootROM 裡就集成了這個 Flash SW Reset 軟復位功能。今天痞子衡就介紹下這個功能在 BootROM 裡實現細節:

  • 備註1:本文主角是i.MXRT500/600,但內容也基本適用i.MXRT1160/1170。
  • 備註2:本文主要適用普通四線 QSPI NOR 或者八線 Octal Flash

一、BootROM中Flash SW Reset功能介紹

1.1 FlexSPI Boot初始化流程

  關於 i.MXRT 系列的序列 NOR Flash 啟動初始化流程,痞子衡一共寫過三篇文章,這些文章雖針對早期 i.MXRT1xxx 系列型號寫的,但內容基本也適用 i.MXRTxxx 系列型號,後續更新的 i.MXRT 型號在這個方面特性只會微調和增強。

  1. 《深入i.MXRT1050系列ROM中序列NOR Flash啟動初始化流程》
  2. 《瞭解i.MXRT1060系列ROM中序列NOR Flash啟動初始化流程優化點》
  3. 《自識別特性(Auto Probe)可以讓i.MXRT1060無需FDCB也能從NOR Flash啟動》

  為了讓大家對 i.MXRTxxx 系列序列 NOR Flash 啟動初始化流程有明確概念,痞子衡重畫了相應啟動流程圖,從流程上來看,其和 i.MXRT1060 最主要的差異就是三處步驟Y,這是最核心的改進點,也是本文主題。除此以外,還有一些微小差異(步驟7的位置調整)。

1.2 Flash SW Reset相關程式碼設計

  BootROM 中 Flash SW Reset 功能是通過 flexspi_nor_restore_spi_protocol() 函式實現的(關於它的原型可以在 i.MXRT1170 SDK\middleware\mcu-boot\src\drivers\flexspi_nor\flexspi_nor_flash.c 檔案裡找到),這個函式一共被呼叫兩次,一次是在 Auto Probe 流程裡(見 flexspi_nor_flash.c 檔案裡的 flexspi_nor_get_config() 函式實現,這個過程使用者無需參與);另一次是在主流程裡(見如下程式碼),主流程裡的呼叫才是使用者可以參與控制的:

// Flash 狀態模式
enum
{
kFlashInstMode_ExtendedSpi = 0x00,
kFlashInstMode_0_4_4_SDR = 0x01,
kFlashInstMode_0_4_4_DDR = 0x02,
kFlashInstMode_QPI_SDR = 0x41,
kFlashInstMode_QPI_DDR = 0x42,
kFlashInstMode_OPI_SDR = 0x81,
kFlashInstMode_OPI_DDR = 0x82,
}; // 主要支援的三種軟復位命令序列
enum
{
kRestoreSequence_Send_66_99 = 6, // 適用大部分 QSPI Flash(如 IS25WP064A,GD25Q64,W25Q64)以及 Micron 的 OctalFlash
kRestoreSequence_Send_6699_9966 = 7, // 適用 MXIC 的 OctalFlash,如 MX25UM51345
kRestoreSequence_Send_06_FF = 8, // 專用 Adesto EcoXIP
}; typedef union {
struct
{
uint8_t por_mode; // 預設上電 Flash 狀態模式
uint8_t current_mode; // 當前 Flash 狀態模式
uint8_t exit_no_cmd_sequence;
uint8_t restore_sequence; // 指定軟復位命令序列
} B;
uint32_t U;
} flash_run_context_t; // 從指定的非易失性區域獲取使用者設定
flash_run_context_t flashRunCtx;
(void)flexspi_nor_read_persistent(&flashRunCtx.U); // 根據使用者設定來做相應 Flash 軟復位操作
(void)flexspi_nor_restore_spi_protocol(flexspiInstance, &flexspiNorConfig, &flashRunCtx);

  其中 flashRunCtx.B.restore_sequence 取值跟 Flash 型號有關, kRestoreSequence_Send_66_99 適用 QSPI NOR,比如華邦的 W25Q64(下圖裡 SW Reset 命令有 SPI 模式和 QPI 模式兩種,但 BootROM 只用 QPI SDR 這種):

  kRestoreSequence_Send_66_99 也適用 Micron 的 OctalFlash,如 MT35X 系列(下圖裡 SW Reset 命令有 SPI 模式和 OPI 模式兩種,但 BootROM 只用 OPI SDR 這種):

  kRestoreSequence_Send_6699_9966 適用旺巨集的 Octal Flash,比如 MX25UM51345(下圖裡 SW Reset 命令有 SPI 模式和 OPI 模式兩類,但 BootROM 只用 OPI 這類,不過 SDR/DTR 都支援):

1.3 儲存SW Reset指示的易失性通用暫存器

  上一節程式碼中的 flash_run_context_t 結構體變數 flashRunCtx 是使用者程式跟 BootROM 溝通的關鍵,這個變數需要存在一個晶片系統軟復位不清除的區域,BootROM 程式碼裡選擇瞭如下非易失性通用暫存器:

// i.MXRT500/600 裡實現
status_t flexspi_nor_read_persistent(uint32_t *data)
{
*data = *(volatile uint32_t *)(SYSCTL0_BASE + 0x380); return kStatus_Success;
} // i.MXRT1160/1170 裡實現
status_t flexspi_nor_read_persistent(uint32_t *data)
{
*data = SRC->GPR[2]; return kStatus_Success;
}

1.4 將SW Reset請求傳遞給 BootROM 的兩種方式

  使用者有兩種方式將 flashRunCtx 值傳遞給 BootROM,一是在應用程式程式碼里加入如下程式碼,主動將值寫進指定的通用暫存器,這種方式比較靈活,flashRunCtx 設定可根據實際應用情況任意調整。

flash_run_context_t flashRunCtx = {.U = 0};
flashRunCtx.B.por_mode = kFlashInstMode_ExtendedSpi;
flashRunCtx.B.current_mode = kFlashInstMode_QPI_SDR;
flashRunCtx.B.restore_sequence = kRestoreSequence_Send_66_99;
// 針對 i.MXRT1160/1170
SRC->GPR[2] = flashRunCtx.U;
// 針對 i.MXRT500/600
*(volatile uint32_t *)(SYSCTL0_BASE + 0x380) = flashRunCtx.U;

  第二種方式是利用啟動頭 FDCB,在 flexspi_nor_config_t.flashStateCtx 裡儲存的就是 flashRunCtx,每一次 BootROM 啟動都會將 FDCB 裡的 flashStateCtx 寫入指定的通用暫存器,這種方式相對來說不夠靈活,適用明確的場景。

#if defined(BOOT_HEADER_ENABLE) && (BOOT_HEADER_ENABLE == 1)
#if defined(__ARMCC_VERSION) || defined(__GNUC__)
__attribute__((section(".flash_conf"), used))
#elif defined(__ICCARM__)
#pragma location = ".flash_conf"
#endif const flexspi_nor_config_t flash_config = {
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
// 其他省去不表
},
.pageSize = 256u,
.sectorSize = 4u * 1024u,
.blockSize = 64u * 1024u,
// 設定 flashRunCtx
.flashStateCtx = 0x06004100u, /*!< [0x1d4-0x1d7] */
}; #endif /* BOOT_HEADER_ENABLE */

二、BootROM中Flash SW Reset功能應用

2.1 Flash進入QPI/OPI模式後系統復位

  Flash 的 SPI 模式和 QPI/OPI 模式常常是互斥的,同一時間僅能一種模式工作。Flash 上電預設是 SPI 模式,需要傳送特殊的 QPIEN 命令或者配置一些內部暫存器才能進入 QPI 或者 OPI模式,一旦進了 QPI/OPI 模式,需要被複位回 SPI 模式才能被 BootROM 正常啟動。

  比如在 MIMXRT595-EVK 板卡上,SDK 裡 FDCB 啟動頭使能了預設板載 Octal Flash - MX25UM51435 的 OPI DDR 模式,所以我們需要在應用程式系統初始化裡插入如下程式碼:

void SystemInit_flash(void)
{
flash_run_context_t flashRunCtx = {.U = 0};
flashRunCtx.B.por_mode = kFlashInstMode_ExtendedSpi;
flashRunCtx.B.current_mode = kFlashInstMode_OPI_DDR;
run_cflashRunCtxtx.B.restore_sequence = kRestoreSequence_Send_6699_9966;
*(volatile uint32_t *)(SYSCTL0_BASE + 0x380) = flashRunCtx.U;
} /*
// 或 FDCB 增加如下設定
const flexspi_nor_config_t flash_config = {
.flashStateCtx = 0x07008200u, //!< [0x1d4-0x1d7] //
};
*/

2.2 Flash進入Continuous read模式後系統復位

  《序列NOR Flash的Continuous read模式下軟復位後i.MXRT無法啟動問題解決方案之SW Reset》 一文裡的問題,可通過如下新方案實現(基於 MIMXRT1170-EVK 板卡):

void reset_flash_to_normal(void)
{
__disable_irq(); flash_run_context_t flashRunCtx = {.U = 0};
flashRunCtx.B.por_mode = kFlashInstMode_ExtendedSpi;
flashRunCtx.B.current_mode = kFlashInstMode_0_4_4_SDR;
flashRunCtx.B.restore_sequence = kRestoreSequence_Send_66_99;
SRC->GPR[2] = flashRunCtx.U; NVIC_SystemReset();
} /*
// 或 FDCB 增加如下設定
const flexspi_nor_config_t flash_config = {
.flashStateCtx = 0x06000100u, //!< [0x1d4-0x1d7] //
};
*/

2.3 Flash進入Deep Power Down模式後系統復位

  大部分 Flash 都支援進入 Deep Power Down 模式(通過 B9H 命令進入),這種模式適合一些對功耗要求敏感的裝置,比如智慧手錶。在 Deep Power Down 模式下,Flash 不再響應讀寫擦命令,需要接受 Release Deep Power Down 命令(同時也是 Read Device ID命令)才能被再次喚醒正常工作,某些 QSPI NOR 以及 OctalFlash 下也支援 SW Reset 命令來喚醒退出低功耗模式,這時候也可以根據實際情況利用 BootROM 裡整合的 SW Reset 功能。

  至此,i.MXRTxxx系列ROM中整合的序列NOR Flash啟動SW Reset功能及其應用場合痞子衡便介紹完畢了,掌聲在哪裡~~~

歡迎訂閱

文章會同時釋出到我的 部落格園主頁CSDN主頁知乎主頁微信公眾號 平臺上。

微信搜尋"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。