痞子衡嵌入式:FlexSPI复位方式不当会致使i.MXRT系列下OTFAD加密启动失败


  你们好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给你们分享的是FlexSPI复位方式不当会致使i.MXRT系列下OTFAD加密启动失败问题html

  本篇是《系统时钟配置不当会致使i.MXRT1xxx系列下OTFAD加密启动失败》 的后续篇,咱们为i.MXRT1010解决了OTFAD时钟配置限制问题后,加密的App就必定能正常跑了吗?其实并不必定,若是你的App跟IAP有关(即会调用FlexSPI驱动去擦写Flash),免不了会在FlexSPI驱动里操做FlexSPI外设寄存器的软复位位,软复位操做方式使用不当可能会致使App没法正常运行,今天痞子衡就来好好聊一聊这个FlexSPI复位小限制:微信

  • Note1: 虽然i.MXRT1170也包含OTFAD,可是本文中的FlexSPI复位限制问题在i.MXRT1170上并不存在。
  • Note2: 三位数系列i.MXRT600一样包含OTFAD,且也受本文中的FlexSPI复位限制影响。

1、问题描述

  从恩智浦官网下载一个SDK包(痞子衡下的是v2.9.1),选择其中 flexspi 例程 \SDK\boards\evkmimxrt1010\driver_examples\flexspi\nor\polling_transfer\ 。编译这个 flexspi_nor_polling_transfer 工程(选择 flexspi_nor_debug build,即XIP工程),获得可执行文件,将其下载到 MIMXRT1010-EVK 板载Flash中离线启动(正常模式,不加密),打开串口调试助手看到以下结果:app

  这个结果是例程预期结果,你可能会对这个XIP build也能擦写Flash感到奇怪,按说板载Flash没有RWW功能,擦写Flash操做不能在Flash里原地执行,可是例程的连接文件里已经将涉及Flash擦写代码的源文件直接放在RAM里了,所以例程是能够正常执行的。函数

  如今让咱们根据《系统时钟配置不当会致使i.MXRT1xxx系列下OTFAD加密启动失败》 文中操做使能OTFAD加密,将整个App空间都加密,记得要修复系统时钟配置限制问题,这时候再离线启动,看到串口调试助手没有任何输出,说明例程执行失败了。查看工程源代码,main()函数里第一句打印前调用了 flexspi_nor_flash_init(EXAMPLE_FLEXSPI);, 看起来OTFAD加密后这个Flash初始化函数执行不太正常。flex

  为了定位问题方便,咱们回到不加密模式,给 flexspi_nor_polling_transfer 工程加上一些辅助调试的打印信息,主要是FlexSPI相关API函数调用前加上打印信息。注意:须要将以下三个源文件也放到RAM中才能看到控制台完整输出。ui

initialize by copy {
  object fsl_debug_console.o,
  object fsl_adapter_lpuart.o,
  object fsl_lpuart.o,
};

  有了辅助打印信息,咱们如今再回到OTFAD加密模式,能够看到代码停在 FLEXSPI_UpdateLUT() 函数就没有继续执行下去了。本文不是为了讲述如何一步步找到问题的方法,痞子衡其实知道就是 FLEXSPI_SoftwareReset() 函数惹的祸(没有停在这个函数,是因为系统buffer的缘故),至因而什么缘由,详见下节。加密

static inline void FLEXSPI_SoftwareReset(FLEXSPI_Type *base)
{
    base->MCR0 |= FLEXSPI_MCR0_SWRESET_MASK;
    while (0U != (base->MCR0 & FLEXSPI_MCR0_SWRESET_MASK))
    {
    }
}

2、缘由分析

  老规矩,痞子衡直接给答案,这是OTFAD对FlexSPI外设复位的小限制,当OTFAD被使能时,若是被加密的app代码是XIP执行,app里利用FlexSPI->MCR0[SWRESET]位作复位时,这个swreset复位功能会同时清掉FlexSPI->INTR[KEYDONE]位,而FlexSPI的运行依赖OTFAD解析KeyBlob的结果,当FlexSPI->INTR[KEYDONE]位是0时,对Flash的AHB访问会被禁掉,故而发生CPU lockup,代码没法继续执行。.net

KEYDONE位为1 - 代表OTFAD解析KeyBlob已正常完成;
KEYDONE位为0 - 代表OTFAD正在解析KeyBlob过程当中;

  FlexSPI->MCR0[SWRESET]位存在于任何一款i.MXRT芯片型号中,其功能是复位FlexSPI外设,在下面几个场景均可以去作一次FlexSPI外设复位,不用担忧,这个外设复位并不影响FlexSPI配置寄存器里的值。不过比较遗憾的是在此时的OTFAD加密启动使能情形下,不能再用MCR0[SWRESET]位去作复位了debug

场景一:初始化FlexSPI,打开MCR0[MDIS]位使能模块时
场景二:更新了FlexSPI的LUT表后
场景三:切换了FlexSPI的工做模式后(好比使能Flash四线)
场景四:完成了FlexSPI的擦、写命令后

3、解决方案

  不少时候FlexSPI->MCR0[SWRESET]位更可能是被用来清除AHB TX/RX Buffer(尤为是在Flash擦写以后),在i.MXRT1010 FlexSPI外设的AHBCR寄存器里其实新增了单独的CLRAHBTXBUF和CLRAHBRXBUF控制位,用以实现AHB TX/RX Buffer的清除。所以咱们为了不影响OTFAD加密启动,可使用AHBCR[CLRAHBTXBUF/CLRAHBRXBUF]位来代替MCR0[SWRESET]位去作复位。调试

  所以在 flexspi_nor_polling_transfer 工程里,将FLEXSPI_SoftwareReset()函数调用所有改为以下的FLEXSPI_ClearAhbBuffer()函数调用就能够保证工程正常运行了。

static inline void FLEXSPI_ClearAhbBuffer(FLEXSPI_Type *base)
{
#if defined(FSL_FEATURE_SOC_OTFAD_COUNT) && defined(FLEXSPI_AHBCR_CLRAHBRXBUF_MASK)
    base->AHBCR |= FLEXSPI_AHBCR_CLRAHBRXBUF_MASK | FLEXSPI_AHBCR_CLRAHBTXBUF_MASK;
    base->AHBCR &= ~(FLEXSPI_AHBCR_CLRAHBRXBUF_MASK | FLEXSPI_AHBCR_CLRAHBTXBUF_MASK);
#endif
}

  至此,FlexSPI复位方式不当会致使i.MXRT系列下OTFAD加密启动失败问题痞子衡便介绍完毕了,掌声在哪里~~~

欢迎订阅

文章会同时发布到个人 博客园主页CSDN主页知乎主页微信公众号 平台上。

微信搜索"痞子衡嵌入式"或者扫描下面二维码,就能够在手机上第一时间看了哦。

相关文章
相关标签/搜索