大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是导致串行 NOR Flash 在 i.MXRT 下无法正常下载 / 启动的常见因素之 SFDP。
i.MXRT 系列 MCU 发布已两年多了,基于 i.MXRT 的客户产品也越来越多,可以说是全面开花了。痞子衡作为 i.MXRT 产品线的系统应用工程师,早期的时候还可以尽情做参考设计,现在基本大量时间都被客户支持占据了。
因为 i.MXRT 系列都没有内置 Flash(RT1064, RT1024 等 SIP 型号除外),因此为其搭配一块串行 NOR Flash 去启动是客户项目的第一个头等大事,而串行 NOR Flash 厂商非常多,客户选择余地很大,因此我们不得不与客户一起同茫茫 Flash 型号打交道,痞子衡也常常调侃自己已沦为 Flash 测试工程师。
痞子衡在支持客户解决串行 NOR Flash 下载启动问题过程中主要遇到几个常见因素,这几个因素可能会影响 Flash 在 i.MXRT 下无法正常使用,今天痞子衡就重点跟大家聊聊 SFDP 这个因素。
一、SFDP 标准简介
SFDP 又叫 JESD216,是 JEDEC 协会于 2011 年开始推出的串行 Flash 接口标准,类似于 CFI 在并行 NOR Flash 上的标准。SFDP 发展至今已经诞生了如下版本:
时间 | 标准 |
---|---|
2011 | JESD216 |
2013.07 | JESD216A |
2014.05 | JESD216B |
2018.08 | JESD216C |
2018.11 | JESD216D |
2019.08 | JESD216D.01 |
我们知道串行 Flash 厂商非常多,在 2011 年之前,大家都是各自玩,没有明确的统一标准(虽然几个领头厂商起了示范作用,但各家在具体细节上还是会有差异),这对于 Flash 用户来说就比较麻烦了,需要把各家 Flash 手册仔细研读,不能漏掉任何一个细节。
随着串行 Flash 市场需求越来越强烈,各个厂商也在铆足劲给自家 Flash 加特性,这时候 JEDEC 站出来了,拉了几个主要的 Flash 厂商一起订个 SFDP 标准,有了这个标准,Flash 用户就方便多了,尤其是软件设计人员,开发 Flash 驱动从此有标准可依,甚至一套驱动可以用在所有支持 SFDP 标准的 Flash 上,实现各厂商 Flash 之间轻松切换。
二、部分 Flash 型号不支持 SFDP
因为 SFDP 标准是 2011 年才开始推出,新兴 Flash 厂商(比如兆易创新)的产品基本都是支持 SFDP 标准的,而部分老牌 Flash 厂商(比如华邦)则存在老型号和新型号共存的问题。老型号都是 2011 年前设计生产的,不支持 SFDP;2011 年之后设计的新型号基本都是支持 SFDP 的。
华邦目前是串行 Flash 第一大厂商,痞子衡遇到好几个 i.MXRT 客户,选用的华邦 NOR Flash,但 Flash 里不支持 SFDP,因此客户支持稍微复杂一些。关于 SFDP 支持问题,痞子衡特别联系过华邦销售人员,得到了他们的答复,华邦 NOR Flash 家族里 W25QxxJV 和 W25QxxJW 系列都是新型号,全部支持 SFDP;而 W25QxxFV 和 W25QxxFW 系列属于老型号,大多没有 SFDP,但是也有如下部分型号支持 SFDP:
虽然我们可以在后续开发的过程中也能正常使用非 SFDP 标准的 Flash 以及能通过读 SFDP 命令查询出芯片是否支持 SFDP,但最好在 Flash 选型前就能明确知道其 SFDP 情况,这个需要跟 Flash 厂商销售沟通好。总之,痞子衡推荐大家选用各厂商支持 SFDP 标准的新型号。
三、不支持 SFDP 的 Flash 如何适用 i.MXRT 下载
如果你认真看过痞子衡写的 i.MXRT 启动系列文章,你应该知道 i.MXRT 之所以能够支持市面上几乎所有的串行 NOR Flash 启动是靠的 512 byte 的 FDCB 结构体,这个结构体原型即 flexspi_nor_config_t,它可以描述启动所需的所有 Flash 参数信息。
i.MXRT 在启动时首先会用 1bit SDR 时序模式去获取用户放在 Flash 开始或偏移 0x400 处(因 i.MXRT 型号而异)的 FDCB,然后根据 FDCB 里的信息去进一步配置启动,因此 Flash 里有无 SFDP 其实不影响启动,只要在 FDCB 里描述清楚即可。
但是 Flash 里有无 SFDP 非常影响在 i.MXRT 相关配套工具下的擦写操作(俗称下载),因为所有工具(JLink、各 IDE、ROM 配套 Flashloader、痞子衡的 MCUBootUtility)默认都是基于 SFDP 来设计 Flash 下载算法的。
仅以 ROM 配套 Flashloader 为例,其上位机工具是 blhost.exe,它有如下经典的命令序列。这个序列就是利用用户提供简化的串行 Flash 配置值 0xc0000007(描述一般的四线 QSPI)来初始化 FlexSPI 以及 Flash,为后续擦写操作做准备。
blhost -u -- fill-memory 0x20202000 4 0xc0000007
blhost -u -- configure-memory 0x9 0x20202000
configure-memory 命令底层到底是什么样的逻辑呢?让我们找到任何一个 SDK 包,在 \SDK_2.x.x_MIMXRTxxxx-EVK\middleware\mcu-boot\src\memory\src\flexspi_nor_memory.c 里可以找到如下函数 flexspi_nor_mem_config(),它就是其底层逻辑,在这个函数里我们可以看到,Flashloader 会判断传来的 config 值到底是简化的 serial_nor_config_option_t,还是完整的 flexspi_nor_config_t。
如果 config 是简化的 serial_nor_config_option_t,Flashloader 会调用 flexspi_nor_get_config()函数去自动填充生成完整的 flexspi_nor_config_t,你可以继续去看 flexspi_nor_get_config()函数的实现,对于普通四线 QSPI,其就是根据 Flash 里读回的 SFDP 表内容来做的填充,因此这种方式下 SFDP 不可缺。
status_t flexspi_nor_mem_config(uint32_t *config)
{
status_t status = kStatus_InvalidArgument;
bool isNorConfigOption = false;
serial_nor_config_option_t *option = (serial_nor_config_option_t *)config;
flexspi_nor_config_t *norConfig = (flexspi_nor_config_t *)config;
if (option->option0.B.tag == kSerialNorCfgOption_Tag)
{
status = flexspi_nor_get_config(s_flexspiNorContext.instance, &s_flexspiNorConfigBlock, option);
// ...
isNorConfigOption = true;
}
else if (norConfig->memConfig.tag == FLEXSPI_CFG_BLK_TAG)
{
memcpy(&s_flexspiNorConfigBlock, norConfig, sizeof(flexspi_nor_config_t));
isNorConfigOption = true;
}
// ...
if (isNorConfigOption)
{
status = flexspi_nor_flash_init(s_flexspiNorContext.instance, &s_flexspiNorConfigBlock);
// ...
}
return status;
}
上面这种 0xc0000007 搞定一切四线 QSPI 的方式仅适用于含 SFDP 的 Flash,对于不含 SFDP 的 Flash 怎么办呢。其实上面已经给了解决方法,那就是直接提供完整的 FDCB,因此 i.MXRT 相关配套工具下载算法都需要相应改一下,痞子衡在两个项目上都做了非 SFDP Flash 支持:
- J-Link 下载算法源工程,可以参考 /boards/msft_rt600_xproject/flash_algo_b0_silicon/Keil_JLink 这个源工程
- MCUBootUtility v2.3 更新,参看文章 《MCUBootUtility v2.3 发布,这次不再放过任何一款 Flash》 第 2.3 节
至此,导致串行 NOR Flash 在 i.MXRT 下无法正常下载 / 启动的常见因素之 SFDP 痞子衡便介绍完毕了,掌声在哪里~~~