T O P

[资源分享]     痞子衡嵌入式:了解i.MXRTxxx系列ROM中灵活的串行NOR Flash启动硬复位引脚选择

  • By - 楼主

  • 2021-07-22 00:00:59

  •   大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是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主页知乎主页微信公众号 平台上。

    微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

    本帖子中包含资源

    您需要 登录 才可以下载,没有帐号?立即注册