野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 9810|回复: 4

IAR的nor_txt_ram.icf文件的几处疑问

[复制链接]
发表于 2018-11-29 16:44:15 | 显示全部楼层 |阅读模式

[mw_shl_code=c,true]define symbol m_interrupts_start       = 0x60002000;
define symbol m_interrupts_end         = 0x600023FF;

define symbol m_text_start             = 0x60002400;
define symbol m_text_end               = 0x61FFFFFF;

define symbol m_data_start             = 0x20000000;
define symbol m_data_end               = 0x2001FFFF;

define symbol m_data2_start            = 0x20200000;
define symbol m_data2_end              = 0x2023FFFF;

define exported symbol m_boot_hdr_conf_start = 0x60000000;
define symbol m_boot_hdr_ivt_start           = 0x60001000;
define symbol m_boot_hdr_boot_data_start     = 0x60001020;
define symbol m_boot_hdr_dcd_data_start      = 0x60001030;

/* Sizes */
if (isdefinedsymbol(__stack_size__)) {
  define symbol __size_cstack__        = __stack_size__;
} else {
  define symbol __size_cstack__        = 0x0400;
}

if (isdefinedsymbol(__heap_size__)) {
  define symbol __size_heap__          = __heap_size__;
} else {
  define symbol __size_heap__          = 0x0400;
}

define exported symbol __VECTOR_TABLE  = m_interrupts_start;
define exported symbol __VECTOR_RAM    = m_interrupts_start;
define exported symbol __RAM_VECTOR_TABLE_SIZE = 0x0;

define memory mem with size = 4G;
define region TEXT_region = mem:[from m_interrupts_start to m_interrupts_end]
                          | mem:[from m_text_start to m_text_end];

define region DATA_region = mem:[from m_data_start to m_data_end-__size_cstack__];
define region DATA2_region = mem:[from m_data2_start to m_data2_end];
define region CSTACK_region = mem:[from m_data_end-__size_cstack__+1 to m_data_end];

define block CSTACK    with alignment = 8, size = __size_cstack__   { };
define block HEAP      with alignment = 8, size = __size_heap__     { };
define block RW        { readwrite };
define block ZI        { zi };
define block NCACHE_VAR    { section NonCacheable , section NonCacheable.init };

initialize by copy { readwrite, section .textrw };
do not initialize  { section .noinit };

place at address mem: m_interrupts_start    { readonly section .intvec };

place at address mem:m_boot_hdr_conf_start { section .boot_hdr.conf };
place at address mem:m_boot_hdr_ivt_start { section .boot_hdr.ivt };
place at address mem:m_boot_hdr_boot_data_start { readonly section .boot_hdr.boot_data };
place at address mem:m_boot_hdr_dcd_data_start { readonly section .boot_hdr.dcd_data };

keep{ section .boot_hdr.conf, section .boot_hdr.ivt, section .boot_hdr.boot_data, section .boot_hdr.dcd_data };

place in TEXT_region                        { readonly };
place in DATA_region                        { block RW };
place in DATA_region                        { block ZI };
place in DATA_region                        { last block HEAP };
place in DATA_region                        { block NCACHE_VAR };
place in CSTACK_region                      { block CSTACK };[/mw_shl_code]
这种模式下,代码保存并运行与SPI NorFlash中,Flash起始地址为0x6000 0000的。通过place at address mem: m_interrupts_start { readonly section .intvec }这句话可以知道中断向量表放置在0x6000 2000~0x6000 203F,因为我看IAR手册定义,.intvec必须放在0x00~0x3F的地址范围。如下图所示:
123.png
(1)请问这种理解是否正确?
(2)那么m_interrupts_end - m_interrupts_start = 0x3FF,大于0x3F的内容放的什么呢?
(3)0x6000 0000~0x6000 1FFF这段地址,放置了这些section .boot_hdr.conf、section .boot_hdr.ivt、readonly section .boot_hdr.boot_data、
readonly section .boot_hdr.dcd_data,这是是什么?没找到相关介绍,section .boot_hdr.ivt这个.ivt也是中断向量表吗?
菜鸟一个,还望给予解答,谢谢!
回复

使用道具 举报

发表于 2018-11-30 08:06:06 | 显示全部楼层
本帖最后由 xiaobakang 于 2018-11-30 08:12 编辑

