RT1176-2(链接脚本)
从链接脚本开始.
以hello_world工程为例:构建完工程打开Debug目录下的evkmimxrt1170_hello_world_demo_cm7_Debug.ld 。
INCLUDE "evkmimxrt1170_hello_world_demo_cm7_Debug_library.ld"
INCLUDE "evkmimxrt1170_hello_world_demo_cm7_Debug_memory.ld"
ENTRY(ResetISR)
........
这里分段学习,第一段如上:第一行和第二行的INCLUDE语句如C语言一样,包含了两个其他的脚本。在Debug目录下可找到。
1、打开evkmimxrt1170_hello_world_demo_cm7_Debug_library.ld的内容如下:
GROUP ("libcr_nohost_nf.a""libcr_c.a""libcr_eabihelpers.a""libgcc.a"
)
根据文件名和文件内容可分析猜测得:这里是链接包好一些库文件,C库等。
2、打开evkmimxrt1170_hello_world_demo_cm7_Debug_memory.ld的内容如下:
MEMORY
{/* Define each memory region */BOARD_FLASH (rx) : ORIGIN = 0x30000000, LENGTH = 0x1000000 /* 16M bytes (alias Flash) */ BOARD_SDRAM (rwx) : ORIGIN = 0x80000000, LENGTH = 0x3000000 /* 48M bytes (alias RAM) */ NCACHE_REGION (rwx) : ORIGIN = 0x83000000, LENGTH = 0x1000000 /* 16M bytes (alias RAM2) */ SRAM_DTC_cm7 (rwx) : ORIGIN = 0x20000000, LENGTH = 0x40000 /* 256K bytes (alias RAM3) */ SRAM_ITC_cm7 (rwx) : ORIGIN = 0x0, LENGTH = 0x40000 /* 256K bytes (alias RAM4) */ SRAM_OC1 (rwx) : ORIGIN = 0x20240000, LENGTH = 0x80000 /* 512K bytes (alias RAM5) */ SRAM_OC2 (rwx) : ORIGIN = 0x202c0000, LENGTH = 0x80000 /* 512K bytes (alias RAM6) */ SRAM_OC_ECC1 (rwx) : ORIGIN = 0x20340000, LENGTH = 0x10000 /* 64K bytes (alias RAM7) */ SRAM_OC_ECC2 (rwx) : ORIGIN = 0x20350000, LENGTH = 0x10000 /* 64K bytes (alias RAM8) */
}/* Define a symbol for the top of each memory region */__base_BOARD_FLASH = 0x30000000 ; /* BOARD_FLASH */ __base_Flash = 0x30000000 ; /* Flash */ __top_BOARD_FLASH = 0x30000000 + 0x1000000 ; /* 16M bytes */ __top_Flash = 0x30000000 + 0x1000000 ; /* 16M bytes */ __base_BOARD_SDRAM = 0x80000000 ; /* BOARD_SDRAM */ __base_RAM = 0x80000000 ; /* RAM */ __top_BOARD_SDRAM = 0x80000000 + 0x3000000 ; /* 48M bytes */ __top_RAM = 0x80000000 + 0x3000000 ; /* 48M bytes */ __base_NCACHE_REGION = 0x83000000 ; /* NCACHE_REGION */ __base_RAM2 = 0x83000000 ; /* RAM2 */ __top_NCACHE_REGION = 0x83000000 + 0x1000000 ; /* 16M bytes */ __top_RAM2 = 0x83000000 + 0x1000000 ; /* 16M bytes */ __base_SRAM_DTC_cm7 = 0x20000000 ; /* SRAM_DTC_cm7 */ __base_RAM3 = 0x20000000 ; /* RAM3 */ __top_SRAM_DTC_cm7 = 0x20000000 + 0x40000 ; /* 256K bytes */ __top_RAM3 = 0x20000000 + 0x40000 ; /* 256K bytes */ __base_SRAM_ITC_cm7 = 0x0 ; /* SRAM_ITC_cm7 */ __base_RAM4 = 0x0 ; /* RAM4 */ __top_SRAM_ITC_cm7 = 0x0 + 0x40000 ; /* 256K bytes */ __top_RAM4 = 0x0 + 0x40000 ; /* 256K bytes */ __base_SRAM_OC1 = 0x20240000 ; /* SRAM_OC1 */ __base_RAM5 = 0x20240000 ; /* RAM5 */ __top_SRAM_OC1 = 0x20240000 + 0x80000 ; /* 512K bytes */ __top_RAM5 = 0x20240000 + 0x80000 ; /* 512K bytes */ __base_SRAM_OC2 = 0x202c0000 ; /* SRAM_OC2 */ __base_RAM6 = 0x202c0000 ; /* RAM6 */ __top_SRAM_OC2 = 0x202c0000 + 0x80000 ; /* 512K bytes */ __top_RAM6 = 0x202c0000 + 0x80000 ; /* 512K bytes */ __base_SRAM_OC_ECC1 = 0x20340000 ; /* SRAM_OC_ECC1 */ __base_RAM7 = 0x20340000 ; /* RAM7 */ __top_SRAM_OC_ECC1 = 0x20340000 + 0x10000 ; /* 64K bytes */ __top_RAM7 = 0x20340000 + 0x10000 ; /* 64K bytes */ __base_SRAM_OC_ECC2 = 0x20350000 ; /* SRAM_OC_ECC2 */ __base_RAM8 = 0x20350000 ; /* RAM8 */ __top_SRAM_OC_ECC2 = 0x20350000 + 0x10000 ; /* 64K bytes */ __top_RAM8 = 0x20350000 + 0x10000 ; /* 64K bytes */
根据文件名和文件内容可分析猜测得:该文件是一个RT1176的内存定义文件和各段内存的别名。
3、ENTRY(ResetISR)
熟悉gnu link script语法的就知道了这句话的意思是程序的入口地址是 ResetISR。即芯片上电后BootRom做完初始化工作后的跳转地址。这里我们暂时记住就行,稍后分析完链接脚本就从这个地址开始分析代码。
4、链接脚本的SECTIONS
SECTIONS
{/* MAIN TEXT SECTION */.text : ALIGN(4){FILL(0xff)__vectors_start__ = ABSOLUTE(.) ;KEEP(*(.isr_vector))/* Global Section Table */. = ALIGN(4) ;__section_table_start = .;__data_section_table = .;LONG(LOADADDR(.data));LONG( ADDR(.data));LONG( SIZEOF(.data));LONG(LOADADDR(.data_RAM2));LONG( ADDR(.data_RAM2));LONG( SIZEOF(.data_RAM2));LONG(LOADADDR(.data_RAM3));LONG( ADDR(.data_RAM3));LONG( SIZEOF(.data_RAM3));LONG(LOADADDR(.data_RAM4));LONG( ADDR(.data_RAM4));LONG( SIZEOF(.data_RAM4));LONG(LOADADDR(.data_RAM5));LONG( ADDR(.data_RAM5));LONG( SIZEOF(.data_RAM5));LONG(LOADADDR(.data_RAM6));LONG( ADDR(.data_RAM6));LONG( SIZEOF(.data_RAM6));LONG(LOADADDR(.data_RAM7));LONG( ADDR(.data_RAM7));LONG( SIZEOF(.data_RAM7));LONG(LOADADDR(.data_RAM8));LONG( ADDR(.data_RAM8));LONG( SIZEOF(.data_RAM8));__data_section_table_end = .;__bss_section_table = .;LONG( ADDR(.bss));LONG( SIZEOF(.bss));LONG( ADDR(.bss_RAM2));LONG( SIZEOF(.bss_RAM2));LONG( ADDR(.bss_RAM3));LONG( SIZEOF(.bss_RAM3));LONG( ADDR(.bss_RAM4));LONG( SIZEOF(.bss_RAM4));LONG( ADDR(.bss_RAM5));LONG( SIZEOF(.bss_RAM5));LONG( ADDR(.bss_RAM6));LONG( SIZEOF(.bss_RAM6));LONG( ADDR(.bss_RAM7));LONG( SIZEOF(.bss_RAM7));LONG( ADDR(.bss_RAM8));LONG( SIZEOF(.bss_RAM8));__bss_section_table_end = .;__section_table_end = . ;/* End of Global Section Table */*(.after_vectors*)*(.text*)*(.rodata .rodata.* .constdata .constdata.*). = ALIGN(4);} > BOARD_SDRAM/** for exception handling/unwind - some Newlib functions (in common* with C++ and STDC++) use this.*/.ARM.extab : ALIGN(4){*(.ARM.extab* .gnu.linkonce.armextab.*)} > BOARD_SDRAM.ARM.exidx : ALIGN(4){__exidx_start = .;*(.ARM.exidx* .gnu.linkonce.armexidx.*)__exidx_end = .;} > BOARD_SDRAM_etext = .;/* DATA section for NCACHE_REGION */.data_RAM2 : ALIGN(4){FILL(0xff)PROVIDE(__start_data_RAM2 = .) ;PROVIDE(__start_data_NCACHE_REGION = .) ;*(.ramfunc.$RAM2)*(.ramfunc.$NCACHE_REGION)*(NonCacheable.init)*(.data.$RAM2)*(.data.$NCACHE_REGION)*(.data.$RAM2.*)*(.data.$NCACHE_REGION.*). = ALIGN(4) ;PROVIDE(__end_data_RAM2 = .) ;PROVIDE(__end_data_NCACHE_REGION = .) ;} > NCACHE_REGION AT>BOARD_SDRAM/* DATA section for SRAM_DTC_cm7 */.data_RAM3 : ALIGN(4){FILL(0xff)PROVIDE(__start_data_RAM3 = .) ;PROVIDE(__start_data_SRAM_DTC_cm7 = .) ;*(.ramfunc.$RAM3)*(.ramfunc.$SRAM_DTC_cm7)*(.data.$RAM3)*(.data.$SRAM_DTC_cm7)*(.data.$RAM3.*)*(.data.$SRAM_DTC_cm7.*). = ALIGN(4) ;PROVIDE(__end_data_RAM3 = .) ;PROVIDE(__end_data_SRAM_DTC_cm7 = .) ;} > SRAM_DTC_cm7 AT>BOARD_SDRAM/* DATA section for SRAM_ITC_cm7 */.data_RAM4 : ALIGN(4){FILL(0xff)PROVIDE(__start_data_RAM4 = .) ;PROVIDE(__start_data_SRAM_ITC_cm7 = .) ;*(.ramfunc.$RAM4)*(.ramfunc.$SRAM_ITC_cm7)KEEP(*(CodeQuickAccess))*(.data.$RAM4)*(.data.$SRAM_ITC_cm7)*(.data.$RAM4.*)*(.data.$SRAM_ITC_cm7.*). = ALIGN(4) ;PROVIDE(__end_data_RAM4 = .) ;PROVIDE(__end_data_SRAM_ITC_cm7 = .) ;} > SRAM_ITC_cm7 AT>BOARD_SDRAM/* DATA section for SRAM_OC1 */.data_RAM5 : ALIGN(4){FILL(0xff)PROVIDE(__start_data_RAM5 = .) ;PROVIDE(__start_data_SRAM_OC1 = .) ;*(.ramfunc.$RAM5)*(.ramfunc.$SRAM_OC1)*(.data.$RAM5)*(.data.$SRAM_OC1)*(.data.$RAM5.*)*(.data.$SRAM_OC1.*). = ALIGN(4) ;PROVIDE(__end_data_RAM5 = .) ;PROVIDE(__end_data_SRAM_OC1 = .) ;} > SRAM_OC1 AT>BOARD_SDRAM/* DATA section for SRAM_OC2 */.data_RAM6 : ALIGN(4){FILL(0xff)PROVIDE(__start_data_RAM6 = .) ;PROVIDE(__start_data_SRAM_OC2 = .) ;*(.ramfunc.$RAM6)*(.ramfunc.$SRAM_OC2)*(.data.$RAM6)*(.data.$SRAM_OC2)*(.data.$RAM6.*)*(.data.$SRAM_OC2.*). = ALIGN(4) ;PROVIDE(__end_data_RAM6 = .) ;PROVIDE(__end_data_SRAM_OC2 = .) ;} > SRAM_OC2 AT>BOARD_SDRAM/* DATA section for SRAM_OC_ECC1 */.data_RAM7 : ALIGN(4){FILL(0xff)PROVIDE(__start_data_RAM7 = .) ;PROVIDE(__start_data_SRAM_OC_ECC1 = .) ;*(.ramfunc.$RAM7)*(.ramfunc.$SRAM_OC_ECC1)*(.data.$RAM7)*(.data.$SRAM_OC_ECC1)*(.data.$RAM7.*)*(.data.$SRAM_OC_ECC1.*). = ALIGN(4) ;PROVIDE(__end_data_RAM7 = .) ;PROVIDE(__end_data_SRAM_OC_ECC1 = .) ;} > SRAM_OC_ECC1 AT>BOARD_SDRAM/* DATA section for SRAM_OC_ECC2 */.data_RAM8 : ALIGN(4){FILL(0xff)PROVIDE(__start_data_RAM8 = .) ;PROVIDE(__start_data_SRAM_OC_ECC2 = .) ;*(.ramfunc.$RAM8)*(.ramfunc.$SRAM_OC_ECC2)*(.data.$RAM8)*(.data.$SRAM_OC_ECC2)*(.data.$RAM8.*)*(.data.$SRAM_OC_ECC2.*). = ALIGN(4) ;PROVIDE(__end_data_RAM8 = .) ;PROVIDE(__end_data_SRAM_OC_ECC2 = .) ;} > SRAM_OC_ECC2 AT>BOARD_SDRAM/* MAIN DATA SECTION */.uninit_RESERVED (NOLOAD) : ALIGN(4){_start_uninit_RESERVED = .;KEEP(*(.bss.$RESERVED*)). = ALIGN(4) ;_end_uninit_RESERVED = .;} > BOARD_SDRAM AT> BOARD_SDRAM/* Main DATA section (BOARD_SDRAM) */.data : ALIGN(4){FILL(0xff)_data = . ;PROVIDE(__start_data_RAM = .) ;PROVIDE(__start_data_BOARD_SDRAM = .) ;*(vtable)*(.ramfunc*)KEEP(*(CodeQuickAccess))KEEP(*(DataQuickAccess))*(RamFunction)*(.data*). = ALIGN(4) ;_edata = . ;PROVIDE(__end_data_RAM = .) ;PROVIDE(__end_data_BOARD_SDRAM = .) ;} > BOARD_SDRAM AT>BOARD_SDRAM/* BSS section for NCACHE_REGION */.bss_RAM2 : ALIGN(4){PROVIDE(__start_bss_RAM2 = .) ;PROVIDE(__start_bss_NCACHE_REGION = .) ;*(NonCacheable)*(.bss.$RAM2)*(.bss.$NCACHE_REGION)*(.bss.$RAM2.*)*(.bss.$NCACHE_REGION.*). = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */PROVIDE(__end_bss_RAM2 = .) ;PROVIDE(__end_bss_NCACHE_REGION = .) ;} > NCACHE_REGION AT> NCACHE_REGION/* BSS section for SRAM_DTC_cm7 */.bss_RAM3 : ALIGN(4){PROVIDE(__start_bss_RAM3 = .) ;PROVIDE(__start_bss_SRAM_DTC_cm7 = .) ;*(.bss.$RAM3)*(.bss.$SRAM_DTC_cm7)*(.bss.$RAM3.*)*(.bss.$SRAM_DTC_cm7.*). = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */PROVIDE(__end_bss_RAM3 = .) ;PROVIDE(__end_bss_SRAM_DTC_cm7 = .) ;} > SRAM_DTC_cm7 AT> SRAM_DTC_cm7/* BSS section for SRAM_ITC_cm7 */.bss_RAM4 : ALIGN(4){PROVIDE(__start_bss_RAM4 = .) ;PROVIDE(__start_bss_SRAM_ITC_cm7 = .) ;*(.bss.$RAM4)*(.bss.$SRAM_ITC_cm7)*(.bss.$RAM4.*)*(.bss.$SRAM_ITC_cm7.*). = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */PROVIDE(__end_bss_RAM4 = .) ;PROVIDE(__end_bss_SRAM_ITC_cm7 = .) ;} > SRAM_ITC_cm7 AT> SRAM_ITC_cm7/* BSS section for SRAM_OC1 */.bss_RAM5 : ALIGN(4){PROVIDE(__start_bss_RAM5 = .) ;PROVIDE(__start_bss_SRAM_OC1 = .) ;*(.bss.$RAM5)*(.bss.$SRAM_OC1)*(.bss.$RAM5.*)*(.bss.$SRAM_OC1.*). = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */PROVIDE(__end_bss_RAM5 = .) ;PROVIDE(__end_bss_SRAM_OC1 = .) ;} > SRAM_OC1 AT> SRAM_OC1/* BSS section for SRAM_OC2 */.bss_RAM6 : ALIGN(4){PROVIDE(__start_bss_RAM6 = .) ;PROVIDE(__start_bss_SRAM_OC2 = .) ;*(.bss.$RAM6)*(.bss.$SRAM_OC2)*(.bss.$RAM6.*)*(.bss.$SRAM_OC2.*). = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */PROVIDE(__end_bss_RAM6 = .) ;PROVIDE(__end_bss_SRAM_OC2 = .) ;} > SRAM_OC2 AT> SRAM_OC2/* BSS section for SRAM_OC_ECC1 */.bss_RAM7 : ALIGN(4){PROVIDE(__start_bss_RAM7 = .) ;PROVIDE(__start_bss_SRAM_OC_ECC1 = .) ;*(.bss.$RAM7)*(.bss.$SRAM_OC_ECC1)*(.bss.$RAM7.*)*(.bss.$SRAM_OC_ECC1.*). = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */PROVIDE(__end_bss_RAM7 = .) ;PROVIDE(__end_bss_SRAM_OC_ECC1 = .) ;} > SRAM_OC_ECC1 AT> SRAM_OC_ECC1/* BSS section for SRAM_OC_ECC2 */.bss_RAM8 : ALIGN(4){PROVIDE(__start_bss_RAM8 = .) ;PROVIDE(__start_bss_SRAM_OC_ECC2 = .) ;*(.bss.$RAM8)*(.bss.$SRAM_OC_ECC2)*(.bss.$RAM8.*)*(.bss.$SRAM_OC_ECC2.*). = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */PROVIDE(__end_bss_RAM8 = .) ;PROVIDE(__end_bss_SRAM_OC_ECC2 = .) ;} > SRAM_OC_ECC2 AT> SRAM_OC_ECC2/* MAIN BSS SECTION */.bss : ALIGN(4){_bss = .;PROVIDE(__start_bss_RAM = .) ;PROVIDE(__start_bss_BOARD_SDRAM = .) ;*(.bss*)*(COMMON). = ALIGN(4) ;_ebss = .;PROVIDE(__end_bss_RAM = .) ;PROVIDE(__end_bss_BOARD_SDRAM = .) ;PROVIDE(end = .);} > BOARD_SDRAM AT> BOARD_SDRAM/* NOINIT section for NCACHE_REGION */.noinit_RAM2 (NOLOAD) : ALIGN(4){PROVIDE(__start_noinit_RAM2 = .) ;PROVIDE(__start_noinit_NCACHE_REGION = .) ;*(.noinit.$RAM2)*(.noinit.$NCACHE_REGION)*(.noinit.$RAM2.*)*(.noinit.$NCACHE_REGION.*). = ALIGN(4) ;PROVIDE(__end_noinit_RAM2 = .) ;PROVIDE(__end_noinit_NCACHE_REGION = .) ;} > NCACHE_REGION AT> NCACHE_REGION/* NOINIT section for SRAM_DTC_cm7 */.noinit_RAM3 (NOLOAD) : ALIGN(4){PROVIDE(__start_noinit_RAM3 = .) ;PROVIDE(__start_noinit_SRAM_DTC_cm7 = .) ;*(.noinit.$RAM3)*(.noinit.$SRAM_DTC_cm7)*(.noinit.$RAM3.*)*(.noinit.$SRAM_DTC_cm7.*). = ALIGN(4) ;PROVIDE(__end_noinit_RAM3 = .) ;PROVIDE(__end_noinit_SRAM_DTC_cm7 = .) ;} > SRAM_DTC_cm7 AT> SRAM_DTC_cm7/* NOINIT section for SRAM_ITC_cm7 */.noinit_RAM4 (NOLOAD) : ALIGN(4){PROVIDE(__start_noinit_RAM4 = .) ;PROVIDE(__start_noinit_SRAM_ITC_cm7 = .) ;*(.noinit.$RAM4)*(.noinit.$SRAM_ITC_cm7)*(.noinit.$RAM4.*)*(.noinit.$SRAM_ITC_cm7.*). = ALIGN(4) ;PROVIDE(__end_noinit_RAM4 = .) ;PROVIDE(__end_noinit_SRAM_ITC_cm7 = .) ;} > SRAM_ITC_cm7 AT> SRAM_ITC_cm7/* NOINIT section for SRAM_OC1 */.noinit_RAM5 (NOLOAD) : ALIGN(4){PROVIDE(__start_noinit_RAM5 = .) ;PROVIDE(__start_noinit_SRAM_OC1 = .) ;*(.noinit.$RAM5)*(.noinit.$SRAM_OC1)*(.noinit.$RAM5.*)*(.noinit.$SRAM_OC1.*). = ALIGN(4) ;PROVIDE(__end_noinit_RAM5 = .) ;PROVIDE(__end_noinit_SRAM_OC1 = .) ;} > SRAM_OC1 AT> SRAM_OC1/* NOINIT section for SRAM_OC2 */.noinit_RAM6 (NOLOAD) : ALIGN(4){PROVIDE(__start_noinit_RAM6 = .) ;PROVIDE(__start_noinit_SRAM_OC2 = .) ;*(.noinit.$RAM6)*(.noinit.$SRAM_OC2)*(.noinit.$RAM6.*)*(.noinit.$SRAM_OC2.*). = ALIGN(4) ;PROVIDE(__end_noinit_RAM6 = .) ;PROVIDE(__end_noinit_SRAM_OC2 = .) ;} > SRAM_OC2 AT> SRAM_OC2/* NOINIT section for SRAM_OC_ECC1 */.noinit_RAM7 (NOLOAD) : ALIGN(4){PROVIDE(__start_noinit_RAM7 = .) ;PROVIDE(__start_noinit_SRAM_OC_ECC1 = .) ;*(.noinit.$RAM7)*(.noinit.$SRAM_OC_ECC1)*(.noinit.$RAM7.*)*(.noinit.$SRAM_OC_ECC1.*). = ALIGN(4) ;PROVIDE(__end_noinit_RAM7 = .) ;PROVIDE(__end_noinit_SRAM_OC_ECC1 = .) ;} > SRAM_OC_ECC1 AT> SRAM_OC_ECC1/* NOINIT section for SRAM_OC_ECC2 */.noinit_RAM8 (NOLOAD) : ALIGN(4){PROVIDE(__start_noinit_RAM8 = .) ;PROVIDE(__start_noinit_SRAM_OC_ECC2 = .) ;*(.noinit.$RAM8)*(.noinit.$SRAM_OC_ECC2)*(.noinit.$RAM8.*)*(.noinit.$SRAM_OC_ECC2.*). = ALIGN(4) ;PROVIDE(__end_noinit_RAM8 = .) ;PROVIDE(__end_noinit_SRAM_OC_ECC2 = .) ;} > SRAM_OC_ECC2 AT> SRAM_OC_ECC2/* DEFAULT NOINIT SECTION */.noinit (NOLOAD): ALIGN(4){_noinit = .;PROVIDE(__start_noinit_RAM = .) ;PROVIDE(__start_noinit_BOARD_SDRAM = .) ;*(.noinit*). = ALIGN(4) ;_end_noinit = .;PROVIDE(__end_noinit_RAM = .) ;PROVIDE(__end_noinit_BOARD_SDRAM = .) ; } > BOARD_SDRAM AT> BOARD_SDRAM/* Reserve and place Heap within memory map */_HeapSize = 0x1000;.heap : ALIGN(4){_pvHeapStart = .;. += _HeapSize;. = ALIGN(4);_pvHeapLimit = .;} > BOARD_SDRAM_StackSize = 0x1000;/* Reserve space in memory for Stack */.heap2stackfill :{. += _StackSize;} > BOARD_SDRAM/* Locate actual Stack in memory map */.stack ORIGIN(BOARD_SDRAM) + LENGTH(BOARD_SDRAM) - _StackSize - 0: ALIGN(4){_vStackBase = .;. = ALIGN(4);_vStackTop = . + _StackSize;} > BOARD_SDRAM/* Provide basic symbols giving location and size of main text* block, including initial values of RW data sections. Note that* these will need extending to give a complete picture with* complex images (e.g multiple Flash banks).*/_image_start = LOADADDR(.text);_image_end = LOADADDR(.data) + SIZEOF(.data);_image_size = _image_end - _image_start;/* Provide symbols for MIMXRT1170 parts for boot header generation code* to set image to be plain load image or XIP.* Config : Plain load image = false*/_boot_loadaddr = ORIGIN(BOARD_SDRAM);_boot_size = LENGTH(BOARD_SDRAM);
}
这一段内容较多,不过很多都是相似的内容,熟悉C程序的内存分布结构的就看着比较容易了。这里我们做分段学习:
(1)、SECTIONS – 1
.text : ALIGN(4){FILL(0xff)__vectors_start__ = ABSOLUTE(.) ;KEEP(*(.isr_vector))/* Global Section Table */. = ALIGN(4) ;__section_table_start = .;__data_section_table = .;LONG(LOADADDR(.data));LONG( ADDR(.data));LONG( SIZEOF(.data));LONG(LOADADDR(.data_RAM2));LONG( ADDR(.data_RAM2));LONG( SIZEOF(.data_RAM2));......LONG(LOADADDR(.data_RAM8));LONG( ADDR(.data_RAM8));LONG( SIZEOF(.data_RAM8));__data_section_table_end = .;__bss_section_table = .;LONG( ADDR(.bss));LONG( SIZEOF(.bss));LONG( ADDR(.bss_RAM2));LONG( SIZEOF(.bss_RAM2));......LONG( ADDR(.bss_RAM8));LONG( SIZEOF(.bss_RAM8));__bss_section_table_end = .;__section_table_end = . ;/* End of Global Section Table */*(.after_vectors*)*(.text*)*(.rodata .rodata.* .constdata .constdata.*). = ALIGN(4);} > BOARD_SDRAM
这一段是我们生成的bin文件的内容布局:C语言中的 text 段,代码段。
ALIGN(4)
: 四字节对齐。(为什么是四字节对齐,个人猜测跟CPU字长相关。)
FILL(0xff)
:填充,即没有用到的空间填充0xff。(在上面脚本中暂时不做用。)
__vectors_start__ = ABSOLUTE(.) ;
:定义地址 vectors_start 类似C语言的指针。(根据上面脚本分析,即bin文件的开头即使__vectors_start__
)
KEEP(*(.isr_vector))
: 把.isr_vector段放在这里。(KEEP的意思告诉编译器不要做垃圾回收)
__section_table_start = .;
__data_section_table = .; :定义两个"指针",指向同一个地方,段表的开始,数据段的开始。
LONG(LOADADDR(.data));
:定义一个变量,.data的load地址,即从哪里取。
LONG( ADDR(.data));
:定义一个变量,.data的目标地址,即放到哪里。
LONG( SIZEOF(.data));
:定义一个变量,.data的大小。
后面都是3个一组类似的。(针对不同的内存段的data段)
__data_section_table_end = .; __bss_section_table = .;
: 定义两个"指针",指向同一个地方,数据段的结束,bss段的开始。
后面都是2个一组类似的。(针对不同的内存段的bss段)
__bss_section_table_end = .; __section_table_end = . ;
: 定义两个"指针",指向同一个地方,bss段的结束,段表的结束。
这一段的含义是做分散加载的,应为RT1176的不同内存地址的速度是不一样的,DTCM和ITCM速度最快跟CPU一致,所以如果有需要可以把相应的代码放到这段内存运行,OCRAM 速度比TCM慢,CPU执行这里的代码需要等待, SDRAM的速度比OCRAM慢。
*(.after_vectors*)
:把.after_vectors放置到这里。
*(.text*)
:把.text放置到这里。
(*.rodata .rodata.* .constdata .constdata.*)
:把*.rodata .rodata.* .constdata .constdata.*
放置到这里。
> BOARD_SDRAM
:把.text的内容(代码段)输出到BOARD_SDRAM内。
(2)SECTIONS – 2
/** for exception handling/unwind - some Newlib functions (in common* with C++ and STDC++) use this.*/.ARM.extab : ALIGN(4){*(.ARM.extab* .gnu.linkonce.armextab.*)} > BOARD_SDRAM.ARM.exidx : ALIGN(4){__exidx_start = .;*(.ARM.exidx* .gnu.linkonce.armexidx.*)__exidx_end = .;} > BOARD_SDRAM_etext = .;
.ARM.extab .ARM.exidx _etext
:看注释是 Newlib库中C++的某些函数异常会用到。(这里不过多关注)
(3)SECTIONS – 3
.data_RAM2 : ALIGN(4){FILL(0xff)PROVIDE(__start_data_RAM2 = .) ;PROVIDE(__start_data_NCACHE_REGION = .) ;*(.ramfunc.$RAM2)*(.ramfunc.$NCACHE_REGION)*(NonCacheable.init)*(.data.$RAM2)*(.data.$NCACHE_REGION)*(.data.$RAM2.*)*(.data.$NCACHE_REGION.*). = ALIGN(4) ;PROVIDE(__end_data_RAM2 = .) ;PROVIDE(__end_data_NCACHE_REGION = .) ;} > NCACHE_REGION AT>BOARD_SDRAM....../* MAIN DATA SECTION */.uninit_RESERVED (NOLOAD) : ALIGN(4){_start_uninit_RESERVED = .;KEEP(*(.bss.$RESERVED*)). = ALIGN(4) ;_end_uninit_RESERVED = .;} > BOARD_SDRAM AT> BOARD_SDRAM/* Main DATA section (BOARD_SDRAM) */.data : ALIGN(4){FILL(0xff)_data = . ;PROVIDE(__start_data_RAM = .) ;PROVIDE(__start_data_BOARD_SDRAM = .) ;*(vtable)*(.ramfunc*)KEEP(*(CodeQuickAccess))KEEP(*(DataQuickAccess))*(RamFunction)*(.data*). = ALIGN(4) ;_edata = . ;PROVIDE(__end_data_RAM = .) ;PROVIDE(__end_data_BOARD_SDRAM = .) ;} > BOARD_SDRAM AT>BOARD_SDRAM
上面的脚本内容定义了不同内存地址的 data 段(部分内容省略)。
.bss_RAM2 : ALIGN(4){PROVIDE(__start_bss_RAM2 = .) ;PROVIDE(__start_bss_NCACHE_REGION = .) ;*(NonCacheable)*(.bss.$RAM2)*(.bss.$NCACHE_REGION)*(.bss.$RAM2.*)*(.bss.$NCACHE_REGION.*). = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */PROVIDE(__end_bss_RAM2 = .) ;PROVIDE(__end_bss_NCACHE_REGION = .) ;} > NCACHE_REGION AT> NCACHE_REGION....../* MAIN BSS SECTION */.bss : ALIGN(4){_bss = .;PROVIDE(__start_bss_RAM = .) ;PROVIDE(__start_bss_BOARD_SDRAM = .) ;*(.bss*)*(COMMON). = ALIGN(4) ;_ebss = .;PROVIDE(__end_bss_RAM = .) ;PROVIDE(__end_bss_BOARD_SDRAM = .) ;PROVIDE(end = .);} > BOARD_SDRAM AT> BOARD_SDRAM
上面的脚本内容定义了不同内存地址的 bss 段(部分内容省略)。
/* NOINIT section for NCACHE_REGION */.noinit_RAM2 (NOLOAD) : ALIGN(4){PROVIDE(__start_noinit_RAM2 = .) ;PROVIDE(__start_noinit_NCACHE_REGION = .) ;*(.noinit.$RAM2)*(.noinit.$NCACHE_REGION)*(.noinit.$RAM2.*)*(.noinit.$NCACHE_REGION.*). = ALIGN(4) ;PROVIDE(__end_noinit_RAM2 = .) ;PROVIDE(__end_noinit_NCACHE_REGION = .) ;} > NCACHE_REGION AT> NCACHE_REGION....../* DEFAULT NOINIT SECTION */.noinit (NOLOAD): ALIGN(4){_noinit = .;PROVIDE(__start_noinit_RAM = .) ;PROVIDE(__start_noinit_BOARD_SDRAM = .) ;*(.noinit*). = ALIGN(4) ;_end_noinit = .;PROVIDE(__end_noinit_RAM = .) ;PROVIDE(__end_noinit_BOARD_SDRAM = .) ; } > BOARD_SDRAM AT> BOARD_SDRAM
上面的脚本内容定义了不同内存地址的 noinit 段,暂时没用到(部分内容省略)。
(4)SECTIONS – 4
/* Reserve and place Heap within memory map */_HeapSize = 0x1000;.heap : ALIGN(4){_pvHeapStart = .;. += _HeapSize;. = ALIGN(4);_pvHeapLimit = .;} > BOARD_SDRAM_StackSize = 0x1000;/* Reserve space in memory for Stack */.heap2stackfill :{. += _StackSize;} > BOARD_SDRAM/* Locate actual Stack in memory map */.stack ORIGIN(BOARD_SDRAM) + LENGTH(BOARD_SDRAM) - _StackSize - 0: ALIGN(4){_vStackBase = .;. = ALIGN(4);_vStackTop = . + _StackSize;} > BOARD_SDRAM/* Provide basic symbols giving location and size of main text* block, including initial values of RW data sections. Note that* these will need extending to give a complete picture with* complex images (e.g multiple Flash banks).*/_image_start = LOADADDR(.text);_image_end = LOADADDR(.data) + SIZEOF(.data);_image_size = _image_end - _image_start;/* Provide symbols for MIMXRT1170 parts for boot header generation code* to set image to be plain load image or XIP.* Config : Plain load image = false*/_boot_loadaddr = ORIGIN(BOARD_SDRAM);_boot_size = LENGTH(BOARD_SDRAM);
_HeapSize
:堆的大小。
_pvHeapStart
:堆的基地址。
_pvHeapLimit
:堆的顶部。
_StackSize
:栈的大小。
_vStackBase
:栈的底部。
_vStackTop
:栈的顶部。
_image_start
:镜像起始地址,即代码段的起始地址。
_image_end
:镜像的终点地址,即mian data段的终点地址。
_image_size
:镜像的大小。
_boot_loadaddr
:bin文件加载到内存的起始地址。
_boot_size
:bin文件的大小,这里是自动生成的(有些问题,如果没有IVT __boot_size
应该是_image_size
, 如果有IVT __boot_size
应该是 _image_size
+ IVT的大小,而不应该是整块内存的大小)。
.stack ORIGIN(BOARD_SDRAM) + LENGTH(BOARD_SDRAM) - _StackSize - 0: ALIGN(4)
:gnu link 的section 语法,定义了栈的空间和栈的起始地址,即BOARD_SDRAM的基地址 + BOARD_SDRAM的长度 - 栈的大小。
简单分析到这里,这里的链接脚本是IDE自动生成的,它有一套自己的生成规则,也可以部分自定义,后面慢慢叙述。gnu link script语法可参考 https://sourceware.org/binutils/docs/ld/。
RT1176-2(链接脚本)相关推荐
- makefile使用.lds链接脚本以及 $@ ,$^, $, 解析
先来分析一个简单的.lds链接脚本 例1,假如现在有head.c init.c nand.c main.c这4个文件: 1.1 首先创建链接脚本nand.lds: 1 SECTIONS { 2 fir ...
- 软件构建之链接应用--链接脚本
链接脚本的基本概念 链接脚本用于描述链接器如何将输入文件格式化为可执行的输出文件,所谓输入文件既为汇编后的目标文件(.o或.obj等结尾). 基本命令: ENTRY (Symbol) 用于设置程序第一 ...
- 重写了GD32VF103的启动脚本和链接脚本
官方的startup和链接脚本有点乱七八糟的,像是调试早期写的东西.我重新整理了下. 启动脚本去掉了中断向量表表部分,能节省一部分代码空间,后续可以自己定义,只要对齐到512字节(这样支持最多128个 ...
- Linker Scripts3--简单的链接脚本命令2-Assigning Values to Symbols
1.前言 本章继续讲述简单脚本命令的后半部分 2.Assigning Values to Symbols 你可以给一个符号(symbol)赋值,它会把这些定义的符号放入全局符号表(symbols ta ...
- 【软件开发底层知识修炼】十一 链接器-链接脚本
上一篇文章学习了链接器之-main函数不是第一个执行的函数:main函数不是第一个执行的函数 今天继续学习链接器,学习链接是如何动作的,从而引入链接脚本的概念.本文就学习链接脚本的概念. 1.链接脚本 ...
- S3C2440 lds链接脚本解析
1. SECTIONS到底意味着什么 在一个裸版程序里面含有*.lds文件,而lds文件意味着如果你的程序烧录在nandflash,那在nandflash的内存将根据lds文件指定偏移来分布,下面从 ...
- linux 链接脚本,Linux下的lds链接脚本简介(一)
每一个链接过程都由链接脚本(linker script, 一般以lds作为文件的后缀名)控制. 链接脚本主要用于规定如何把输入文件内的section放入输出文件内, 并控制输出文件内各部分在程序地址空 ...
- 链接脚本文件(*.lds)
链接脚本 SECTIONS {. = 0x87800000;.text : {start.o *(.text)}.rodata ALIGN(4) : {*(.rodata)}.data ALIGN(4 ...
- [GNU LD系列 3.1]一些基本的链接脚本概念
我们需要定义一些基本的概念和词汇来描述链接脚本语言. 链接器(linker)将一系列输入文件(input files)组合起来变成一个单一的输出文件(output file).输出文件和每一个输入文件 ...
最新文章
- Hexo集成Valine实现评论留言
- RADIUS协议:认证与计费的鼻祖
- 打造TypeScript的Visual Studio Code开发环境
- 微软官方解读 Win11 操作系统
- python办公入门经典_Python3入门经典100例
- 洛谷 P1560 [USACO5.2]蜗牛的旅行Snail Trails(不明原因的scanf错误)
- mini2440 SD卡脱机烧写恢复
- ueditor编辑器的坑(视频空白/保存无数据/无法删除/不能插入百度动态地图/有序列表显示问题)
- 学习Hibernate框架笔记-第3天
- Linux 中的 owner,group,others
- Redis Cluster集群
- 几步操作即可实现WhatsApp群发
- VIN码识别又叫车架号识别,OCR技术深度应用
- 谷歌浏览器被2345主页强制绑定
- 浏览器的三个精度Bug
- 网络安全实验室|网络信息安全攻防学习平台(基础关)
- css 实现弹框滚动条
- gl linux qt 库_Linux下Qt应用程序的发布(使用LDD命令查看所有依赖的库文件)
- windows的C盘根目錄下中文文件夾重命名
- switch语句的执行顺序
热门文章
- 标准日本语第六课课件
- 支付/购物车/搜索/文件上传/登录/还款/订单/功能设计点
- linux局域网控制软件下载,针对Linux系统的轻量级局域网电脑控制软件:remote安装使用...
- [转]用户体验与产品管理
- 马化腾关于产品设计与用户体验的培训(1)
- 哈工大计算机学院在职博士 学费,哈尔滨工业大学在职研究生需要缴纳的学费是不是比全日制多...
- “京东钱包” 体验报告
- AD20--添加批量原理图编号
- 编译GCC遇到的“pthread.h” not found问题
- emoji iphone android,Emoji Android to iphone