繁体   English   中英

avr-gcc Arduino atmega2560使用太多的RAM

[英]avr-gcc Arduino atmega2560 using far too much RAM

我目前正在尝试编译一些代码以在AVR(ATMEGA2560)上运行,看起来我的内存不足。

我查看了清单(使用avr-objdump -x -S project.elf ),发现.data太大,无法放入8kb RAM(大约12k)中-实际上是“真正的” RAM内容从0x802FEE开始,该地址位于“外部RAM”的地址空间中。

我懂了:

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .data         00003088  00800200  0002297a  00022a0e  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  1 .text         0002297a  00000000  00000000  00000094  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .bss          00000755  00803288  00803288  00025a98  2**2
                  ALLOC
  3 .stab         00001a7c  00000000  00000000  00025a98  2**2
                  CONTENTS, READONLY, DEBUGGING
  4 .stabstr      00000d4d  00000000  00000000  00027514  2**0
                  CONTENTS, READONLY, DEBUGGING

然后,我对.data符号进行了.data并根据地址进行了排序:

grep "\.data" project.lst | sort
00800200 g       .data  00000000 __data_start
00800200 l    d  .data  00000000 .data
00802fee g     O .data  00000008 __thenan_sf
00802ff6 g     O .data  00000100 __clz_tab
008030f6 l     O .data  00000004 next
... lots of stuff in here ....
00803267 l     O .data  00000010 CSWTCH.18
00803277  w    O .data  00000010 _ZTV14HardwareSerial
00803288 g       .data  00000000 __data_end
00803288 g       .data  00000000 _edata

因此, .data应该以0x800200开始,但是由于某些原因,第一个符号位于00802fee超出了地址范围。

我想-Wl,--section-start,.data=0x800000,--defsym=__heap_end=0x8021FF但这只能通过移回事情0x200如预期-还是有一些的开始.data是推动一切了。

有谁知道这是什么,或为什么会发生? 这很烦人,因为如果不是那样的话,所有内容都应该适合。

好吧,OP已经发现了(在Olaf关于从何处开始寻找位置的评论的帮助下)实际占用了空间,但是确实应该有一个答案,因此尝试在此处进行总结:

  1. 数据段中的空间也被匿名数据(代码中的文字 )尤其是字符串文字占用。

  2. 这里的棘手问题是: avr哈佛体系结构 ,这意味着代码和数据有不同/独立的地址空间,这与普遍的只有一个统一地址空间的冯·诺依曼体系结构相反。 是为后者设计的,因此只能处理一个地址空间。 avr芯片上,数据地址空间由RAM支持,代码地址空间由闪存支持

    现在,如果RAM不足,那么将只读数据也放入闪存中将是明智的,但是有一个陷阱:给定一个带有char *的函数,编译器将转换该函数,并假设指针旨在指向数据寻址空间并发出从那里获取的程序集。 因此,需要另一个类似的功能来代替代码地址空间。

  3. 使用avr-gccavr-libc解决此问题的方法是提供PROGMEM限定符,因此编译器知道以这种方式限定的数据应存在于程序存储器(代码地址空间)中。 还有一个方便的宏PSTR()使字符串文字直接存在于程序存储器中,而无需引入另一个PROGMEM限定的标识符。 为了使用这些功能, avr-libc具有一些标准函数,后缀_P (例如puts_P() ),它们的功能完全相同,但期望它们的参数位于程序存储器中。 这是一个有点麻烦使用它的方式,但在没有透明地处理这一点,只是无法知道关于不同的地址空间。

由于avr芯片上的RAM通常很小,因此您可以做一些其他事情来保存它,例如根本不使用堆(在许多嵌入式程序中,您实际上并不需要动态分配,只需考虑一下) ),在适当的地方使用位域,让编译器“打包”所有结构( -fpack-struct选项),始终对枚举使用尽可能小的大小( -fshort-enums选项),对于小整数始终使用uint8_t ,使用位域(或在适当的地方使用位屏蔽/移位对状态进行编码等)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM