Quite simply, how can I tell how much free memory I have in a memory pool? I've created a memory pool, initialized it with init_mempool and use malloc & free finctions for memory management. Is there a simple way to find out how much memory is still available to be allocated? I have a fairly dynamic application and I would like to insert some degugging triggers if memory gets low. I thought of simply using malloc to request a block of say 200 bytes and then free it again. Could do this once a second and generate a low memory error if it fails. Seems a bit clunky, is there an easier way that I have missed?? Thanks, Bryan Green.
The problem with what you're asking is that using memory allocation can cause fragmentation of the heap such that there is plenty of memory left but there is not a block big enough for what you need. The Keil free routine merges adjacent free blocks. But that may not be enough. If you have an application that consistently runs out of memory, you need a larger heap (or a different allocation strategy). Have you looked at the BOX functions? Jon
We are using the BOX functions where we need quick access to fixed size blocks of memory. Our application/firmware is designed to run in several similar products and all have different memory/storage requirements. We use a standard controller PCB, loaded with a single application, our users tell it where it is being used (saves users heaps on spare parts!) Most of the memory is allocated at startup, while small amounts are malloc/free while app is running. I'm concerned that I have allocated enough ram for the memory pool and currently the only way I have of knowing that I have totally run out of memory is when malloc returns a null pointer. It's all too late then. I understand the point on how the memory may get fragmented; just because there may be 1000 bytes of unallocated memory doesn't mean that you can have a single block of 1000 bytes. I suppose the best way to continue testing is to deliberately set the memory pool to a small size and keep increasing it when the application runs out of ram. For example, works in 1.5K but not 1K, lets use 2K.
Most of the memory is allocated at startup, while small amounts are malloc/free while app is running. Do you know how much memory you have to allocate at startup (you should)? And how much is "small amount"? Maybe could place the startup data in some appropriate large buffer (static memory). I've done so and called this "non returnable heap":
static uint8_t nrheap[NRHEAP_SIZE]; static uint8_t *nrheap_ptr = nrheap; // public uint16_t nrheap_requested = 0; uint16_t nrheap_num_calls = 0; uint8_t* nrheap_alloc( uint16_t size) { uint8_t *ptr = nrheap_ptr; nrheap_num_calls++; nrheap_requested += size; if (size > nrheap_free) { return (NULL); } nrheap_ptr += size; nrheap_free -= size; return ptr; }
"Most of the memory is allocated at startup, while small amounts are malloc/free while app is running." Do these 'small amounts' plus your initial big blob add up to more RAM that is available? If not, perhaps you could just malloc up suitably sized bits of memory once and keep them around for the duration of the program? If your memory allocation/deallocation follows a malloc->free->malloc->free sequence how about using a single shared block? Perhaps you could dump dynamic allocation altogether?
Bryan, I haven't tested this, but the following function should do what you want.
long alloc_ttl, alloc_max; void available_alloc (void) { struct __mp__ MTYP *q; alloc_ttl = 0; alloc_max = 0; q = (struct __mp__ MTYP *) &__mp__; q = q->next; while (q) { alloc_ttl += q->len; if (alloc_max < q->len) allox_max = q->len; q = q->next; } }
Jon, Thanks for the code, I'll give it a go over the next few days. Bryan.