嵌入式软件面试之启动文件中data段和bss段代码拷贝分析

嵌入式软件面试之启动文件中data段和bss段代码拷贝分析

引用网上的问题:

“单片机上电初始化后,RAM存储初始化全局变量,这些全局变量是从调试器烧进去的S19文件中获取的吗?” 这是个很好的问题, 全局变量和静态变量的初始化值是保存在Flash中的Const段里的 ,新建一个工程的时候默认有个startup的汇编程序文件,它负责将const段中的初始值付给这些全部变量。这些事情是发生在你的main函数之前的。

这个问题其实简单讲就是:单片机程序下载好之后,所有的数据都存放在flash中,那么map文件中的.data段和.bss段怎么在上电之后放到RAM中呢?

mcu启动后,程序运行需要的data段、bss段在mcu startup阶段拷贝到ram中。其实就是在启动文件中添加一段拷贝代码,将flash中存放的.data段和.bss段拷贝到RAM,以下是以startup_stm32f103xe.s 为例:

单片机程序下载好之后,所有的数据都存放在flash中,那么map文件中的.data段和.bss段怎么在上电之后放到RAM中呢?

其实就是在启动文件中添加一段拷贝代码,将flash中存放的.data段和.bss段拷贝到RAM,以下是以startup_stm32f103xe.s 为例:

Reset_Handler:  //在复位函数中包含拷贝操作

/* Copy the data segment initializers from flash to SRAM */
  ldr r0, =_sdata      //data在RAM的起始地址
  ldr r1, =_edata     //data在RAM的结束地址
  ldr r2, =_sidata    //data段的FLASH存储地址
  movs r3, #0        //地址偏移寄存器
  b LoopCopyDataInit   // 跳转到子函数

CopyDataInit: // copy代码
  ldr r4, [r2, r3]     //将flash中偏移地址是r3的数据拷贝到R4
  str r4, [r0, r3]    //将R4的数据放到RAM上去
  adds r3, r3, #4 // 偏移地址加

LoopCopyDataInit:  // 循环拷贝函数
  adds r4, r0, r3       //R4的地址是搬到ram的地址
  cmp r4, r1             // 比较是否到结束地址,到结束地址的话就表示数据搬完了
  bcc CopyDataInit   //没有结束的话跳转到copy代码
  
/* Zero fill the bss segment. */
  ldr r2, =_sbss    // bss的起始地址
  ldr r4, =_ebss    //bss的结束地址
  movs r3, #0   // 这是初始化的值,0
  b LoopFillZerobss   //跳转到子函数

FillZerobss:
  str  r3, [r2]   //将R2地址初始化为0
  adds r2, r2, #4  // 地址加4

LoopFillZerobss: //循环函数
  cmp r2, r4    //判断地址是否到结束地址
  bcc FillZerobss  //没有结束的话跳转到FillZerobss

Keil中是没有这段代码的,应该是放在了KEIl的STM支持包中,如果是自己使用ARM-GCC构建STM32的编译环境,则启动文件中需要加上这段代码。

上述代码每行有添加了注释,说明了功能。有嵌入式er可能会问:这其中的地址标记符是在哪里定义的?像_sdata,_edata,_sidata这些,这些是在链接脚本中的指定好的,此启动代码对应的链接脚本文件中的定义如下:

 /* used by the startup to initialize data */
  _sidata = LOADADDR(.data);

  /* Initialized data sections goes into RAM, load LMA copy after code */
  .data : 
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */

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

  
  /* Uninitialized data section */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss secion */
    _sbss = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)

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

更多嵌入式软件面试总结见公众号【阿目分享嵌入式】,欢迎关注,可以一起交流,相互学习!

如需转载请标明出处:https://blog.csdn.net/qq_25502401/article/details/135006089

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值