如何可视化AVR程序的内存(SRAM)使用?

Mat*_*och 19 memory embedded debugging avr avr-gcc

我在AVR微控制器(ATMega328P)上运行的C程序中遇到了问题.我相信这是由于堆栈/堆冲突,但我希望能够证实这一点.

有没有什么办法可以通过堆栈和堆来可视化SRAM的使用?

注意:该程序使用avr-gcc编译并使用avr-libc.

更新:我遇到的实际问题是malloc实现失败(返回NULL).所有malloc这些都是在启动时发生的,所有这些都free发生在应用程序的最后(实际上从来没有,因为应用程序的主要部分处于无限循环中).所以我确定碎片不是问题.

mMo*_*ntu 21

您可以使用avr-size实用程序检查RAM静态使用情况,如
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=62968,http://www.avrfreaks.net/index.php?name=中所述
. PNphpBB2&file = viewtopic&t = 82536,
http ://www.avrfreaks.net/index.php?name = PnphpBB2&file = viewtopic&t = 95638,
http://letsmakerobots.com/node/27115

avr-size -C -x Filename.elf

(avr-size documentation:http://ccrma.stanford.edu/planetccrma/man/man1/avr-size.1.html)

下面是如何在IDE上设置它的示例:On Code :: Blocks,Project - > Build options - > Pre/post build steps - > Post-build steps,include:

avr-size -C $(TARGET_OUTPUT_FILE) 要么
avr-size -C --mcu=atmega328p $(TARGET_OUTPUT_FILE)

构建结束时的示例输出:

AVR Memory Usage
----------------
Device: atmega16

Program:    7376 bytes (45.0% Full)
(.text + .data + .bootloader)

Data:         81 bytes (7.9% Full)
(.data + .bss + .noinit)

EEPROM:       63 bytes (12.3% Full)
(.eeprom) 
Run Code Online (Sandbox Code Playgroud)

数据是您的SRAM使用情况,它只是编译器在编译时知道的数量.您还需要在运行时创建的内容(特别是堆栈使用).

要检查堆栈使用情况(动态RAM),请访问http://jeelabs.org/2011/05/22/atmega-memory-use/

这是一个小实用程序函数,用于确定当前未使用的RAM:

int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}
Run Code Online (Sandbox Code Playgroud)

这是使用该代码的草图:

void setup () {
    Serial.begin(57600);
    Serial.println("\n[memCheck]");
    Serial.println(freeRam());
}
Run Code Online (Sandbox Code Playgroud)

freeRam()函数返回堆末尾和堆栈上最后分配的内存之间存在的字节数,因此它实际上是堆栈/堆在碰撞之前可以增长多少.

您可以检查此函数的返回值,您怀疑可能导致堆栈/堆冲突.

  • +1 - 感谢您的链接!请注意,如果在malloc"空闲列表"中保存释放的内存,则此处定义的`freeRam()`函数将失败.如果内存经常被动态分配和释放,这在实践中可能只是一个问题 - 在AVR上可能是一种罕见的情况(例如,在我的情况下,我只是在程序初始化期间动态分配内存,所以`freeRam()`代码适合我). (2认同)

Rod*_*ddy 11

你说malloc失败并返回NULL:

你应该首先看到的一个显而易见的原因是你的堆是"满的" - 即你要求malloc的内存无法分配,因为它不可用.

有两种情况需要牢记:

a:你有一个16 K的堆,你已经使用了10 K的malloc,你尝试另外10K的malloc.你的堆太小了.

b:更常见的是,你有一个16 k的堆,你一直在做一堆malloc/free/realloc调用你的堆不到50%'满':你把malloc称为1K而且它失败了 - 什么事了?答案 - 堆空闲空间是碎片化的 - 没有可以返回的1K空闲内存.C堆管理器在发生这种情况时无法压缩堆,因此通常情况不好.有一些技术可以避免碎片,但很难知道这是否真的是问题所在.您需要将日志记录填充添加到malloc并释放,以便您可以了解正在执行的动态内存操作.

编辑:

你说所有的malloc都是在启动时发生的,所以碎片不是问题所在.

在这种情况下,应该很容易用static替换动态分配.

旧代码示例:

char *buffer;

void init()
{
  buffer = malloc(BUFFSIZE);
}
Run Code Online (Sandbox Code Playgroud)

新代码:

char buffer[BUFFSIZE];
Run Code Online (Sandbox Code Playgroud)

一旦你到处都这样做了,你的LINKER应该警告你,如果一切都不能适应可用的内存.不要忘记减小堆大小 - 但要注意一些运行时io系统函数可能仍然使用堆,因此您可能无法完全删除它.