1. initialize by copy { readwrite, section .textrw };
do not initialize  { section .noinit };   
我的理解是程序虽然存放在FALSH中,但上电后初始化后通过上面这段代码把程序copy到RAM/SDRAM中运行。2. section .boot_hdr.conf、section .boot_hdr.ivt、readonly section .boot_hdr.boot_data、
readonly section .boot_hdr.dcd_data 这些字段在野火工程的XIP文件夹下
fire_imxrt1052_sdram_ini_dcd.c  fire_imxrt1052_spiflash_config.c fsl_flexspi_nor_boot.c  三个文件的开头处定义。
LZ如果还不明白,请看下面这个链接,关于icf文件的讲解
https://blog.csdn.net/hj74535099/article/details/44243089
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-11-30 15:15:26 | 显示全部楼层
xiaobakang 发表于 2018-11-30 08:06
1. initialize by copy { readwrite, section .textrw };
do not initialize  { section .noinit };   
...

谢谢你的解释,我仔细研究了一下。
第一个: initialize by copy { readwrite, section .textrw };这句的有一个参数,by copy,意思是 在程序执行后自动执行初始化,也就是对于RW、.textrw这些段,在程序启动后执行初始化。
do not initialize  { section .noinit };   这句的意思是在程序启动后不对.noinit段进行初始化;这段icf文件,链接配置以后,这段使用XIP功能,不会拷贝到SRAM中运行,直接在NorFlash运行,这也是XIP功能的特性。
第二个:这些在XIP里面找到了section .boot_hdr.conf、section .boot_hdr.ivt、readonly section .boot_hdr.boot_data、readonly section .boot_hdr.dcd_data,谢谢提醒。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-11-30 15:50:34 | 显示全部楼层
哈哈哈,我自研究了一下芯片的Flashloader、BootROM、Bootable Image这些东西,大了解一个大概,后面做完实验,会整理一篇博客贴出来,谢谢。
这里我对自己的三个问题做一个解释
第一个和第二个问题:从程序编译出来的.map文件里,关于.intvec段:
"A0":                                                       0x400
  .intvec                 ro code  0x6000'2000   0x400  startup_MIMXRT1052.o [1]
                                       - 0x6000'2400   0x400
