从链接脚本开始.
以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/。