MCU Flash与RAM空间计算

文章详细介绍了MCU在生成Image时Flash和RAM的存储内容及占用空间的计算,包括数据段(BSS,DATA),代码段(CODE,.RODATA),堆和栈的分配。在初始化过程中,涉及BSS段的清零,数据段的复制以及堆栈的设置。文章通过KeiluVision和gcc交叉编译器的例子展示了如何查看和理解这些信息。
摘要由CSDN通过智能技术生成

本文介绍MCU在生成Image时,Flash与RAM存储内容及占用空间计算。

1.段

我们知道在操作系统平台,如Linux上可执行二进制程序(在linux下为一个进程单元)通常包含如下几个段:

1)数据段(BSS段,DATA段)

BSS段为未初始化的数据,此部分并不占用代码段空间,DATA段为初始化的数据,此部分是需要占用代码段空间的(需要提供具体的初始化值)。


2)代码段(CODE,.RODATA)

代码段为实际可执行的代码指令,当然,代码段同样包括一些只读数据(.RODATA),如一些定义为const的变量,代码段也包含如上所提的数据段需要初始化的数据。


3)堆

堆为动态内存分配区域,需要用户在编译前制定,对于大部分情况下,MCU的堆大小被置为0。


4)栈

栈为程序执行过程中,局部变量,中断现场保护所需要的存储区域,一般情况下,函数内部定义的自动变量越多,函数嵌套层次越高,所需的栈空间也越大。需要说明的是,编译器一般只会评估静态的栈空间的大小,无法评估实际程序在运行过程中栈空间的大小,因此,这部分的设置需尤为注意。

2.Flash空间大小

殊途同归,MCU在生成Image的过程中也需要考虑这些段,如我们使用Keil uVision生成Image(bin,hex)时,查看Map文件:

图中,我们可以看到Total ROM Size是包含Code,RO Data,RW Data的。

采用gcc交叉编译器时,Print Size:

实际生成的bin文件大小:

 

可见,生成的bin文件大小:22976 bytes = 22944(text) + 32(data) bytes,并不包含bss段(5248 bytes)。

3.RAM空间

从Keil uVision,我们可以得出,Total RW Size包含RW Data,ZI Data的。而同样道理,采用gcc交叉编译器时,Print Size时RAM空间应包含:data,bss。

但这个地方还忽略了2个非常重要的段,堆和栈。实际,我们在评估所消耗的RAM空间时,应将这2部分也考虑进去。

如Keil uVision默认设置的堆和栈大小:

采用gcc交叉编译器,通常在配置文件中也对堆,栈也有描述:

因此,实际占用RAM空间大小为:data,bss,stack,heap的总和。

4.初始化

我们知道,对于C生成的可执行文件入口函数为main函数,但在main函数之前还有一些初始化操作,这部分通常包括startup.s和__main函数(对于keil uVision来讲),为更加清晰的描述这段过程,我们以gcc交叉编译器的entry.s为例。

_start:
  j handle_reset

/* Some of the Mi-V soft IP cores support compressed 'C' extension. If the Mi-V
   core in your design doesn't support 'C' extension and you enable 'C' extension
   in firmware project compiler options, then it would result in a trap. For this
   case, we are avoiding compressed instruction here so you can put a breakpoint
   at the jump so that yo can at least look at mcause, mepc and get some hints
   about the crash. */
trap_entry:
.option push
.option norvc
j generic_trap_handler
.option pop
  .word 0
  .word 0

/* 省略 */

generic_reset_handling:
/* Copy sdata section first so that the gp is set and linker relaxation can be
   used */
    la a4, __sdata_load
    la a5, __sdata_start
    la a6, __sdata_end
    beq a4, a5, 1f     /* Exit if source and dest are same */
    beq a5, a6, 1f     /* Exit if section start and end addresses are same */
    call block_copy

1:
  /* initialize global pointer */
  la gp, __global_pointer$

.option pop

/* Floating point support configuration */
#ifdef __riscv_flen
  csrr t0, mstatus
  lui t1, 0xffffa
  addi t1, t1, -1
  and t0, t0, t1
  lui t1, 0x4
  or t1, t0, t1
  csrw mstatus, t1

  lui t0, 0x0
  fscsr t0
#endif
  call initializations
  /* Initialize stack pointer */
  la sp, __stack_top

  /* Jump into C code */
  j _init

/* Error: trap_entry is not at the expected address of reset_vector+mtvec offset
   as configured in the MIV_RV32 core vectored mode */
vector_address_not_matching:
  ebreak

initializations:
/* Initialize the .bss section */
    mv t0, ra           /* Store ra for future use */
    la  a5, __bss_start
    la  a6, __bss_end
    beq a5, a6, 1f     /* Section start and end address are the same */
    call zeroize_block

1:
/* Initialize the .sbss section */
    la  a5, __sbss_start
    la  a6, __sbss_end
    beq a5, a6, 1f     /* Section start and end address are the same */
    call zeroize_block

/* Clear heap */
    la  a5, __heap_start
    la  a6, __heap_end
    beq a5, a6, 1f     /* Section start and end address are the same */
    call zeroize_block

1:
/* Copy data section */
    la  a4, __data_load
    la  a5, __data_start
    la  a6, __data_end
    beq a4, a5, 1f     /* Exit early if source and dest are same */
    beq a5, a6, 1f     /* Section start and end addresses are the same */
    call block_copy

1:
    mv ra, t0           /* Retrieve ra */
    ret

zeroize_block:
    bltu a6, a5, block_copy_error   /* Error. End address is less than start */
    or a7, a6, a5                   /* Check if start or end is unalined */
    andi a7, a7, 0x03u
    bgtz a7, block_copy_error       /* Unaligned addresses error*/
zeroize_loop:
    sw x0, 0(a5)
    add a5, a5, __SIZEOF_POINTER__
    blt a5, a6, zeroize_loop
    ret

block_copy:
    bltu a6, a5, block_copy_error   /* Error. End address is less than start */
    or a7, a6, a5                   /* Check if start or end is unalined */
    andi a7, a7, 0x03u
    bgtz a7, block_copy_error       /* Unaligned addresses error*/
block_copy_loop:
    lw a7, 0(a4)
    sw a7, 0(a5)
    addi a5, a5, 0x04
    addi a4, a4, 0x04
    blt a5, a6, block_copy_loop
    j block_copy_exit

block_copy_error:
    j block_copy_error

block_copy_exit:
    ret

初始化流程:

generic_reset_handling->initializations->init data/bss/heap->_init->main

可以清晰的看到初始化过程中对bss,data,heap,stack的初始化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值