痞子衡嵌入式:深扒i.MXRTxxx系列ROM中集成的串行NOR Flash启动SW Reset功能及其应用场合
大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是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 型号在这个方面特性只会微调和增强。
为了让大家对 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主页、知乎主页、微信公众号 平台上。
微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

痞子衡嵌入式:深扒i.MXRTxxx系列ROM中集成的串行NOR Flash启动SW Reset功能及其应用场合的更多相关文章
- 痞子衡嵌入式:了解i.MXRTxxx系列ROM中灵活的串行NOR Flash启动硬复位引脚选择
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRTxxx系列ROM中灵活的串行NOR Flash启动硬复位引脚选择. 关于 i.MXRT 系列 BootROM 中串行 NOR ...
- 痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash启动初始化流程
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是深入i.MXRT1050系列ROM中串行NOR Flash启动初始化流程. 从外部串行NOR Flash启动问题是i.MXRT系列开发最 ...
- 痞子衡嵌入式:了解i.MXRT1060系列ROM中串行NOR Flash启动初始化流程优化点
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT1060系列ROM中串行NOR Flash启动初始化流程优化点. 前段时间痞子衡写了一篇 <深入i.MXRT1050系 ...
- 痞子衡嵌入式:了解i.MXRTxxx系列ROM API及其与i.MXRT1xxx系列的差异
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRTxxx系列ROM API设计细节. 痞子衡之前写过两篇文章 <利用i.MXRT1xxx系列ROM提供的FlexSPI ...
- 痞子衡嵌入式:简析i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道. ECC 是 "Error Correc ...
- 痞子衡嵌入式:揭秘i.MXRTxxx系列上串行NOR Flash双程序可交替启动设计
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT500/600上串行NOR Flash双程序可交替启动设计. 在上一篇文章 <i.MXRT1170上串行NOR Fla ...
- 痞子衡嵌入式:利用i.MXRT1xxx系列ROM提供的FlexSPI driver API可轻松IAP
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT系列ROM中的FlexSPI驱动API实现IAP. 痞子衡的技术交流群里经常有群友提问: i.MXRT中的FlexSPI驱动 ...
- 痞子衡嵌入式:RT-MFB - 一种灵活的i.MXRT下多串行NOR Flash型号选择的量产方案
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是一种灵活的i.MXRT下多串行NOR Flash型号选择的量产方案. 对于以 i.MXRT 这类没有内部 NVM (Non-Volati ...
- 痞子衡嵌入式:在i.MXRT启动头FDCB里使能串行NOR Flash的QPI/OPI模式
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是在FDCB里使能串行NOR Flash的QPI/OPI模式. 我们知道 Flash 读时序里有五大子序列 CMD + ADDR + MO ...
随机推荐
- Redis压测
测试命令 这条命令redis自带 redis-benchmark [option] [option value] redis 性能测试工具可选参数如下所示: 序号 选项 描述 默认值 1 -h 指 ...
- 【模板】关于vector的lower_bound和upper_bound以及vector基本用法 STL
关于lower_bound和upper_bound 共同点 函数组成: 一个数组元素的地址(或者数组名来表示这个数组的首地址,用来表示这个数组的开头比较的元素的地址,不一定要是首地址,只是用于比较的& ...
- NOIP模拟测试11「string·matrix·big」
打的big出了点小问题,maxx初值我设的0然后少了10分 第二题暴力打炸 第一题剪了一些没用的枝依然40分 总分70 这是一次失败的考试 string 想到和序列那个题很像,但我没做序列,考场回忆学 ...
- html中各种标签和属性(最基础的基本都有)
1.标题标签: h1~h6 ctrl+1~6 2.段落标签: p ctrl+shift+p 3.换行标签: br shift+回车 4.水平线: hr 5.加粗标签: stro ...
- Redmine部署中遇到的问题
Redmine部署文章: 第一篇:Redmine部署 第二篇:Redmine部署中遇到的问题 上一篇文章我写了Redmine怎样部署(点这里直达上一篇文章),这一篇就写一下在Redmine部署中遇到过 ...
- 15、docker
15.0.服务器使用说明: 服务器名称 ip地址 controller-node1 172.16.1.90 15.1.docker介绍: 1.Docker 是一个开源的应用容器引擎,基于 Go 语言 ...
- hdu 1556 Color the ball 线段树 区间更新
水一下 #include <bits/stdc++.h> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 ...
- 删除有序数组中的重复项II
题目描述 给你一个有序数组 nums ,请你原地删除重复出现的元素,使每个元素最多出现两次,返回删除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组 并在使用O(1)额外空间的条件下 ...
- 使用IDEA配置Maven
IDEA中配置Maven File --> settings 推荐配置:设置maven在不联网的情况下使用本地插件 一般使用maven为我们提供好的骨架时,是需要联网的,配置这个,可以在没有网络 ...
- hadoop学习(一)环境的搭建
1.安装几台Linux虚拟机.安装的过程就不赘述了,网上教程很多.win7系统上装了一个VMWare,因为一些原因,VMWare版本不是最新的,是VMWare7.1版本,由于VMWare版本不高,所以 ...