Yahoo Groups archive

AVR-Chat

Index last updated: 2026-04-28 22:41 UTC

Message

Re: Sanity checking

2009-02-23 by Don Kinzer

--- In AVR-Chat@yahoogroups.com, David VanHorn <microbrix@...> wrote:
> In C, is there a simple way to test wether the system has
> run out of memory while the program is running?
Simple?  No.  But there is a way.  The issues involved depend on 
which resources you're using in your C program.  It also depends on 
whether you're using external RAM or not.  For the sake of 
simplicity, the discussion below assumes no external RAM.

To review, RAM is divided into three areas: 1) statically allocated 
data items (whether initialized or not), 2) the heap (from which 
malloc() allocates space) and 3) the stack.  The statically 
allocated data items are assigned addresses in low RAM, beginning 
with the first available RAM address (which value depends on which 
AVR you're using).  The heap begins just above the statically 
allocated data items and grows toward the high end of RAM.  The 
stack begins at the high end of RAM and grows toward the low end of 
RAM.  Naturally, bad thing tend to happen if the stack grows into 
the heap and/or the statically allocated data items.

You can exploit these facts to help determine when the RAM areas are 
colliding.  The basic idea is to "seed" the RAM used by the heap and 
stack and then examine the contents from time to time to see how 
much of the seeded area remain untouched.  If you're not using the 
heap, you can determine programmatically how much unused space is 
left by scanning upward from the end of the statically allocated 
data until you find the first location with content different from 
the seed value.  If you are using the stack, the problem is 
complicated by the fact that you have two dynamic areas whose ends 
can be higher or lower at any time.

The code below can be used to seed the heap/stack RAM space.  It 
will be inserted into the startup initialization sequence fairly 
early, just after the stack pointer has been initialized.  It could 
be placed in one of the other initialization sections but .init2 
should be suitable for most applications.  If you examine the .lss 
file after compiling/linking with this code added, you'll see that 
the resulting code appears several instructions after the initial 
startup instruction.

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

#define USED __attribute__((used))
#define NAKED __attribute__((naked))
#define INIT2 __attribute__((section(".init2")))

extern uint8_t *_end;  // the end of statically allocated data
extern uint8_t *__stack; // the end of internal RAM

static void seedRAM(void) NAKED USED INIT2;
static void seedRAM(void)
{
#define SEED_VAL  0xcc
  uint16_t addr;
  for (addr = (uint16_t)&_end; addr < (uint16_t)&__stack; addr++)
    *(uint8_t *)addr = SEED_VAL;
#undef SEED_VAL
}

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.