一、简介
最近学习NXP新推出的S32K3系列芯片,我在学习容易转牛角尖,非得要搞明白这个芯片的启动流程,所以花费了一些时间,进行查阅资料进行学习,这里做下详细的记录,希望有用,如果有错误欢迎指正!
Linker链接器脚本作用是编译时用来分配内存,把变量和程序代码链接到脚本所定义的内存地址上。把编译器离散的编译好的程序代码链接到一起!生成MAP文件!
二、背景
一直有个疑问每次编译后总是会出来下面这个图片信息中的text,data,bass,dec
1.text 是程序代码存放在ROM中
2.data 是声明带初始化变量数据放在RAM中,初始化数据放在ROM中,上电初始化后拷贝到RAM中 例如:全局变量uint8_t i = 30; i的的地址在RAM中,数据30在ROM中!如果加上const修饰符,他们都放在ROM中。
3. bass 是声明未初始化变量数据放在RAM中,例如:全局变量uint8_t UpgradeFlag;如果加上const修饰符,他们都放在ROM中。
4. dec 是前面三个数量的总和。
有了上面这些划分,编译器在编译好代码是,linker链接器脚本会把这些代码段从新分配到各个代码分区的内存中,所以在定义变量时,如果是RAM很小的情况下,一定都要尽量放到ROM中。
Linker链接器脚本解析
我们一句一句的解析这些脚本,学习以后可以融会贯通!
S32K3系列内存资源
/*
* GCC Linker Command File:
* 0x00400000 0x001F3FFF 2047999 Program Flash (last 64K sBAF)
* 0x10000000 0x1003FFFF 262144 Data Flash (last 32K HSE_NVM)
* 0x20400000 0x20408000 32768 Standby RAM_0 (32K)
* 0x20400000 0x20417FFF 98304 SRAM_0 (96KB)
* Last 48 KB of SRAM_1 reserved by HSE Firmware
* Last 176 KB of CODE_FLASH_3 reserved by HSE Firmware
* Last 128 KB of DATA_FLASH reserved by HSE Firmware (not supported in this linker file)
*/
HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x00002000;
这里设置堆的长度为0x2000
ENTRY(Reset_Handler)
ENTRY这里是程序的入口Reset_Handler,程序就是从这里开始的。也就是程序执行的第一条指令从这里开始!
MEMORY
{
/*int_flash : ORIGIN = 0x00400000, LENGTH = 0x001D4000 /* 2048K - 176K (sBAF + HSE)*/
int_flash : ORIGIN = 0x00400000, LENGTH = 0x00040000 /* 256K */
int_itcm : ORIGIN = 0x00000000, LENGTH = 0x00008000 /* 32K */
int_dtcm : ORIGIN = 0x20000000, LENGTH = 0x00010000 /* 64K */
int_sram : ORIGIN = 0x20400000, LENGTH = 0x00006F00 /* 27 KB */
int_sram_fls_rsv : ORIGIN = 0x20406F00, LENGTH = 0x00000100
int_sram_stack_c0 : ORIGIN = 0x20407000, LENGTH = 0x00001000
int_sram_no_cacheable : ORIGIN = 0x20408000, LENGTH = 0x00007F00 /* 32kb , needs to include int_results */
int_sram_results : ORIGIN = 0x2040FF00, LENGTH = 0x00000100
int_sram_shareable : ORIGIN = 0x20410000, LENGTH = 0x00008000 /* 32KB */
ram_rsvd2 : ORIGIN = 0x20418000, LENGTH = 0 /* End of SRAM */
}
这里是划分内存块,可以将别名添加到使用 MEMORY命令创建的现有内存区域。该命令描述目标中内存块的位置和大小。您可以使用它来描述链接器可以使用哪些内存区域,以及它必须避免使用哪些内存区域。然后可以将节分配到特定的内存区域。链接器将根据内存区域设置节地址,并在区域变得太满时发出警告。链接器不会打乱部分以适应可用的区域。
ORIGIN 该块起始地址。LENGTH表示该块的长度byte为单位!
这里是根据数据手册真实芯片分配内存分配的,你也可以手动划分,需要注意的是字节对齐,这里FLASH默认起始地址是0X00400000,RAM默认起始地址是0X20000000,如果加入Bootloader的话,需要把应用程APP的flash代码地址和Bootloader的flash代码地址错开分配!这里默认放置,需要的话可以参考BOOT章节!
SECTIONS该命令告知链接器如何映射输入部分 到输出部分,以及如何将输出部分放在内存中。
命令的格式为:SECTIONS
<span style="color:#000000">SECTIONS
{
sections-command
sections-command
…
}</span>
保持当前结构不变,下面是结构分配长度和定义!
.表示输出(locale)当前位置,ALIGN(X),就是X字节对齐
可以看到flash.是从0x00400000地址开始,0x1000字节对齐后,把0x1000给text_start 和_interrupts_rom_start。
中断向量表,4字节对齐!
长度是0x408 (一共258个中断列表)