你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

GCC STM32链接文件和启动文件分

[复制链接]
STMCU小助手 发布时间:2022-12-30 17:36
STM32链接文件和启动文件分析
SOC: STM32F401CCU6 256K flash 64k ram
Mem map:

389fdf24ee6148959f06ff67f817a096.png

链接文件部分:
. = ALIGN(4);是指4字节对齐
.,小数点表示当前的地址位置,例如__MALLOC_SYMBOLS = .;的意思是`__MALLOC_SYMBOLS 的地址就是.malloc段的地址
一般的程序中包含常见的几个段:
text(存放程序)
rodata(存放被初始化的数据)
data(表示初始化不为0的变量)
bss(表示初始化值为默认的全局变量)
text,rodata放在flash中,而data中的初始化值作为rodata放在flash中,变量在ram中占有空间,bss占ram空间
如果没有AT> FLASH,那么编译bin文件时地址是连续的
  1. /*
  2. *****************************************************************************
  3. **

  4. **  File        : stm32_flash.ld
  5. **
  6. **  Abstract    : Linker script for STM32F401VC Device with
  7. **                256KByte FLASH, 64KByte RAM
  8. **
  9. **                Set heap size, stack size and stack location according
  10. **                to application requirements.
  11. **
  12. **                Set memory bank area and size if external memory is used.
  13. **
  14. **  Target      : STMicroelectronics STM32
  15. **
  16. **  Environment : Atollic TrueSTUDIO(R)
  17. **
  18. **  Distribution: The file is distributed as is, without any warranty
  19. **                of any kind.
  20. **
  21. **  (c)Copyright Atollic AB.
  22. **  You may use this file as-is or modify it according to the needs of your
  23. **  project. This file may only be built (assembled or compiled and linked)
  24. **  using the Atollic TrueSTUDIO(R) product. The use of this file together
  25. **  with other tools than Atollic TrueSTUDIO(R) is not permitted.
  26. **
  27. *****************************************************************************
  28. */
  29. /* Entry Point */
  30. //指定入口地址为Reset_Handler
  31. //ENTRY(SYMBOL) :将符号SYMBOL的值设置成入口地址。
  32. //入口地址(entry point)是指进程执行的第一条用户空间的指令在进程地址空间的地址
  33. //ld有多种方法设置进程入口地址, 按一下顺序: (编号越前, 优先级越高)
  34. //1, ld命令行的-e选项
  35. //2, 连接脚本的ENTRY(SYMBOL)命令
  36. //3, 如果定义了start符号, 使用start符号值
  37. //4, 如果存在.text section, 使用.text section的第一字节的位置值
  38. //5, 使用值0
  39. ENTRY(Reset_Handler)

  40. /* Highest address of the user mode stack */
  41. //ram的结束地址
  42. _estack = 0x20010000;    /* end of RAM */
  43. /* Generate a link error if heap and stack don't fit into RAM */
  44. //指定的最小的堆栈大小
  45. _Min_Heap_Size = 0x200;      /* required amount of heap  */
  46. _Min_Stack_Size = 0x400; /* required amount of stack */

  47. /* Specify the memory areas */
  48. //指定flash和sram大小
  49. MEMORY
  50. {
  51. FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 256K
  52. RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 64K
  53. }

  54. /* Define output sections */
  55. // 输出文件组合布局
  56. SECTIONS
  57. {
  58.   /* The startup code goes first into FLASH */
  59.   //将向量表放在最前面,上电即可执行
  60.   .isr_vector :
  61.   {
  62.     . = ALIGN(4);
  63.     KEEP(*(.isr_vector)) /* Startup code */
  64.     . = ALIGN(4);
  65.   } >FLASH

  66.   /* The program code and other data goes into FLASH */
  67.   //指定text段,主要存放代码
  68.   .text :
  69.   {
  70.     . = ALIGN(4);
  71.     *(.text)           /* .text sections (code) */
  72.     *(.text*)          /* .text* sections (code) */
  73.     *(.glue_7)         /* glue arm to thumb code */
  74.     *(.glue_7t)        /* glue thumb to arm code */
  75.     *(.eh_frame)

  76.     KEEP (*(.init))
  77.     KEEP (*(.fini))

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

  81.   /* Constant data goes into FLASH */
  82.   //指定只读段
  83.   .rodata :
  84.   {
  85.     . = ALIGN(4);
  86.     *(.rodata)         /* .rodata sections (constants, strings, etc.) */
  87.     *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
  88.     . = ALIGN(4);
  89.   } >FLASH

  90.   .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
  91.   .ARM : {
  92.     __exidx_start = .;
  93.     *(.ARM.exidx*)
  94.     __exidx_end = .;
  95.   } >FLASH

  96.   .preinit_array     :
  97.   {
  98.     PROVIDE_HIDDEN (__preinit_array_start = .);
  99.     KEEP (*(.preinit_array*))
  100.     PROVIDE_HIDDEN (__preinit_array_end = .);
  101.   } >FLASH
  102.   .init_array :
  103.   {
  104.     PROVIDE_HIDDEN (__init_array_start = .);
  105.     KEEP (*(SORT(.init_array.*)))
  106.     KEEP (*(.init_array*))
  107.     PROVIDE_HIDDEN (__init_array_end = .);
  108.   } >FLASH
  109.   .fini_array :
  110.   {
  111.     PROVIDE_HIDDEN (__fini_array_start = .);
  112.     KEEP (*(SORT(.fini_array.*)))
  113.     KEEP (*(.fini_array*))
  114.     PROVIDE_HIDDEN (__fini_array_end = .);
  115.   } >FLASH

  116.   /* used by the startup to initialize data */
  117.   //_sidata 保存.data的地址相当于_sidata = & .data
  118.   _sidata = LOADADDR(.data);

  119.   /* Initialized data sections goes into RAM, load LMA copy after code */
  120.   //指定数据段在ram中,但是数据保存在flash中,在启动的时候需要将数据拷贝到ram中去。
  121.   .data :
  122.   {
  123.     . = ALIGN(4);
  124.     _sdata = .;        /* create a global symbol at data start */
  125.     *(.data)           /* .data sections */
  126.     *(.data*)          /* .data* sections */

  127.     . = ALIGN(4);
  128.     _edata = .;        /* define a global symbol at data end */
  129.   } >RAM AT> FLASH

  130.   
  131.   /* Uninitialized data section */
  132.   //指定bss段
  133.   . = ALIGN(4);
  134.   .bss :
  135.   {
  136.     /* This is used by the startup in order to initialize the .bss secion */
  137.     _sbss = .;         /* define a global symbol at bss start */
  138.     __bss_start__ = _sbss;
  139.     *(.bss)
  140.     *(.bss*)
  141.     *(COMMON)

  142.     . = ALIGN(4);
  143.     _ebss = .;         /* define a global symbol at bss end */
  144.     __bss_end__ = _ebss;
  145.   } >RAM

  146.   /* User_heap_stack section, used to check that there is enough RAM left */
  147.   //指定堆栈段
  148.   ._user_heap_stack :
  149.   {
  150.     . = ALIGN(4);
  151.     PROVIDE ( end = . );
  152.     PROVIDE ( _end = . );
  153.     . = . + _Min_Heap_Size;
  154.     . = . + _Min_Stack_Size;
  155.     . = ALIGN(4);
  156.   } >RAM

  157.   /* Remove information from the standard libraries */
  158.   /DISCARD/ :
  159.   {
  160.     libc.a ( * )
  161.     libm.a ( * )
  162.     libgcc.a ( * )
  163.   }
  164.   .ARM.attributes 0 : { *(.ARM.attributes) }
  165. }
复制代码

启动文件
  1. /**
  2.   ******************************************************************************
  3.   * @file      startup_stm32f401xx.s
  4.   * @author    MCD Application Team
  5.   * @version   V1.8.0
  6.   * @date      09-November-2016
  7.   * @brief     STM32F401xx Devices vector table for Atollic TrueSTUDIO toolchain.
  8.   *            This module performs:
  9.   *                - Set the initial SP
  10.   *                - Set the initial PC == Reset_Handler,
  11.   *                - Set the vector table entries with the exceptions ISR address
  12.   *                - Configure the clock system  
  13.   *                - Branches to main in the C library (which eventually
  14.   *                  calls main()).
  15.   *            After Reset the Cortex-M4 processor is in Thread mode,
  16.   *            priority is Privileged, and the Stack is set to Main.
  17.   ******************************************************************************
  18.   * @attention
  19.   *
  20.   * <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2>
  21.   *
  22.   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  23.   * You may not use this file except in compliance with the License.
  24.   * You may obtain a copy of the License at:
  25.   *
  26.   *        http://www.st.com/software_license_agreement_liberty_v2
  27.   *
  28.   * Unless required by applicable law or agreed to in writing, software
  29.   * distributed under the License is distributed on an "AS IS" BASIS,
  30.   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  31.   * See the License for the specific language governing permissions and
  32.   * limitations under the License.
  33.   *
  34.   ******************************************************************************
  35.   */
  36.    
  37.   .syntax unified //统一汇编语法-UAL
  38.   .cpu cortex-m4  //CPU类型
  39.   .fpu softvfp    //fpu 类型
  40.   .thumb          //thumb指令

  41. .global  g_pfnVectors //全局变量,外部可见
  42. .global  Default_Handler //全局变量

  43. /* start address for the initialization values of the .data section.
  44. defined in linker script */
  45. .word  _sidata //保存.data地址的变量
  46. /* start address for the .data section. defined in linker script */  
  47. .word  _sdata //data 段的起始地址,_sidata 4字节对齐后的地址,在链接脚本中定义
  48. /* end address for the .data section. defined in linker script */
  49. .word  _edata //data段的结束地址
  50. /* start address for the .bss section. defined in linker script */
  51. .word  _sbss  //bss的起始地址
  52. /* end address for the .bss section. defined in linker script */
  53. .word  _ebss  //bss的结束地址
  54. /* stack used for SystemInit_ExtMemCtl; always internal RAM used */

  55. /**
  56. * @brief  This is the code that gets called when the processor first
  57. *          starts execution following a reset event. Only the absolutely
  58. *          necessary set is performed, after which the application
  59. *          supplied main() routine is called.
  60. * @param  None
  61. * @retval : None
  62. */

  63.     .section  .text.Reset_Handler //设置新的代码段
  64.   .weak  Reset_Handler  //.weak 声明其他的同名标号优先于该标号被引用。
  65.   .type  Reset_Handler, %function //.type将Reset_Handler 指定为函数
  66. Reset_Handler:  

  67. /* Copy the data segment initializers from flash to SRAM */  
  68.   movs  r1, #0 //将立即数0存放到r1
  69.   b  LoopCopyDataInit //跳转到LoopCopyDataInit 执行
  70. //下面是将初始化的data数据拷贝到sram中去
  71. CopyDataInit:
  72.   ldr  r3, =_sidata //r3 = _sidata (flash中存放data的地址)
  73.   ldr  r3, [r3, r1] //r3 = *(r3+r1) 取出该位置的数据
  74.   str  r3, [r0, r1] //*(r0 + r1) = r3 将数据写入sram中r0 + r1的地方
  75.   adds  r1, r1, #4  //r1 += 4
  76.    
  77. LoopCopyDataInit:
  78.   ldr  r0, =_sdata //r0 = _sdata ld文件中定义
  79.   ldr  r3, =_edata //r3 = _edata  ld文件中定义
  80.   adds  r2, r0, r1 //r2 = r0+r1
  81.   cmp  r2, r3      //比较r2和r3更新标志位
  82.   bcc  CopyDataInit //C is clear 就跳转(无符号数小r2 < r3)因为汇编是顺序执行,所以这里会被循环执行,直到r2 == r3
  83.   ldr  r2, =_sbss //r2 = _sbss ld文件中定义
  84.   b  LoopFillZerobss
  85. /* Zero fill the bss segment. */  
  86. FillZerobss:
  87.   movs  r3, #0 //r3 = 0
  88.   str  r3, [r2], #4 //*r2 = 0; r2 += 4;
  89.    
  90. LoopFillZerobss: //将bss数据初始化为0
  91.   ldr  r3, = _ebss //r3 = _ebss ld文件中定义
  92.   cmp  r2, r3 //比较r2 r3
  93.   bcc  FillZerobss //r2 < r3跳转

  94. /* Call the clock system intitialization function.*/
  95.   bl  SystemInit   //跳转到SystemInit
  96. /* Call static constructors */
  97. //__libc_init_array 这个函数中执行的关键过程如下:
  98. //调用 .preinit_array 段中的预初始化函数
  99. //调用 .init 段中的 _init 函数
  100. //调用 .init_array 中的所有函数
  101.   bl __libc_init_array
  102. /* Call the application's entry point.*/
  103.   bl  main
  104.   bx  lr  
  105. // .size name,expression:将符号name所占空间设为expression(就是Reset_Handler函数大小)  
  106. .size  Reset_Handler, .-Reset_Handler

  107. /**
  108. * @brief  This is the code that gets called when the processor receives an
  109. *         unexpected interrupt.  This simply enters an infinite loop, preserving
  110. *         the system state for examination by a debugger.
  111. * @param  None     
  112. * @retval None      
  113. */
  114. //Default_Handler是个死循环
  115.     .section  .text.Default_Handler,"ax",%progbits
  116. Default_Handler:
  117. Infinite_Loop:
  118.   b  Infinite_Loop
  119.   .size  Default_Handler, .-Default_Handler
  120. /******************************************************************************
  121. *
  122. * The minimal vector table for a Cortex M3. Note that the proper constructs
  123. * must be placed on this to ensure that it ends up at physical address
  124. * 0x0000.0000.
  125. *
  126. *******************************************************************************/
  127.    .section  .isr_vector,"a",%progbits
  128.   .type  g_pfnVectors, %object
  129.   .size  g_pfnVectors, .-g_pfnVectors
  130.    
  131. // _estack是栈顶的值,这个值保存在flash的0地址处,flash的地址为0x08000000,
  132. // 所以0x08000000保存_estack的值
  133. g_pfnVectors:
  134.   .word  _estack
  135.   .word  Reset_Handler
  136.   .word  NMI_Handler
  137.   .word  HardFault_Handler
  138.   .word  MemManage_Handler
  139.   .word  BusFault_Handler
  140.   .word  UsageFault_Handler
  141.   .word  0
  142.   .word  0
  143.   .word  0
  144.   .word  0
  145.   .word  SVC_Handler
  146.   .word  DebugMon_Handler
  147.   .word  0
  148.   .word  PendSV_Handler
  149.   .word  SysTick_Handler
  150.   
  151.   /* External Interrupts */
  152.   .word     WWDG_IRQHandler                   /* Window WatchDog                             */                                       
  153.   .word     PVD_IRQHandler                    /* PVD through EXTI Line detection             */                        
  154.   .word     TAMP_STAMP_IRQHandler             /* Tamper and TimeStamps through the EXTI line */            
  155.   .word     RTC_WKUP_IRQHandler               /* RTC Wakeup through the EXTI line            */                     
  156.   .word     FLASH_IRQHandler                  /* FLASH                        */                                          
  157.   .word     RCC_IRQHandler                    /* RCC                          */                                            
  158.   .word     EXTI0_IRQHandler                  /* EXTI Line0                   */                        
  159.   .word     EXTI1_IRQHandler                  /* EXTI Line1                   */                          
  160.   .word     EXTI2_IRQHandler                  /* EXTI Line2                   */                          
  161.   .word     EXTI3_IRQHandler                  /* EXTI Line3                   */                          
  162.   .word     EXTI4_IRQHandler                  /* EXTI Line4                   */                          
  163.   //略...
  164.                           
  165. /*******************************************************************************
  166. *
  167. * Provide weak aliases for each Exception handler to the Default_Handler.
  168. * As they are weak aliases, any function with the same name will override
  169. * this definition.
  170. *
  171. *******************************************************************************/
  172.    .weak      NMI_Handler
  173.    .thumb_set NMI_Handler,Default_Handler
  174.   
  175.    .weak      HardFault_Handler
  176.    .thumb_set HardFault_Handler,Default_Handler
  177.   
  178.    .weak      MemManage_Handler
  179.    .thumb_set MemManage_Handler,Default_Handler
  180.   
  181.    .weak      BusFault_Handler
  182.    .thumb_set BusFault_Handler,Default_Handler

  183.    .weak      UsageFault_Handler
  184.    .thumb_set UsageFault_Handler,Default_Handler

  185.    .weak      SVC_Handler
  186.    .thumb_set SVC_Handler,Default_Handler

  187.    .weak      DebugMon_Handler
  188.    .thumb_set DebugMon_Handler,Default_Handler

  189.    .weak      PendSV_Handler
  190.    .thumb_set PendSV_Handler,Default_Handler

  191.    .weak      SysTick_Handler
  192.    .thumb_set SysTick_Handler,Default_Handler              
  193.   
  194.    .weak      WWDG_IRQHandler                  
  195.    .thumb_set WWDG_IRQHandler,Default_Handler      
  196.                   
  197.    .weak      PVD_IRQHandler      
  198.    .thumb_set PVD_IRQHandler,Default_Handler
  199.                
  200.    .weak      TAMP_STAMP_IRQHandler            
  201.    .thumb_set TAMP_STAMP_IRQHandler,Default_Handler
  202.             
  203.    //略...
  204.            
  205. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

复制代码

总结:stm32链接文件链接后布局如下,可以看到跟链接文件的配置是一致的,Flash的起始地址放的是.isr_vector,isr_vector的第一个地址放的是_estack,也就是msp(栈顶指针的值)

  1. tony@DESKTOP-VP4O54O:~/workdir/tony_linux_stm32_cmake/build$ readelf -S USER.elf
  2. There are 23 section headers, starting at offset 0x95690:

  3. Section Headers:
  4.   [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  5.   [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  6.   [ 1] .isr_vector       PROGBITS        08000000 010000 000194 00   A  0   0  1
  7.   [ 2] .text             PROGBITS        08000194 010194 000afc 00  AX  0   0  4
  8.   [ 3] .rodata           PROGBITS        08000c90 020010 000000 00  WA  0   0  1
  9.   [ 4] .init_array       INIT_ARRAY      08000c90 010c90 000004 04  WA  0   0  4
  10.   [ 5] .fini_array       FINI_ARRAY      08000c94 010c94 000004 04  WA  0   0  4
  11.   [ 6] .data             PROGBITS        20000000 020000 000010 00  WA  0   0  4
  12.   [ 7] .bss              NOBITS          20000010 020010 0000e8 00  WA  0   0  4
  13.   [ 8] ._user_heap_stack NOBITS          200000f8 0200f8 000600 00  WA  0   0  1
  14.   [ 9] .ARM.attributes   ARM_ATTRIBUTES  00000000 020010 000030 00      0   0  1
  15.   [10] .debug_line       PROGBITS        00000000 020040 003936 00      0   0  1
  16.   [11] .debug_info       PROGBITS        00000000 023976 003df2 00      0   0  1
  17.   [12] .debug_abbrev     PROGBITS        00000000 027768 000ace 00      0   0  1
  18.   [13] .debug_aranges    PROGBITS        00000000 028238 000470 00      0   0  8
  19.   [14] .debug_str        PROGBITS        00000000 0286a8 064708 01  MS  0   0  1
  20.   [15] .debug_ranges     PROGBITS        00000000 08cdb0 0003f8 00      0   0  8
  21.   [16] .debug_loc        PROGBITS        00000000 08d1a8 0027c4 00      0   0  1
  22.   [17] .debug_macro      PROGBITS        00000000 08f96c 00345e 00      0   0  1
  23.   [18] .comment          PROGBITS        00000000 092dca 000049 01  MS  0   0  1
  24.   [19] .debug_frame      PROGBITS        00000000 092e14 00121c 00      0   0  4
  25.   [20] .symtab           SYMTAB          00000000 094030 000d00 10     21 105  4
  26.   [21] .strtab           STRTAB          00000000 094d30 000869 00      0   0  1
  27.   [22] .shstrtab         STRTAB          00000000 095599 0000f6 00      0   0  1
  28. Key to Flags:
  29.   W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  30.   L (link order), O (extra OS processing required), G (group), T (TLS),
  31.   C (compressed), x (unknown), o (OS specific), E (exclude),
  32.   y (purecode), p (processor specific)
复制代码

所以上电后会从08000000 执行,对应的异常处理函数是Reset_Handler,Reset_Handler函数做的工作首先将flash中存放的初始化的data数据拷贝到sram中(0x20000000),然后将Bss段中的数据全部初始化为0,调用SystemInit 函数初始化时钟,最后跳转到Main函数执行。
startup.s中开头注释也有总结:
- Set the initial SP
- Set the initial PC == Reset_Handler,
- Set the vector table entries with the exceptions ISR address
- Configure the clock system
- Branches to main in the C library (which eventually calls main()).
1.初始化堆栈寄存器,这里msp寄存器时机器上电后就由硬件将flash 08000000 中存的栈顶的值load到msp
寄存器中。
2.调用08000004 Reset_Handler异常处理函数
3.设置异常向量表
4.配置系统时钟,SystemInit
5.调用Main
————————————————
版权声明:tony++


收藏 评论0 发布时间:2022-12-30 17:36

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版