痞子衡嵌入式:了解i.MXRTxxx系列ROM中靈活的串列NOR Flash啟動硬複位引腳選擇
- 2021 年 7 月 22 日
- 筆記
- D1.單片機i.MXRT-CM33
大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是i.MXRTxxx系列ROM中靈活的串列NOR Flash啟動硬複位引腳選擇。
關於 i.MXRT 系列 BootROM 中串列 NOR Flash 啟動流程,痞子衡寫過一篇非常詳細的文章 《深入i.MXRT1050系列ROM中串列NOR Flash啟動初始化流程》,這篇文章主要針對 i.MXRT1xxx 四位數系列,但基本上也適用 i.MXRTxxx 三位數系列,僅一些細節處有區別。
在串列 NOR Flash 熱啟動過程中(非首次上電複位,而是單純系統軟複位 NVIC_SystemReset),有很多場景下均需要先複位一下 Flash ,將其恢復到默認的 Normal 模式,然後 Flash 才能被 BootROM 正常啟動。這些場景包括 Flash 在上次系統運行時被配置到了某種特殊運行模式(QSPI 進入 Continuous Read 或者 QPI 模式,Octal Flash 進入 OPI 模式等),或者直接進到了低功耗模式(Deep Power Down)。
本文就是介紹利用 BootROM 里集成的 Flash 硬複位功能來完成 Flash 複位操作。閑話少敘,進入正文:
- 備註1:本文主要針對已量產的 i.MXRT500/600 。
- 備註2:本文僅適用那些包含獨立 RESET# 引腳的 Flash。
一、BootROM中實現
在 《深入i.MXRT1050系列ROM中串列NOR Flash啟動初始化流程》 一文的 2.1 節里,我們知道在 i.MXRT1xxx 四位數系列 BootROM 里同樣集成了 Flash 硬複位功能,但是用於連接 Flash RESET# 引腳的 GPIO 是固定的(i.MXRT1050 上是GPIO1[9],i.MXRT1170 上是GPIO4[3] / GPIO2[8]),這對 PCB 設計有一定限制,如果被指定的 GPIO 在項目設計里有不可替代的功能,那隻能放棄 BootROM 里這個 Flash 複位功能了。
鑒於 i.MXRT1xxx 里 GPIO 指定不夠靈活的缺陷,恩智浦 ROM 小組在 i.MXRTxxx 系列裡做了改進,我們來看 i.MXRT600 的 fusemap 表,其中 BOOT_CFG[1] 里關於 QSPI_RESET_PIN 定義如下:
我們看到了 3bit GPIO_PORT (0-7) 和 5bit GPIO_PIN_NUM (0-31) 設置,有了這個設置,用於連接 Flash RESET# 引腳 的 GPIO 選擇就非常靈活了,基本可以涵蓋所有 GPIO,因此項目 PCB 設計里只要隨便找一個空閑的 GPIO 連到 Flash RESET# 引腳即可。
該功能在 BootROM 里實現程式碼大概如下:
const clock_ip_name_t k_GpioClocks[8] = { kCLOCK_HsGpio0, kCLOCK_HsGpio1, kCLOCK_HsGpio2, kCLOCK_HsGpio3,
kCLOCK_HsGpio4, kCLOCK_HsGpio5, kCLOCK_HsGpio6, kCLOCK_HsGpio7 };
const RSTCTL_RSTn_t k_GpioResets[8] = { kHSGPIO0_RST_SHIFT_RSTn, kHSGPIO1_RST_SHIFT_RSTn, kHSGPIO2_RST_SHIFT_RSTn, kHSGPIO3_RST_SHIFT_RSTn,
kHSGPIO4_RST_SHIFT_RSTn, kHSGPIO5_RST_SHIFT_RSTn, kHSGPIO6_RST_SHIFT_RSTn, kHSGPIO7_RST_SHIFT_RSTn};
if (OCOTP->OTP_SHADOW[0x61] & 0x400)
{
// Initialize Reset Pin
uint32_t portInstance = (OCOTP->OTP_SHADOW[0x61] & 0x3800) >> 15;
uint32_t gpioInstance = (OCOTP->OTP_SHADOW[0x61] & 0x7c000) >> 18;
// Enable Clock before accessing registers
CLOCK_EnableClock(k_GpioClocks[portInstance]);
RESET_PeripheralReset(k_GpioResets[portInstance]);
// Configure the port to GPIO mode with pull-up resistor enabled.
IOPCTL->PIO[portInstance][gpioInstance] = IOPCTL_PIO_FSEL(0) | IOPCTL_PIO_PUPDENA(1) | IOPCTL_PIO_PUPDSEL(1) | IOPCTL_PIO_FULLDRIVE(1);
GPIO->DIRSET[portInstance] = (1u << gpioInstance);
// High
GPIO->SET[portInstance] = (1u << gpioInstance);
flexspi_sw_delay_us(250);
// Low
GPIO->CLR[portInstance] = (1u << gpioInstance);
flexspi_sw_delay_us(250);
// High
GPIO->SET[portInstance] = (1u << gpioInstance);
flexspi_sw_delay_us(500);
}
二、在MIMXRT685-EVK上實踐
我們現在在官方 MIMXRT685-EVK 上實測一下這個功能,EVK 上選用的 Flash 型號是旺宏的 MX25UM51345G,這顆 Flash 有獨立的 RESET# 引腳(A4),它被連到了主晶片的 PIO2_12 腳上。
要想激活 BootROM 中 Flash 硬複位功能需要燒寫 eFuse(也可以寫相應 OCOTP Shadow Register 來替代,Shadow Register 只在上電或者觸發 OCOTP refresh 命令時從 eFuse 中載入一次值,其後即使軟複位 Shadow Register 值也不丟失),我們暫且用寫 Shadow Register 方式來測試。
正好前段時間痞子衡在做 SBL 項目寫了篇文章 《在SBL項目實戰中妙用i.MXRT1xxx里SystemReset不複位的GPR暫存器》,裡面就有系統軟複位需求,在支援 i.MXRT600 時就遇到了問題,因為第一次啟動後 MIMXRT685-EVK 上的這顆 Octal Flash 被配置到了 OPI 模式,需要複位後才能再次被 BootROM 正常啟動,所以我們直接就用上了 BootROM 里的 Flash 硬複位功能,程式碼很簡單:
void isp_cleanup_enter(uint32_t flag)
{
CLOCK_EnableClock(kCLOCK_Rtc);
RTC->CTRL &= ~RTC_CTRL_SWRESET_MASK;
RTC->GPREG[0] = flag;
// Reset Flash to normal mode by BootROM
// QSPI_RESET_PIN_ENABLE = 1'b1, GPIO_PORT = 3'b010, GPIO_PIN_NUM = 5'b01100
OCOTP->OTP_SHADOW[0x61] = 0x314000;
__DSB();
NVIC_SystemReset();
}
至此,i.MXRTxxx系列ROM中靈活的串列NOR Flash啟動硬複位引腳選擇痞子衡便介紹完畢了,掌聲在哪裡~~~
歡迎訂閱
文章會同時發布到我的 部落格園主頁、CSDN主頁、知乎主頁、微信公眾號 平台上。
微信搜索”痞子衡嵌入式“或者掃描下面二維碼,就可以在手機上第一時間看了哦。