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()函数返回堆末尾和堆栈上最后分配的内存之间存在的字节数,因此它实际上是堆栈/堆在碰撞之前可以增长多少.
您可以检查此函数的返回值,您怀疑可能导致堆栈/堆冲突.
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系统函数可能仍然使用堆,因此您可能无法完全删除它.