cancel
Showing results for 
Search instead for 
Did you mean: 

Have I run out of Memory, RAM Overflow

uli stone
Associate II

Hi,

I'm having trouble, because I got when I defined a second array which I need for processing a image with the STM32F429ZI Microcontroller a message that I have a RAM overflow.

When I now define a smaller array, like uint8_t image[240][320] my whole application is not running on the Microcontroller. But when I comment the initialization n of the image array out, everything is working fine.

How can I see how much memory I have used and how could I rearrange other memory on the Microcontroller?

Thank you

21 REPLIES 21

>>But somehow my code is not working correctly

Something no doubt you'll need to debug yourself.

>>When I use "uint8_t image[240][320]" (locally in the main function) I don't get an error.

Yes, the array will be half the size, and allocated from the stack. You probably aren't doing a stack-check, so good chance it will blow out globals/statics below the stack/heap

0x20030000 - 0x20024e70 = 0xB190 (45456 bytes), probably not going to accommodate 76800 (320x240)

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

CCM RAM in the 'F40x/42x is connected directly to the mcu and is unavailable for other bus masters, i.e. DMA, including the OTG_HS and ETH DMA.

As such, it's the prime memory to put stack and the processor-only variables into.

JW

(PS, Both OTG_USB modules have their own FIFO RAM - as does CAN - which do not count towards the total 256kB of RAM).

Chris1
Senior III

CCM RAM can be used but it is not contiguous with other RAM; it is located at 0x1000 0000 - 0x1000 FFFF.

This region would have to be described in your linker control file, then variables / arrays could be placed there (must be less than 64K bytes in size though).

Is your image data constant? If so, you could locate it in flash memory very easily (declare array as const).

I personally would put the stack into the CCM at 0x10000000 64KB, but in the GNU/GCC case that would actually require you to understand and fix the memory allocator in _sbrk

Clearly you won't be able to put a 76800 byte array into 64KB either, but you should perhaps evaluate your use of auto/local variables.

Rough math

uint16_t image[74880] takes 149760 bytes

149760 - 45456 bytes left

104304 over available

Does your STM32F429 implementation include SDRAM?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Bob S
Principal

Oops - yeah, I mis-added the RAM sizes. There is indeed 192K bytes of RAM starting at 0x20000000 through 0x2002ffff, and the other 64K is the CCM down at 0x10000000 as @Community member​  said.

> I personally would put the stack into the CCM at 0x10000000 64KB, but in the GNU/GCC case that would actually require you to understand and fix the memory allocator in _sbrk

For heap, not stack.

Putting stack to CCM is a trivial exercise in startup code. That most gnu-based tools mess with some linker-based symbol is just that, a mess.

OTOH it won't help with the RAM overflow, stack (unless multitasking aka RTOS) usually does not contain more than a few hundred bytes - oh, and unless there's an attempt to locate huge memories on stack through local declarations. Moving most of mcu-only data into CCM (which requires to retarget bbs/COMMON and data into CCM, two lines in the linker script; but the manually and individually locate large and other-masters-handled data into the "conventional RAM") could help, but not in this case, where 100kB+ is missing.

Our OP clearly omitted some basic back-of-the-envelope calculation before starting a project. I see this more and more often: it appears that these days the newcomers are simply not aware of the orders of magnitude larger information content (=> memory requirement) of pictures (and as an extension, video), and of course the requirements to move these data around not to mention processing them. Caused probably by the ubiquity of huge colorful displays and cheap giga/terabyte memories. This is one of those things which ought to be taught at the higher grades of elementary school these days, instead of formal grammar.

JW

uli stone
Associate II

Thank you Bob and Clive for your time!

To your questions Bob:

  1. I'm using a Image (with 312x240 pixels) and every pixel has 16 bits, but I can reduce it to 8 bits (the second array, copy of the camera image), that's why I used 8 bit. To save memory.
  2. 320x240 was an unprecise definition, since the correct definition is 312x240 but I always forget it...
  3. Memory is devided like following:
/* Specify the memory areas */
MEMORY
{
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 2048K
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 192K
CCMRAM (rw)      : ORIGIN = 0x10000000, LENGTH = 64K
}

uli stone
Associate II

Thank you Bob and Clive for your response!

To your questions Bob,

  1. The copy of the image I get from DMA can be only 8 bits, I used 16bits vs. 8bits to save memory.
  2. 312x240 is the correct image size, I always mess it up.
  3. The following is copied form the ld file:
/* Specify the memory areas */
MEMORY
{
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 2048K
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 192K
CCMRAM (rw)      : ORIGIN = 0x10000000, LENGTH = 64K
}

>>For heap, not stack.

it was more of a commentary on the craptacular _sbrk implementations that uses the SP has a high water mark for the heap, and the expectation that both reside in the 0x20000000 memory space, when the stack is down below 0x10010000 it assumes you're 20,000 leagues under the sea and dies.

/*
 sbrk
 Increase program data space.
 Malloc and related functions depend on this
 */
caddr_t _sbrk(int incr) {
 
    extern char _ebss; // Defined by the linker
    static char *heap_end;
    char *prev_heap_end;
 
    if (heap_end == 0) {
        heap_end = &_ebss;
    }
    prev_heap_end = heap_end;
 
char * stack = (char*) __get_MSP();
     if (heap_end + incr >  stack)
     {
         _write (STDERR_FILENO, "Heap and stack collision\n", 25);
         errno = ENOMEM;
         return  (caddr_t) -1;
         //abort ();
     }
 
    heap_end += incr;
    return (caddr_t) prev_heap_end;
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Uh.

I stand firmly on the *control* side of micro*control*ler, which almost completely excludes the notion of dynamic allocation of memory, let alone through any third party library, however glorified it is.

In other words, I didn't know this... ;-) Thanks.

Jan