应该是独自占据了,0x6000'2000——0x6000'2400一共0x400大小存储,至于IAR软件手册中的.intvec的描述,就不清楚了,难道特指中断向量表的大小?不包括后面汇编定义的复位中断函数等定义吗?
第三个问题:先说一下这里的ivt,是Image vector table的缩写,这几个文件是为了XIP启动自己配置的段,也是Bootable Image的头
具体定义XIP文件中可以找到:
下面是.boot_hdr.conf的段定义,通过#progra location定义的变量数组段,
定义一个section则是通过 :#pragma section = “MYSECTION”
具体定义一个段的介绍,下面这篇文章有介绍:https://blog.csdn.net/huan447882949/article/details/79535653
[mw_shl_code=c,true]#pragma location = ".boot_hdr.conf"
const flexspi_nor_config_t spiflash_config = {
    .memConfig =
        {
            .tag = FLEXSPI_CFG_BLK_TAG,/*标志:FCFB*/
            .version = FLEXSPI_CFG_BLK_VERSION,/*版本:V1.4.0*/
            .readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackInternally,/*内部环回*/
            .csHoldTime = 3u, /*保持时间*/
            .csSetupTime = 3u,/*建立时间*/
            .columnAddressWidth = 0u,/*列地址宽度*/
            .deviceModeCfgEnable = 1u,/*设备模式配置使能*/
            .deviceModeType = 1u,/*Quad 使能命令*/
            .deviceModeSeq.seqNum = 1u,/*LUT序列号*/
            .deviceModeSeq.seqId = 4u, /*LUT序列索引*/   
            .deviceModeArg = 0x000200,/*设置 QE=1(S9)*/
            .deviceType = kFlexSpiDeviceType_SerialNOR,/*设备类型为nor flash*/
            .sflashPadType = kSerialFlash_4Pads,/*设备数据总线为4*/
            .serialClkFreq = kFlexSpiSerialClk_133MHz,/*flash 时钟*/
            .sflashA1Size = 32u * 1024u * 1024u,      /*flash 大小32MBytes*/
            //.dataValidTime = {16u, 16u},
            .lookupTable =
                {
                    /*快速读命令(四线)*/
                    [0]     = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18),
                    [1]     = FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x06, READ_SDR, FLEXSPI_4PAD, 0x04),
                    

                    /*读状态命令*/
                    [1*4]   = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05, READ_SDR, FLEXSPI_1PAD, 0x04),
                    /*写使能命令*/
                    [3*4]   = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06, STOP, FLEXSPI_1PAD, 0),      
                    /*擦除扇区命令*/
                    [5*4]   = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20, RADDR_SDR, FLEXSPI_1PAD, 0x04),
                    /*页编程命令(四线)*/
                    [9*4]   = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x32, RADDR_SDR, FLEXSPI_1PAD, 0x18),  
                    [9*4+1] = FLEXSPI_LUT_SEQ(WRITE_SDR,FLEXSPI_4PAD , 0x04, STOP, FLEXSPI_1PAD, 0),                  
                    /*整片擦除*/
                    [11*4]  = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xc7, STOP, FLEXSPI_1PAD, 0),                  
                },
        },
    .pageSize = 256u,/*页大小为256字节*/
    .sectorSize = 4u * 1024u,/*扇区大小为4k字节*/
};[/mw_shl_code]
其余三个段类似。
至于每个段的作用这里做一个大致介绍,这些是RT1052芯片内部BootLoader(就是集成在片上ROM的那段程序,这里姑且这么称呼)外部串行NorFlash启动所需要的Image头,
分别是FDCB(Flash Device Configuration Block)、IVT(Image Vector Table)、BD(Boot Data)、DCD(Device Configuration Data)。
下面的部分来自痞子衡的博客:
偏移0x0000: FDCB(Flash Device Configuration Block)
第一个组成部分叫FDCB,是个可选组成,目前只用于Serial/Parallel NOR FLASH。FDCB是从FLASH的起始地址处开始存放的,也是Bootable image最开始部分。
FDCB最大4KB,其本身没有统一的与FLASH无关的structure,具体structure根据启动FLASH的接口类型(Serial / Parallel)而定,其一般是用来存储当前连接的FLASH的具体特性参数,BootROM上电会使用通用且可靠的FLASH接口控制器配置(即BootROM中默认参数配置,一般是比较低速的配置)去访问外接FLASH并获取FDCB,然后根据FDCB存储的参数去重新配置FLASH接口控制器,再去进一步访问FLASH。
偏移0x0400/0x1000: IVT(Image Vector Table)
第二个组成部分叫IVT,是个必备组成,也是6类信息数据里的最核心数据,IVT是一个统一的与FLASH无关的structure,其原型如下面结构体所示,从结构体定义我们得知,IVT中记录了应用程序、DCD、BD、CSF的位置信息,这些信息对BootROM加载启动至关重要。IVT大小固定为32byte,其在Bootable image中的偏移位置也是固定的(对于XIP FLASH而言偏移是0x1000,对于Non-XIP FLASH而言偏移是0x400)。
偏移0x0420/0x1020: BD(Boot Data)
第三个组成部分叫BD,是个必备组成,是仅次于IVT的核心数据,BD也是一个统一的与FLASH无关的structure,其原型如下面结构体所示,BD中记录了Bootable image的起始地址与总长度。
BD大小固定为16字节,BD信息虽然记录在了IVT中,但其在Bootable image中的偏移位置并不是任意的,BD是紧挨着IVT的。
DCD(Device Configuration Data)
第四个组成部分叫DCD,是个可选组成,目前主要用于SDRAM接口控制器(SEMC)的配置。由于i.MX RT内部SRAM的大小通常是够用的,且访问速度也很快,所以SDRAM并不一定要被使能,Bootable image常常不会包含DCD,所以痞子衡在这里先不做展开,后续有必要会再介绍。下面是SDK_2.3.1_EVKB-IMXRT1050包里hello_world工程(flexspi_nor)所使用DCD示例:

接着下面一部分就是我们的应用程序了,
偏移0x2000: Application Binary
第五个组成部分是你最熟悉的应用程序代码,当然是个必备组成,其在Bootable image中的偏移位置是固定的(0x2000),关于应用本身这里就不再赘述了。只特别提一点,那就是i.MX RT的应用程序只读段(主要指ARM中断向量表),并不可以从任意地址开始链接,有一个小小的限制,必须从选定的存储器地址空间偏移0x2000之后开始链接(如选中ITCM,则必须要链接在0x00002000之后;如选中DTCM,则必须链接在0x20002000之后...),因为要预留至少8KB空间给IVT、BD、DCD等数据,这个限制是BootROM自身决定的,务必要注意。

当然这里还有两个和安全启动相关的CSF、KeyBlob粘贴了。感谢一下痞子衡,写这么好的文章。
回复 支持 反对

使用道具 举报

发表于 2018-11-30 15:54:52 | 显示全部楼层
本帖最后由 xiaobakang 于 2018-11-30 16:24 编辑
Bastian 发表于 2018-11-30 15:15
谢谢你的解释,我仔细研究了一下。
第一个: initialize by copy { readwrite, section .textrw };这句 ...

恩恩,这个icf是XIP功能配置文件。
回复 支持 反对

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-5-1 04:49 , Processed in 0.046887 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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