MCU变量加载过程

发布时间:2022-06-27 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了MCU变量加载过程脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

前言

在开发mcu代码的时候经常会有些疑惑,变量是怎么在编译之后进入单片机的ram区的呢,特别是在使用keil开发的时候。后来在接触gcc编译器和自研的mcu后,终于明白了这个问题。实际上变量编译后被放在了bin文件中代码的后面。程序运行时会主动将该区域的数据依次搬运到ram区域中。

原理

写完代码编译后,会把code中的所有变量放在代码的后面,当然这个规则也是由链接文件来决定的。示例图如下

MCU变量加载过程

在程序运行后正式进入C环境下,code中会存在一段汇编代码。主要作用就是把data区域内存依次复制到ram中,复制结束后把后面和bss长度一致区域的内存全置为0。

通过这也能够看出为什么bss区域的值会被设置为0,因为内存中是没有类型的说法。如果不全置0,无论其它哪个值都没法确认实际类型的值。

但是在keil中我们没有看到这样的代码。keil的汇编代码如下:

Reset_Handler   PROC
                EXPORT  Reset_Handler             [WEAK]
                IMPORT  SystemInit
                IMPORT  __main
                LDR     R0, =SystemInit
                BLX     R0
                LDR     R0, =__main
                BX      R0
                ENDP

这段代码执行完毕后会跳转到__main函数里执行,主要注意的是这里并不是直接跳转到我们编写的main函数里。在__main有很多的操作,其中就包括将变量复制到ram区域中。执行完毕后才会跳转到我们自己开发的main函数中执行。

示例分析

下面这段代码就是gcc编译器下移动变量内存的代码。其中有几个变量,data区的起始、结束地址,bss区的起始、结束地址都是通过ld文件中获取的。 运行完下面的code后,程序中的所有变量都被移动到了ram区域中。

/*
 *  The ranges of copy from/to are specified by following symbols
 *    __etext: LMA of start of the section to copy from. Usually end of text
 *    __data_start__: VMA of start of the section to copy to
 *    __data_end__: VMA of end of the section to copy to
 *
 *  All addresses must be aligned to 4 bytes boundary.
 */
    lrw     r1, __erodata       // data在bin文件中的起始地址
    lrw     r2, __data_start__  // data在ram中的起始地址
    lrw     r3, __data_end__    // data在ram中的结束地址

    subu    r3, r2              // r3为data的长度
    cmpnei  r3, 0               // 判断长度是否为0
    bf      .L_loop0_done

.L_loop0:                       // 将bin文件中数据依次移到ram中
    ldw     r0, (r1, 0)          
    stw     r0, (r2, 0)         
    addi    r1, 4
    addi    r2, 4
    subi    r3, 4
    cmpnei  r3, 0
    bt      .L_loop0

.L_loop0_done:

/*
 *  The BSS section is specified by following symbols
 *    __bss_start__: start of the BSS section.
 *    __bss_end__: end of the BSS section.
 *
 *  Both addresses must be aligned to 4 bytes boundary.
 */
    lrw     r1, __bss_start__
    lrw     r2, __bss_end__

    movi    r0, 0

    subu    r2, r1
    cmpnei  r2, 0
    bf      .L_loop1_done

.L_loop1:                       // 将bss里的数据复制为0
    stw     r0, (r1, 0)
    addi    r1, 4
    subi    r2, 4
    cmpnei  r2, 0
    bt      .L_loop1
.L_loop1_done:

脚本宝典总结

以上是脚本宝典为你收集整理的MCU变量加载过程全部内容,希望文章能够帮你解决MCU变量加载过程所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: