• 欢迎访问我的博客,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站
  • 本网站关闭了评论功能,联系请点击→邮箱
  • Ctrl+D 可快捷收藏本站点

使用gcc编译STM32的对的.ld .map文件的理解

C/C++ gql 4年前 (2021-04-01) 1143次浏览

使用arm-none-eabi-gcc (Sourcery G++ Lite For AMR)编译STM32的C++程序后的.ld .map文件的理解
以stm32f030rct6为例,在stm32f0_stm32f030xc.ld,有如下一段脚本。

/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = 0x20008000;    /* end of 32K RAM */

/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0;      /* required amount of heap  */
_Min_Stack_Size = 0x200; /* required amount of stack */

/* Specify the memory areas */
/*ORIGIN = 0x08006000, LENGTH = 232K*/
MEMORY
{
  FLASH (rx)      : ORIGIN = 0x08006000, LENGTH = 232K
  RAM (xrw)       : ORIGIN = 0x200000C0, LENGTH = 32K
  MEMORY_B1 (rx)  : ORIGIN = 0x60000000, LENGTH = 0K
}

这里就指定了程序的入口就是在Reset_Handler,指定栈顶空间为0x20008000;堆栈大小,定义Flash起始地址0x08006000,原本0x08000000,分出0x6000作为BootLoader的引导程序。剩余的flash大小 256 – (0x6000/1024)=232 (f030rct6只有256KB的flash)。原因请查看这里 :evil:
在生成的.map文件,我们可以在Linker script and memory map(链接器脚本和内存映射)段查找到

              
                0x20008000                _estack = 0x20008000
                0x00000000                _Min_Heap_Size = 0x0
                0x00000200                _Min_Stack_Size = 0x200

接下来继续看在stm32f0_stm32f030xc.ld,有如下一段脚本。

 /* The startup code goes first into FLASH */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH

  /* The program code and other data goes into FLASH */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH

这里指定开始文件编译生成的文件放在 .isr_vector段,其实这一段就是存放的F030RC的47个中断向量地址,具体的可以在启动文件startup_stm32f030xc.s中查找,字节对齐后就是188字节(0xbc),编译后在map文件,我也可以看到如下描述,.isr_vector开始地址为0x08006000,4字节对齐,大小0xbc,与我们计算的吻合。.text代码段起始地址为 0x080060c0(为啥呢 :?: ,这里有什么占用了4个字节目前不清楚,如果哪位大佬看到了请给我说下)这里代码段占用0x1a6a8字节,接下来map文件就会接受那个函数编译后占用的flash大小了,

.isr_vector     0x08006000       0xbc
                0x08006000                . = ALIGN (0x4)
 *(.isr_vector)
 .isr_vector    0x08006000       0xbc OutPut/startup_stm32f030xc.o
                0x08006000                g_pfnVectors
                0x080060bc                . = ALIGN (0x4)

.text           0x080060c0    0x1a6a8
                0x080060c0                . = ALIGN (0x4)

可以看到前面与我们的配置信息相同。比如下面是/syscalls.c文件编译出syscalls.o文件,其中_exit函数起始地址 0x08019e5c,大小0x4,要访问函数_exit,访问地址0x08019e5c即可。

 .text._exit    0x08019e5c        0x4 OutPut/syscalls.o
                0x08019e5c                _exit
 .text._getpid  0x08019e60        0x4 OutPut/syscalls.o
                0x08019e60                _getpid
 .text._sbrk    0x08019e64       0x30 OutPut/syscalls.o
                0x08019e64                _sbrk

继续看stm32f0_stm32f030xc.ld,就会定义.rodata、.ARM.extab、.preinit_array、.init_array、.fini_array、.data、.bss、._user_heap_stack等数据段
其中.rodata段存放只读数据如常量、字符串等。.ARM.extab,.preinit_array、.init_array、.fini_array母鸡呀。.data属于已经初始化好的数据段,.bss是未初始化的数据段。这些信息都可以在map文件看到,下面来看看编译链接后的信息

section               size        addr
.isr_vector            188   134242304
.text               108200   134242496
.rodata              11084   134350696
.ARM.extab            1280   134361780
.ARM                  1448   134363060
.init_array             24   134364508
.fini_array              4   134364532
.data                 2272   536871104
.bss                  7152   536873376
._user_heap_stack      512   536880528
.ARM.attributes         41           0

可以看到.isr_vecto起始地址134242304(0x8000000),大小都与map文件吻合。.data段的既会存放在flash中,也会存放在RAM中,起始地址就是536871104(0x200000C0)与前面的描述也吻合。
存放在flash的有.isr_vector、.text、.rodata、.ARM.extab、.preinit_array、.init_array、.fini_array、.data,他们的总和就是生成的bin文件大小,该是188+4(前面提了这个疑问)+108200+11084+1280+1448+24+4+2272+7152=124504个字节(≈122KB)不能大于flash大小256KB,但是由于使用了IAP,所以不能大于前面计算的232KB。
占用的RAM就是.data,.bss的总和总计2272+7152=9424字节(不能大于f030的RAM32KB)


如未注明 , 均为原创。转载请注明原文链接:使用gcc编译STM32的对的.ld .map文件的理解
喜欢 (3)