本文由 发布,转载请注明出处,如有问题请联系我们! 发布时间: 2021-05-18痞子衡嵌入式:导致串行NOR Flash在i.MXRT下无法正常下载/启动的常见因素之Write Protection

加载中

无赖衡内嵌式:造成串行通信NOR Flash在i.MXRT下没法一切正常免费下载/运行的普遍要素之Write Protection


  各位好!,我是无赖衡,是正儿八经搞技术性的无赖。今日无赖衡给大伙儿详细介绍的是造成串行通信NOR Flash在i.MXRT下没法一切正常免费下载/运行的普遍要素之Write Protection

  i.MXRT系列产品MCU公布已2年多了,根据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,造成无法打开。

  即然难题和特殊版本号的MBED bootloader相关,那看上去就是这个bootloader引进的难题,可是无赖衡拿不上顾客MBED bootloader源代码,没法做白盒剖析。由于无赖衡这些年和Flash相处的工作经验,无赖衡盲猜是bootloader也就能了Flash的手机软件写保护作用(Software Write Protection)造成的难题,因此无赖衡让顾客寄来啦一块主控板,评测来确认无赖衡的猜测。

二、改动SDK FlexSPI方法来载入Status Register

  查询W25Q64JVSSIQ数据信息指南获知,手机软件写保护作用的配备集成化在Flash元器件內部非易失性Status Register中,这款Flash一共有3个9ait的Status Register(情况存储器均适用易失性载入(即关闭电源修复)和非易失性载入(即关闭电源维持),由流板的Write Enable指令种类c006/c050决策),而且每一个Status Register都是有不一样的读写能力指令:

  如今大家简易改动了下SDK里的以下flexspi nor方法(挑选ram build),提升以上三个Status Register载入作用的适用,进而评测载入Status Register来做认证。

\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)。

const uint32_t customLUT[CUSTOM_LUT_LENGTH] = {
    // ...

    /* 原来 Read status register 1 */
    [4 * NOR_CMD_LUT_SEQ_IDX_READSTATUSREG] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, c005, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, c004),

    /* 增加 Read status register 2 */
    [4 * NOR_CMD_LUT_SEQ_IDX_READSTATUSREG2] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, c035, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, c004),

    /* 增加 Read status register 3 */
    [4 * NOR_CMD_LUT_SEQ_IDX_READSTATUSREG3] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, c015, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, c004),

    // ...
};

  随后在 flexspi_nor_flash_ops.c 中增加以下 flexspi_nor_get_status_register() 涵数,这一涵数立即模仿 flexspi_nor_get_vendor_id() 涵数步骤写就可以,Flash端时钟频率是一样的。

status_t flexspi_nor_get_status_register(FLEXSPI_Type *base, uint8_t seqIndex, uint8_t *regValue)
{
    /* Wait status ready. */
    uint32_t readValue;
    flexspi_transfer_t flashXfer;

    flashXfer.deviceAddress = 0;
    flashXfer.port          = kFLEXSPI_PortA1;
    flashXfer.cmdType       = kFLEXSPI_Read;
    flashXfer.SeqNumber     = 1;
    flashXfer.seqIndex      = seqIndex;
    flashXfer.data          = &readValue;
    flashXfer.dataSize      = 1;

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

    status = flexspi_nor_wait_bus_busy(base);

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

    return status;
}

  最终便是在 flexspi_nor_polling_transfer.c 中的 main() 涵数里提升 flexspi_nor_get_status_register() 调用函数句子,将Status Register 1/2/3的值所有载入出去。

static uint8_t s_regValue1 = 0;
static uint8_t s_regValue2 = 0;
static uint8_t s_regValue3 = 0;

int main(void)
{
    status_t status;
    BOARD_ConfigMPU();
    BOARD_InitPins();
    BOARD_BootClockRUN();
    BOARD_InitDebugConsole();

    flexspi_nor_flash_init(EXAMPLE_FLEXSPI);

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

    // ...
}

三、W25Q64JVSSIQ的Write Protection特点

  将上一节改动后的 flexspi nor 方法免费下载进RAM调节运作,能够 读取Status Register 1/2/3的值各自为c040、c042、c060,看上去Status Register的确被MBED bootloader改动过。无赖衡标明了W25Q64JVSSIQ內部情况存储器中全部与写保护有关的bit位以下,大家必须对比Flash数据信息指南实际查询读出的值相匹配了哪些的写保护设定:

  最先Status Register1[SRP],Status Register2[SRL]及其外界WP#脚位一同决策Status Register设定标准,本例中SRL和SRP均为0,则WP#脚位操纵不起效,Status Register能够 立即被设定。

  Status Register中别的写保护有关的bit位表述以下,在其中WPS是关键设定,它决策了写保护是用独立的Block lock指令来操纵(见Flash命令集)或是立即由Status Register1/2中的CMP,TB,SEC,BPx位来决策。

Status Register3[WPS]:决策写保护对策是单独的Block锁住指令操纵(WPS=1,默认)或是由Status Register1/2操纵(WPS=0)

Status Register1[BPx]:特定Flash Memory维护地区块范畴
Status Register1[SEC]:特定Flash Memory维护地区块企业是4k高清B Sector(SEC=1)或是64KB Block(SEC=0)
Status Register1[TB]:特定Flash Memory维护地区是以Top(TB=0)/Bottom(TB=1)逐渐
Status Register2[CMP]:决策由BPx,SEC,TB决策的Flash Memory维护地区是不是起效(否得话,则地区外是受维护的)

  综合性上边剖析,最终大家发觉MBED bootloader将所有的8MB Flash室内空间都维护起来了,因此 各种各样下载神器都没法一切正常烧录这个Flash了,要想再次也就能烧录,必须一个独立的内嵌式小工程项目(可参照第二节里读SR作用改动流程)将Status Register1/2/3值再改返回默认设置情况(WPS=1, CMP=0),这儿就不会再进行了。

  这儿仅以华邦Flash为例子详细介绍Write Protection,别的生产商Flash针对这一Write Protection特点设计方案或许各有不同,必须查询数据信息指南深入分析。除此之外由于Flash这诸多要素会造成在i.MXRT无法打开或一切正常运行,无赖衡以前方案做的全新升级上位机软件专用工具MCUTestSuite,会考虑到将串行通信NOR Flash情况记录查询作用(SFDP/QE bit/Write Protection等)也装进去,敬请期待这一最新项目:

  • MCUTestSuite专用工具新项目:https://GitHub.com/JayHeng/NXP-MCUTestSuite

  到此,造成串行通信NOR Flash在i.MXRT下没法一切正常免费下载/运行的普遍要素之Write Protection无赖衡便详细介绍结束了,欢呼声在哪儿~~~

热烈欢迎定阅

文章发表另外公布到我的 博客园首页、CSDN首页、知乎问答首页、微信公众平台 服务平台上。

搜索微信"无赖衡内嵌式"或是扫描仪下边二维码,就可以在手机上第一时间看过哦。

评论(0条)

刀客源码 游客评论