痞子衡嵌入式:深扒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 ...
随机推荐
- laya fgui 超简单的UI框架
FairyGUI 超简单的UI框架 Laya使用fgui的超简单UI框架 使用场景:用于使用fgui进行layaUI开发的程序人员 整个框架分为3个模块,共有4个类: FGUIManager :FGU ...
- Mybatis 中经典的 9 种设计模式!面试可以吹牛了
虽然我们都知道有23个设计模式,但是大多停留在概念层面,真实开发中很少遇到.Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更深入的理解设计模式. Mybatis至少 ...
- java面试技巧及层次。
不断的积累,从打算找工作之日起,就要坚持在每天闲暇之余学习其中几道题目,日积月累,等到出去面试时,一切都水到渠成,面试时就自然会游刃有余了. 答题时,先答是什么,再答有什么作用和要注意什么,这里给人的 ...
- 入门Kubernetes - .Net Core 运行
前言: 之前文章 对Kubernetes 的一些基础概念及在windows下的环境搭建,接下来把.Net Core 运行到Kubernetes 中,在实际的操作中,对Kubernetes 的进一步学习 ...
- 《吃透微服务》 - 服务容错之Sentinel
大家好,我是小菜. 一个希望能够成为 吹着牛X谈架构 的男人!如果你也想成为我想成为的人,不然点个关注做个伴,让小菜不再孤单! 本文主要介绍 SpringCloud中Sentinel 如有需要,可以参 ...
- 把 STM32 bluepill 变成调试器(daplink)
在调一块 ARM M0 内核的板子,使用官方的 DEMO 板子来调,板子上集成了 daplink 调试器. 为了方便使用,我把目标板跟 daplink 剪开了,然后用杜邦线把 daplink 跟目标板 ...
- 浙江大学计算机程序设计能力考试(PAT)简介
计算机程序设计能力考试(Programming Ability Test,简称 PAT)旨在通过统一组织的在线考试及自动评测方法客观地评判考生的算法设计与程序设计实现能力,科学地评价计算机程序设计人才 ...
- 10年程序员的编程语言感受与Go的结缘
因为小编最近在写两套教程,分别是Java语言基础教程和Go语言的基础教程,并且这 2 门语言,小编在实际的工作中也都有用过 而且 www.helloworld.net 社区的后台,就是用Go语言写的, ...
- __sync_fetch_and_add函数(Redis源码学习)
__sync_fetch_and_add函数(Redis源码学习) 在学习redis-3.0源码中的sds文件时,看到里面有如下的C代码,之前从未接触过,所以为了全面学习redis源码,追根溯源,学习 ...
- Gym 101206L Daylight Saving Time 根据年月日计算星期
题意: [3月的第二个周日02:00:00 , 3月的第二个周日03:00:00) 这个区间都不是PST或PDT,[11月的第一个周日01:00:00 , 11月的第一个周日02:00:00) 这个区 ...