查看: 2804|回复: 0

i.MX RT系列MCU启动那些事(9) - 从Parallel NOR启动

[复制链接]
  • TA的每日心情
    开心
    2021-12-31 14:33
  • 签到天数: 45 天

    连续签到: 1 天

    [LV.5]常住居民I

    55

    主题

    144

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    1161
    最后登录
    2025-6-13
    发表于 2019-6-18 11:29:05 | 显示全部楼层 |阅读模式
    i.MX RT没有内置Flash,只有一块ROM区用于启动系统,并运行放在片外存储器中的代码。本站将连载痞子衡撰写的,关于i.MX RT产品启动相关的一系列文章,下面是系列中的第9篇。点击下面链接阅读前几篇:

    (4) - Flashloader初体验(5) - 再聊eFUSE及其烧写方法
    (7) - 掉队了,追赶中...

    大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是恩智浦i.MX RT系列MCU的Parallel NOR启动。

    上一篇讲i.MX RT从Raw NAND启动的文章一经发布,深入广大网友喜爱,短时间内阅读量飙升,这让痞子衡深受鼓舞,因此趁热打铁继续把从Parallel NOR启动也顺便一起讲了,为什么说是顺便呢?因为Parallel NOR与Raw NAND都是并行接口,属于同一门派,且这两种外存设备在i.MX RT内部是通过同一模块(SEMC)实现底层接口通信的,所以了解了Raw NAND启动,再来看Parallel NOR启动会觉得简单很多。话不多说,开讲。


    一、支持的并行NOR存储器


    依旧开门见山,i.MX RT支持加载启动的主要是,兼容CFI/JESD68标准且内置EPSCD命令集的ADM SLC Parallel NOR,这个命令集是目前的主流,最新的NOR产品都是使用这个命令集。至于数据线宽度,x8和x16都支持;关于时钟模式,i.MX RT105x和i.MX RT102x仅支持Asynchronous,i.MX RT106x既支持Asynchronous也支持Synchronous。

    关于Parallel NOR基本知识请先看一下痞子衡的另一篇文章《通用NOR接口标准(CFI-JESD68)及SLC Parallel NOR简介》。

    Parallel NOR厂商非常多,对应Parallel NOR芯片型号也很多,如果你在选型时不确定到底该为i.MX RT选择哪一款Parallel NOR时,可选用下面三款芯片,痞子衡均实测过:

    Micron MT28EW128ABA1LPC-0SIT

        x8/x16 bits

        32B Page/128KB Block/128Mb Device

        Non-ADM

        Asynchronous

    Winbond W29GL128CH9T

        x8/x16 bits

        64B Page/128KB Sector/128Mb Device

        Non-ADM

        Asynchronous

    Spansion S29GL128S90TFI020

        x16 bits

        512B Page/128KB Sector/128Mb Device

        Non-ADM

        Asynchronous

        注: ADM即地址线与数据线复用。为了减少芯片引脚,有些Parallel NOR芯片会将低位地址线与数据线复用,但目前市面上主流Parallel NOR芯片还是Non-ADM(即地址与数据是不复用的)居多。
        i.MX RT虽不能直接连接Non-ADM NOR芯片,但在i.MX RT与Non-ADM NOR芯片之间使用一片74系列锁存器桥接一下便能正常工作。


    二、Parallel NOR的硬件连接

    确定了Parallel NOR芯片选型后,接下来便进入Parallel NOR硬件电路设计,及与i.MX RT的信号连接环节。

    i.MX RT对于Parallel NOR的底层接口支持,是通过内部SEMC这个模块实现的。SEMC最多能支持五种设备(SDRAM、NAND、NOR、SRAM、8080显示接口),但SEMC接口信号是复用的,所以同一时刻仅能支持一种设备。

    下表是SEMC接口复用表,关于NOR接口信号,需要特别说一下的是CE#信号和地址线宽度,从表中可以看到NOR的CE4#信号有6个,即有6种配置选择,但i.MX RT的BootROM固定选择的是SEMC_CSX[0],至于地址线宽度,SEMC本身最大可支持28位地址宽度,但是i.MX RT的BootROM里最大只支持24位地址宽度(即A0-A23,最大128Mb),这2点在设计NOR硬件连接时需要特别注意。

        注: 对于小容量Paralle NOR芯片(比如512KB,地址线A0-A18),i.MX RT当然也可以支持,SEMC未用的地址线(即A19-A23)可不用管。

    011.png
    如下是典型的NOR硬件连接设计,示例NOR芯片是MT28EW128ABA1LPC-0SIT,该NOR芯片为Non-ADM,所以我们使用了一片74ALVT16373锁存器桥接,当WEIM_ADV_B信号为高电平时,锁存器Dx会输出给Qx,即此时WEIM_DATA[15:0]作为地址线输出给A[15:0],而WEIM_ADV_B信号为低电平时,WEIM_DATA[15:0]就是数据线(即此处WEIM_ADV_B作为ADV#信号是高有效,这在后续配置NOR eFUSE时会涉及到)。
    022.png

    三、Parallel NOR加载启动过程


    确保Parallel NOR硬件相关设计无误之后,就可以下载更新Bootable Image进Parallel NOR以供BootROM加载启动了,在下载Bootable image之前有必要先了解Parallel NOR的加载启动过程。

    痞子衡在启动系列文章的第六篇Bootable image格式与加载最后,已经介绍过non-XIP image加载启动过程,但实际上那个过程主要适用于存储在外部NAND Flash中Bootable image加载启动,对于存储在外部Parallel NOR的Bootable image而言有一些区别。我们知道NOR Flash是支持XIP执行的,所以从NOR启动有两种选择,一种是Non-XIP,另一种是XIP。
    对于Non-XIP启动而言,其基本流程与第六篇里介绍的non-XIP image加载启动过程类似,只有两点区别,第一个区别是存储在NOR Flash里的Bootable image中的IVT偏移地址,是固定在0x1000(对于NAND Flash,偏移固定是0x400);第二个区别是BootROM加载initial image的大小为12KB(对于NAND Flash,initial image是4KB),且这个initial image的加载不需要经过OCRAM缓存,BootROM是直接从NOR对应的SEMC map region去获取的。
    对于XIP启动而言,其基本流程与non-XIP image加载启动过程差异就比较大了,因为整个Bootable image都不需要搬运,BootROM直接从NOR对应的SEMC map region去获取IVT、BootData和应用程序代码,而BootROM中分配给SEMC NOR的XIP空间为0x90000000 - 0x90FFFFFF,所以XIP执行的应用程序代码需要链接在这个空间里。

    033.png

    有了前面的背景知识,NOR的加载启动过程便是上电之后,BootROM先从NOR起始地址处加载initial image数据(12KB),再根据initial image里的IVT获取应用代码起始地址,如代码地址是链接在SRAM里,便认为这是个Non-XIP程序,然后再将代码拷贝到相应SRAM里去启动;如代码地址是链接在SEMC NOR XIP空间里,则不需要拷贝,直接原地XIP执行启动。


    四、下载应用程序代码至Parallel NOR


    理解了Parallel NOR加载启动过程,我们便可以开始使用Flashloader下载程序代码至Parallel NOR芯片中

    痞子衡在启动系列文章的第四篇Flashloader初体验和第六篇Bootable image格式与加载,分别介绍了Flashloader的基本使用,以及如何将你的程序代码制作成Bootable image,但那里面制作的Bootable image主要是用于NAND启动,而对于NOR启动,其用于生成Bootable image的BD文件稍有不同。

    先来看Non-XIP的情况,下面是一个Non-XIP的BD文件示例,ivtOffset必须设0x1000,因为startAddress = 0x8000, initialLoadSize = 0x3000,所以代码只读段应从0xb000处开始链接:

    options {
        flags = 0x00;
        # Note: This is an example address, it can be any non-zero address in ITCM region
        startAddress = 0x8000;
        ivtOffset = 0x1000;
        initialLoadSize = 0x3000;
        # Note: This is required if the default entrypoint is not the Reset_Handler
        #       Please set the entryPointAddress to Reset_Handler address
        // entryPointAddress = 0xd531;
    }

    sources {
        elfFile = extern(0);
    }

    section (0)
    {
    }


    再来看XIP的情况,下面是一个XIP的BD文件示例,ivtOffset也必须设0x1000,因为startAddress = 0x90000000, initialLoadSize = 0x3000,所以程序代码的只读段应从0x90003000处开始链接:

    options {
        flags = 0x00;
        startAddress = 0x90000000;
        ivtOffset = 0x1000;
        initialLoadSize = 0x3000;
        # Note: This is required if the default entrypoint is not the Reset_Handler
        #       Please set the entryPointAddress to Reset_Handler address
        // entryPointAddress = 0x90005531;
    }

    sources {
        elfFile = extern(0);
    }

    section (0)
    {

    }

    假定你已经制作好Bootable image并且使用blhost工具与Flashloader建立了基本通信,正要开始将Bootable image下载进Parallel NOR。

    与Raw NAND启动一样,Parallel NOR也支持configuration block,只不过configuration block对于BootROM启动而言不是必需的,configuration block必须放在NOR Flash起始地址处,下面是其结构原型(如果你还有印象的话,你会发现它跟Raw NAND的semc_nand_config_t很像),如果想使能configuration block,你需要手动创建这256字节数据,并且用其覆盖bootable image的前256字节,在本文里暂不使能configuration block。

    #define SEMC_NOR_INIT_IMG_SIZE (12u * 1024)
    #define SEMC_NOR_MAX_SIZE (16U * 1024 * 1024)

    #define SEMC_MEM0_BASE (0x80000000u)
    #define SEMC_MEM1_BASE (0x90000000u)
    #define SEMC_MEM2_BASE (0xA0000000u)
    #define SEMC_MEM3_BASE (0xC0000000u)
    #define SEMC_MEM_NOR_AXI_BASE SEMC_MEM1_BASE

    typedef struct__semc_nor_config {
        semc_mem_config_t memConfig;//!< [0x000-0x04f]
        uint8_t vendorType;               //!< [0x050-0x050]
        uint8_t acTimingMode;           //!< [0x051-0x051]
        uint8_t deviceCommandSet;    //!< [0x052-0x052]
        uint8_t reserved0[77];         //!< [0x053-0x09f]
        uint32_t pageSizeInBytes;    //!< [0x0a0-0x0a3]
        uint32_t blockSizeInBytes;   //!< [0x0a4-0x0a7]
        uint32_t blockCount;             //!< [0x0a8-0x0ab]
        uint32_t reserved1[21];       //!< [0x0ac-0x0ff]
    } semc_nor_config_t;

    前面铺垫了这么多,终于来到关键地方了,到底怎么样将Bootable image数据下载进Parallel NOR中呢?当然还是靠Flashloader工具,我们只需要提供简化的4字节配置数据即可。下面是一种程序代码下载更新示例(该示例适用于第二节里介绍的NOR硬件连接):

    // 在SRAM里临时存储Parallel NOR配置数据
    blhost -p COMx -- fill-memory 0x2000 0x4 0xD0000600 // CSX0, ADV high active, 16bits IO, safe AC timing mode

    // 使用Parallel NOR配置数据去配置Parallel NOR接口
    blhost -p COMx -- configure-memory 0x8 0x2000

    在上述示例里痞子衡首先使用了fill-memory命令在0x2000地址处暂存了4字节的配置数据,然后通过config-memory将这4字节数据里的信息配置到Flashloader的Parallel NOR接口中,实际上这2个命令成功执行后,你就可以开始使用Flashloader下载Bootable image了。那么这4字节配置数据到底是怎么组织的?详见下表:

    044.png

    从上表我们可以知道,其实这4字节数据提供的配置信息主要是NOR配置,其中真正需要注意的只有两个地方(ADV# Polarity、Data Port Size),其余可用默认配置。

    configure-memory命令执行成功之后,image的下载很简单,只需要将Bootable image从SEMC NOR起始map地址开始下载即可,具体步骤如下:

    // 擦除Parallel NOR并将image下载进Parallel NOR
    blhost -p COMx -- flash-erase-region 0x90000000 0x20000
    blhost -p COMx -- write-memory 0x90000000 ivt_image.bin

        注: 实测发现,RT1050 Flashloader 1.1里使用USB接口去下载Parallel NOR会报kStatus_SemcNOR_ProgramVerifyFailure错误,而使用UART接口下载则正常,应该是USB下载对NOR的支持有缺陷,期望在后续版本的Flashloader里修复这个问题。

    Bootable image下载成功之后,我们可以试着用read-memory从NOR芯片里读回IVT、BootData、程序代码确认一下,Bootable image起始地址在0x90000000,那么IVT和BootData应该在0x90001000,程序代码应该在0x90003000:
    Non-XIP Bootable image读回情况如下,检查初始PC可知其链接在SRAM空间

    055.png
    XIP Bootable image读回情况如下,检查初始PC可知其链接在SEMC NOR map空间
    066.png

        注: 如果程序代码是XIP在SEMC NOR空间,其时钟初始化代码不能覆盖BootROM里对于SEMC的相关配置,否则XIP可能会失败。

    至此,代码的下载工作便结束了。



    五、进入Parallel NOR启动模式


    程序代码已经被成功下载进Parallel NOR芯片之后,此时我们便可以开始设置芯片从Parallel NOR启动.

    在进入Boot Device选择之前,你首先需要确定BOOT_MODE[1:0]=2'b00,即芯片处于Boot From Fuses模式,并且将BT_FUSE_SEL(eFUSE偏移0x460处的32位配置数据的第4位)烧写为1'b1,这里看不懂的朋友请温习痞子衡前面的文章Boot配置(BOOT Pin/eFUSE)。
    设置好正确Boot模式后,再来选择Boot Device,你还需要将BOOT_CFG1[7:4](eFUSE偏移0x450处的32位配置数据的位7:4)烧写成4'b0001,此时便进入了从SEMC NOR启动模式。
    如果想确保i.MX RT芯片一定正在从Parallel NOR启动,可在芯片上电时使用Jlink调试器,或者借助Flashloader读取芯片内部2个寄存器的值,这2个寄存器分别是SRC_SBMR1/2。我们设置的关于启动模式的BOOT_MODE pins/BOOT_CFG pin/eFUSE,偏移0x450配置值在上电时会自动加载到SRC_SBMR1/2寄存器里,BootROM主要是根据SRC_SBMR1/2寄存器的值来判断启动模式的。

    077.png

    PS: BOOT_MODE[1:0]也可以设为2'b10,即芯片处于Internal Boot模式,此时需要确保BT_FUSE_SEL(eFUSE偏移0x460处的32bit配置数据的bit4)为1'b0,和BOOT_CFG1[7:4]这四个引脚的输入状态设为4'b0001。


    六、配置eFUSE启动Parallel NOR
    设置好芯片启动模式是从Parallel NOR启动之后,我们还需要最后关注一下与Parallel NOR相关的具体特性配置。

    你应该记得,我们在使用Flashloader下载代码时,提供过4字节的NOR配置数据,这4字节的NOR配置数据是为了让Flashloader能够正确初始化Parallel NOR接口,去访问NOR芯片(主要是写Bootable image),同样BootROM上电也需要初始化Parallel NOR接口去访问NOR芯片(主要是读Bootable image),所以BootROM也需要类似这4字节NOR配置数据,而BootROM的NOR配置便放在如下的eFUSE区域里:

    088.png
    099.png
    上述所有步骤全部完成之后,复位芯片你就应该能看到你放在Parallel NOR里的程序代码已经正常地启动了。

    至此,i.MX RT系列MCU的Parallel NOR启动痞子衡便介绍完毕了,掌声在哪里~~~





    作者:痞子衡     文章出处:恩智浦MCU加油站


    11111签到
    回复

    使用道具 举报

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

    本版积分规则

    关闭

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

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

    GMT+8, 2025-7-20 06:44 , Processed in 0.085500 second(s), 20 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

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