查看: 1904|回复: 6

[分享] 串行Flash无法再次下载?检查下写保护设置

[复制链接]
  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3303

    主题

    6550

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32068
    最后登录
    2024-4-30
    发表于 2021-5-18 12:32:14 | 显示全部楼层 |阅读模式
    串行Flash无法再次下载?检查下写保护设置


    大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是导致串行NOR Flash在i.MXRT下无法正常下载/启动的常见因素之Write Protection。


    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因素》 和 《QE bit因素》, 今天痞子衡重点跟大家聊聊Write Protection这个因素。


    一、引入客户板子可以启动、无法再次下载问题
    痞子衡最近遇到一个智能电表厂商客户,他们项目板卡选用的是主控i.MXRT1051 + 华邦W25Q64JVSSIQ,应用程序是MBED bootloader + User App二级加载设计,其中MBED bootloader是由Arm Pelion物联网小组主导设计的,User App是这个电表厂商自己的功能代码。


    客户的问题是烧写了一个特定版本的MBED bootloader运行之后,板卡Flash无法再次做烧写了,但是板子是能够正常从Flash启动的。客户之后尝试使用了各种下载工具都不管用(J-Flash/IDE/NXP Tool等),其中下载工具包括痞子衡设计的一站式下载工具 MCUBootUtility ,于是问题就转到了痞子衡这里(好像有点躺枪的感觉)。工具后台报的错是擦除或者写入时会返回 kStatus_FlexSPINOR_CommandFailure,导致无法下载。
    11.png
    既然问题和特定版本的MBED bootloader有关,那看起来就是这个bootloader引入的问题,但是痞子衡拿不到客户MBED bootloader源码,无法做白盒分析。鉴于痞子衡这么多年和Flash打交道的经验,痞子衡盲猜是bootloader使能了Flash的软件写保护功能(Software Write Protection)导致的问题,于是痞子衡让客户寄来了一块板卡,实测来证实痞子衡的猜想。


    二、修改SDK FlexSPI例程来读取Status Register
    查看W25Q64JVSSIQ数据手册得知,软件写保护功能的配置集成在Flash器件内部非易失性Status Register中,这款Flash一共有3个8bit的Status Register(状态寄存器均支持易失性写入(即断电恢复)和非易失性写入(即断电保持),由前导的Write Enable命令类型0x06/0x50决定),并且每个Status Register都有不同的读写命令:
    12.png

    现在我们简单修改了下SDK里的如下flexspi nor例程(选择ram build),增加上述三个Status Register读取功能的支持,从而实测读取Status Register来做验证。
    1. \SDK_2.9.1_EVKB-IMXRT1050\boards\evkbimxrt1050\driver_examples\flexspi\nor\polling_transfer
    复制代码
    首先是在 app.h 和 flexspi_nor_polling_transfer.c 中将Status Register的读取命令加入到LUT表中。原来工程里已经有Status Register 1的读取支持,所以我们仅需增加Status Register 2/3的支持即可。因为这新增的两条命令,需要将CUSTOM_LUT_LENGTH由60改到64(i.MXRT1051上最大64,即支持16条LUT Sequence)。
    13.png
    1. const uint32_t customLUT[CUSTOM_LUT_LENGTH] = {
    2.     // ...

    3.     /* 原有 Read status register 1 */
    4.     [4 * NOR_CMD_LUT_SEQ_IDX_READSTATUSREG] =
    5.         FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x05, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),

    6.     /* 新增 Read status register 2 */
    7.     [4 * NOR_CMD_LUT_SEQ_IDX_READSTATUSREG2] =
    8.         FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x35, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),

    9.     /* 新增 Read status register 3 */
    10.     [4 * NOR_CMD_LUT_SEQ_IDX_READSTATUSREG3] =
    11.         FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x15, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),

    12.     // ...
    13. };
    复制代码
    然后在 flexspi_nor_flash_ops.c 中新增如下 flexspi_nor_get_status_register() 函数,这个函数直接仿照 flexspi_nor_get_vendor_id() 函数流程写即可,Flash端时序是一样的。
    1. status_t flexspi_nor_get_status_register(FLEXSPI_Type *base, uint8_t seqIndex, uint8_t *regValue)
    2. {
    3.     /* Wait status ready. */
    4.     uint32_t readValue;
    5.     flexspi_transfer_t flashXfer;

    6.     flashXfer.deviceAddress = 0;
    7.     flashXfer.port          = kFLEXSPI_PortA1;
    8.     flashXfer.cmdType       = kFLEXSPI_Read;
    9.     flashXfer.SeqNumber     = 1;
    10.     flashXfer.seqIndex      = seqIndex;
    11.     flashXfer.data          = &readValue;
    12.     flashXfer.dataSize      = 1;

    13.     status_t status = FLEXSPI_TransferBlocking(base, &flashXfer);
    14.     *regValue = readValue;

    15.     status = flexspi_nor_wait_bus_busy(base);

    16.     /* Do software reset. */
    17.     FLEXSPI_SoftwareReset(base);

    18.     return status;
    19. }
    复制代码
    最后就是在 flexspi_nor_polling_transfer.c 中的 main() 函数里增加 flexspi_nor_get_status_register() 函数调用语句,将Status Register 1/2/3的值全部读取出来。
    1. static uint8_t s_regValue1 = 0;
    2. static uint8_t s_regValue2 = 0;
    3. static uint8_t s_regValue3 = 0;

    4. int main(void)
    5. {
    6.     status_t status;
    7.     BOARD_ConfigMPU();
    8.     BOARD_InitPins();
    9.     BOARD_BootClockRUN();
    10.     BOARD_InitDebugConsole();

    11.     flexspi_nor_flash_init(EXAMPLE_FLEXSPI);

    12.     /* Get status register 1-3. */
    13.     status = flexspi_nor_get_status_register(EXAMPLE_FLEXSPI, NOR_CMD_LUT_SEQ_IDX_READSTATUSREG, &s_regValue1);
    14.     status = flexspi_nor_get_status_register(EXAMPLE_FLEXSPI, NOR_CMD_LUT_SEQ_IDX_READSTATUSREG2, &s_regValue2);
    15.     status = flexspi_nor_get_status_register(EXAMPLE_FLEXSPI, NOR_CMD_LUT_SEQ_IDX_READSTATUSREG3, &s_regValue3);

    16.     // ...
    17. }
    复制代码
    三、W25Q64JVSSIQ的Write Protection特性
    将上一节修改后的 flexspi nor 例程下载进RAM调试运行,可以读出Status Register 1/2/3的值分别为0x40、0x42、0x60,看起来Status Register确实被MBED bootloader修改过。痞子衡标出了W25Q64JVSSIQ内部状态寄存器中所有与写保护相关的bit位如下,我们需要对照Flash数据手册具体查看读出来的值对应了什么样的写保护设置:
    14.png
    15.png
    首先Status Register1[SRP],Status Register2[SRL]以及外部WP#引脚共同决定Status Register设置条件,本例中SRL和SRP均为0,则WP#引脚控制不生效,Status Register可以直接被设置。

    16.png
    Status Register中其他写保护相关的bit位解释如下,其中WPS是核心设置,它决定了写保护是用单独的Block lock命令来控制(见Flash命令集)还是直接由Status Register1/2中的CMP,TB,SEC,BPx位来决定。
    1. Status Register3[WPS]:决定写保护策略是独立的Block锁定命令控制(WPS=1,默认设置)还是由Status Register1/2控制(WPS=0)

    2. Status Register1[BPx]:指定Flash Memory保护区域块范围
    3. Status Register1[SEC]:指定Flash Memory保护区域块单位是4KB Sector(SEC=1)还是64KB Block(SEC=0)
    4. Status Register1[TB]:指定Flash Memory保护区域是从Top(TB=0)/Bottom(TB=1)开始
    5. Status Register2[CMP]:决定由BPx,SEC,TB决定的Flash Memory保护区域是否生效(否的话,则区域外是受保护的)
    复制代码
    综合上面分析,最后我们发现MBED bootloader将全部的8MB Flash空间都保护起来了,所以各种下载工具都无法正常烧写这款Flash了,要想重新使能烧写,需要一个单独的嵌入式小工程(可参考第2节里读SR功能修改步骤)将Status Register1/2/3值再改回到默认状态(WPS=1, CMP=0),这里就不再展开了。
    17.png
    这里仅以华邦Flash为例介绍Write Protection,其他厂商Flash对于这个Write Protection特性设计也许有所不同,需要查看数据手册具体分析。此外鉴于Flash这种种因素会导致在i.MXRT无法下载或正常启动,痞子衡之前计划做的全新上位机工具MCUTestSuite,会考虑将串行NOR Flash状态信息查询功能(SFDP/QE bit/Write Protection等)也放进去,敬请关注这个新项目:
    1. MCUTestSuite工具项目:https://github.com/JayHeng/NXP-MCUTestSuite
    复制代码
    至此,导致串行NOR Flash在i.MXRT下无法正常下载/启动的常见因素之Write Protection痞子衡便介绍完毕了,掌声在哪里~~~

    签到签到
    回复

    使用道具 举报

  • TA的每日心情
    无聊
    2024-4-29 08:18
  • 签到天数: 560 天

    [LV.9]以坛为家II

    34

    主题

    5922

    帖子

    2

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    5735
    最后登录
    2024-5-6
    发表于 2021-5-20 11:15:28 | 显示全部楼层
    好东西,都是干货
    哎...今天够累的,签到来了~
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2023-8-30 17:43
  • 签到天数: 306 天

    [LV.8]以坛为家I

    14

    主题

    1746

    帖子

    4

    金牌会员

    Rank: 6Rank: 6

    积分
    2540
    最后登录
    2023-8-30
    发表于 2021-5-20 18:20:05 | 显示全部楼层
    秘密麻麻都是数据和参数有点看不懂呀
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    昨天 08:02
  • 签到天数: 623 天

    [LV.9]以坛为家II

    0

    主题

    1823

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    4629
    最后登录
    2024-5-6
    发表于 2021-5-21 13:13:02 | 显示全部楼层
    学习学习
    哎...今天够累的,签到来了~
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2022-3-21 22:25
  • 签到天数: 44 天

    [LV.5]常住居民I

    0

    主题

    110

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    228
    最后登录
    2022-3-21
    发表于 2021-5-25 21:19:53 | 显示全部楼层
    学习了
    哎...今天够累的,签到来了~
    回复

    使用道具 举报

  • TA的每日心情
    无聊
    2021-5-27 14:51
  • 签到天数: 2 天

    [LV.1]初来乍到

    21

    主题

    75

    帖子

    1

    中级会员

    Rank: 3Rank: 3

    积分
    291
    最后登录
    2021-5-27
    发表于 2021-5-26 16:49:02 | 显示全部楼层
    学习下
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    昨天 09:26
  • 签到天数: 1418 天

    [LV.10]以坛为家III

    48

    主题

    3501

    帖子

    21

    金牌会员

    Rank: 6Rank: 6

    积分
    7332
    最后登录
    2024-5-6
    发表于 2021-6-2 09:23:46 | 显示全部楼层
    666,开发过程中经常会碰到的问题
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-5-7 06:50 , Processed in 0.124607 second(s), 25 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表