打印
[其他]

MCU Flash与RAM空间计算

[复制链接]
351|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2023-6-13 08:33 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本文介绍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的初始化。



————————————————
版权声明:本文为CSDN博主「propor」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/propor/article/details/130762094

使用特权

评论回复
沙发
guijial511| | 2023-6-13 23:26 | 只看该作者
二姨家还能转载其它网站上的文章嘛?

使用特权

评论回复
板凳
ynndmalh21| | 2023-6-19 18:50 | 只看该作者
这个不错的,很棒的东西。哈哈

使用特权

评论回复
地板
kjkujkj22| | 2023-6-19 18:54 | 只看该作者
感谢楼主的分享,不错的想法。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1364

主题

13994

帖子

8

粉丝