概述
部分知识点概念上难以理解,本章节基于此部分根据Hightec内部的文档《tricore-ld》进行自己的认知分析一下。
分析条目
VMA与LMA
每一个装载或者允许装载的输出段都有两个地址,一个是VMA virture memory address 虚拟存储器地址,当程序正在执行的时候运行的是此地址,另一个是LMA load memory address 加载存储器地址,这是加载段的地址。
大部分情况下这两个地址是一样的,举个不一样的例子,当数据段在ROM,程序开始启动的时候Copy进RAM。这种情况下ROM是LMA,RAM地址是VMA。
.text | 代码段 |
.rodata | 只读数据 |
.data | 可读写初始化数据存放位置 |
.bss | 可读写未初始化数据存放位置 |
PROVIDE
目前阶段个人的理解,标识一个地址的位置,可以是开始,或者结束,这个标识符假设在程序里面出现会占用字节,假设程序里面没有定义就不占用字节。有一个例外情况要是声明的是一个数组,那么也是不占用字节的。
extern uint32 TargetAddress;
extern uint32 TargetAddress[];
实用方法例如:
PROVIDE(__USER_CODE_START = .)
ABSOLUTE
absolute 相对于其父元素的位置放置一个元素并改变它周围的布局
简单的例子
AAAAA = .
BBBBB = ABSOLUTE(.)
假设AAAAA 的地址为0x100 而且A不占用字节,那么BBBBB也为0x100的地址
LOADADDR
返回相对的虚拟地址段和指令ADDR类似,有AT指令进行指向的时候又是不一样的。
例如:
CCCCC = LOADADDR (.FLSLOADERRAMCODE),展现的是个ROM地址。
AT
AT是在上电启动的时候把ROM内容Copy到RAM,个人理解分析一下内容
section :ALIGN(4)
{
.....
} > RAM_ADDRESS > AT > ROM_ADDRESS
RAM_ADDRESS > AT > ROM_ADDRESS 两层含义
第一步:在链接阶段代码或者数据放置到ROM_ADDRESS
第二部:RAM_ADDRESS与ROM_ADDRESS通过AT关联起来,在第一步里面已经执行的放置ROM操作,在单片机上电开始阶段,执行ROM_ADDRESS 复制进RAM操作,这样子理解为什么RAM_ADDRESS能精准的找到ROM_ADDRESS
注意点1
有时候针对不同的供应商,最底层的Memmap.h可能最终包含的不同,这个时候我们可以定义多个段来进行兼容。
举例:
CPU2_TRUSTED_DATA :ALIGN(4)
{
*(.data.cpu2_Trusted_16*);
*(.data.cpu2_16*);
}> CPU2_TRUSTED AT >PFLASH_CPU2_PRIVIDE
在上述里面 *(.data.cpu2_Trusted_16*);与 *(.data.cpu2_16*);其实可以表达相同的含义,但是假设针对ETAS与MCAL不同的供应商可能表达的不一样,故设置了两个。
x > AT > Y = 0
举例:
FLS_AC_ERASE :ALIGN(4)
{
*(.FLS_AC_ERASE);
. = ALIGN(4);
} > CPU0_PSPR_FLS_ERASE AT > PFLASH0_FLS_ERASE = 0
里面的= 0;含义是填充0,也可以是0xFF,但是0xFF有时候代表有用途,这样就比较麻烦,所以一般就是等于0比较合适。
*16*含义
可以是xxx16xxx这样子的组合。
RODATA :ALIGN(4)
{
*(.rodata.*16*);
. = ALIGN(4);
}> PFLASH0_CONST
例如电机里面的标定数据 就存放在 *(.rodata*) 默认的const数据是存放在*(.rodata*)里面的,注意一个地方 *(.rodata*)包含 *(.rodata.*)。
KEEP
.inttab :
{
KEEP(*(.inttab));
*(*.ostrap);
}> PFLASH0_TRAP_INT_TAB
.o在链接时使用,一旦链接完就会丢弃,但是使用了KEEP,链接的整个过程均可以使用,也有一种说法是防止优化编译。