查看: 5828|回复: 0

[分享] 这个FlexSPI有隐藏新功能,让我们解锁它

[复制链接]
  • TA的每日心情
    开心
    2025-7-11 08:53
  • 签到天数: 301 天

    连续签到: 2 天

    [LV.8]以坛为家I

    3938

    主题

    7559

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    40222
    最后登录
    2025-9-9
    发表于 2020-8-21 13:35:41 | 显示全部楼层 |阅读模式
    这个FlexSPI有隐藏新功能,让我们解锁它


    大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是i.MXRT三位数系列隐藏的FlexSPI Remap功能。


    前段时间痞子衡写了一篇文章 《利用i.MXRT1060,1010上新增的FlexSPI地址重映射(Remap)功能可安全OTA》,介绍了Remap功能在OTA设计中的重要性。如果你对比过i.MXRT三位数(RT500/600)和四位数(RT1xxx)的FlexSPI模块,你会发现它们是一样的,寄存器定义几乎完全一致。但是我们知道这两个系列又分别是来自不同平台(LPC/i.MX),i.MXRT三位数可没有i.MXRT四位数上用于存放Remap控制的IOMUXC_GPR模块,那么在i.MXRT500/600上到底有没有Remap功能呢?本文痞子衡将为你解答。


    1. FlexSPI NOR系统映射地址
    老规矩还是先看一下FlexSPI在i.MXRT三位数上的系统映射空间。因为内核架构的差异,分配的映射地址与i.MXRT1xxx上完全不同。


    i.MXRT500中分配给FlexSPI的系统映射空间如下,两个FlexSPI各分配了128MB。
    1.png
    i.MXRT600中分配给FlexSPI的系统映射空间如下,一个FlexSPI分配了128MB。
    2.png
    2. FlexSPI Remap控制在哪里?
    目前我们已经可以从恩智浦官网下载到i.MXRT600的SDK软件包和参考手册,i.MXRT500的资料暂时还没有公布。对于i.MXRT600,无论是在SDK软件包中的头文件还是在参考手册中搜索“Remap”关键字,都搜不到任何信息,莫非是没有Remap功能?


    好了,痞子衡就不卖关子了,其实Remap功能是支持的,而且直接做到了FlexSPI模块里,控制寄存器也在FlexSPI里,就在FLEXSPI BASE地址偏移0x420的地方(模块有更新,但文档暂时没有同步更新):

    1. typedef struct
    2. {
    3.     __IO uint32_t HADDRSTART;
    4.     __IO uint32_t HADDREND;
    5.     __IO uint32_t HADDROFFSET;
    6. } FLEXSPI_REMAP_Type;

    7. #define FLEXSPI_REMAP  ((FLEXSPI_REMAP_Type *)(FLEXSPI_BASE + 0x420u));
    复制代码
    因为Remap控制嵌在FlexSPI模块寄存器里,所以对于有两个FlexSPI模块的i.MXRT500,Remap控制也有两组,相互独立,这点跟同样有两个FlexSPI模块的i.MXRT1060上Remap设计是不一样的。


    3. FlexSPI Remap功能设计
    虽然i.MXRT500/600上的Remap控制嵌在FlexSPI模块内部,但Remap设计依然是属于系统架构层面的,只是在AHB总线层面做一个地址重定向。下面是Remap控制寄存器:
    3.png
    Remap设计很简单,就是地址(addr)落在[ADDR_START, ADDR_END]里的AHB读访问,其实际访问到的是addr + ADDR_OFFSET位置处的数据。(注意ADDR_START, ADDR_END, ADDR_OFFSET都是4KB对齐的)
    4.png
    Remap功能及寄存器定义上基本跟i.MX1xxx保持一致,但有一个小区别,就是HADDRSTART寄存器的bit0同时也承担了Remap功能开关控制。
    5.png
    4. Remap对擦写Flash的影响
    启用Remap功能后,调用FlexSPI NOR驱动函数去擦写Flash不会受影响,擦写Flash操作正常走的是FlexSPI IPG命令方式,数据没有经过AHB bus。



    下面这段测试代码是在MIMXRT500-EVK上跑的,用ROM API驱动擦写0x08100000地址,擦写操作前加了一段Remap设置干扰,实测下来Remap设置对擦写没有任何影响,复位后去读Flash,操作的还是原0x08100000地址。

    1. #define FLEXSPI0_REMAP  ((FLEXSPI_REMAP_Type *)(FLEXSPI0_BASE + 0x420u));

    2. flexspi_nor_config_t flashConfig;
    3. serial_nor_config_option_t configOption;
    4. configOption.option0.U = 0xc0403004;

    5. uint32_t programBuffer[64];
    6. for (uint32_t i = 0; i < sizeof(programBuffer); i++)
    7. {
    8.     *((uint8_t *)programBuffer + i) = (uint8_t)(i & 0xFF);
    9. }

    10. g_bootloaderTree->flexspiNorDriver->get_config(1, &flashConfig, &configOption);
    11. g_bootloaderTree->flexspiNorDriver->init(1, &flashConfig);

    12. FLEXSPI0_REMAP->HADDRSTART  = 0x08100000 | 0x01;
    13. FLEXSPI0_REMAP->HADDREND    = 0x08200000;
    14. FLEXSPI0_REMAP->HADDROFFSET = 0x100000;

    15. g_bootloaderTree->flexspiNorDriver->erase(1, &flashConfig, 0x100000, 0x100);
    16. g_bootloaderTree->flexspiNorDriver->page_program(1, &flashConfig, 0x100000, programBuffer);
    复制代码
    Remap寄存器因为在FlexSPI模块中,因此Remap设置代码要在FlexSPI模块初始化之后,仅有模块时钟被开启,模块寄存器才能正常赋值,否则不生效(实测时钟不打开,读写Remap寄存器永远是0,并且不产生HardFault)。


    5. 关于ROM API传参的疑惑解释
    最后再简单说一下第4节示例代码里一点让人疑惑的地方,我们是在MIMXRT500-EVK上做的测试,i.MXRT500有两个FlexSPI(0/1),Flash是连在FlexSPI0上,但是ROM API里的instance传参竟然需要是1(i.MXRT1060 ROM API的FLEXSPI0传参就是0),这是怎么回事?


    下面是i.MXRT500 BootROM中根据instance获取FLEXSPI模块基址的函数代码,其是根据i.MXRT500头文件中FLEXSPI_BASE_PTRS定义来获取基址值的。


    1. static FLEXSPI_Type *const g_flexSpiInstances[] = FLEXSPI_BASE_PTRS;

    2. static FLEXSPI_Type *flexspi_get_module_base(uint32_t instance)
    3. {
    4.     FLEXSPI_Type *baseAddr = NULL;
    5.     baseAddr = g_flexSpiInstances[instance];
    6.     return baseAddr;
    7. }
    复制代码
    而BootROM中用的i.MXRT500头文件中FLEXSPI_BASE_PTRS定义如下所示,有点奇怪,跟正式SDK里的定义不一致。其实也可以理解,BootROM是芯片设计阶段的产物,那时候头文件是初版,后期有变化也正常。

    1. /** Array initializer of FLEXSPI peripheral base pointers */
    2. #define FLEXSPI_BASE_PTRS                      \
    3.     {                                          \
    4.         (FLEXSPI_Type *)0u, FLEXSPI1, FLEXSPI2 \
    5.     }
    复制代码
    至此,i.MXRT三位数系列隐藏的FlexSPI Remap功能痞子衡便介绍完毕了,掌声在哪里~~~


    文章出处:痞子衡嵌入式

    qiandao qiandao
    回复

    使用道具 举报

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

    本版积分规则

    关闭

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

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

    GMT+8, 2025-9-10 04:34 , Processed in 0.083767 second(s), 20 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

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