Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 3 of 3

Thread: How to watch for out-of-memory errors?

  1. #1
    Junior Member
    Join Date
    Sep 2018
    Posts
    17

    How to watch for out-of-memory errors?

    Hi,

    If the stack or malloc heap in Teensy 4.x grows too large for the space available, how will I know? I'm starting to suspect out-of-memory errors in some strange crashes I'm seeing. Is there some facility or function I can use within my sketch to constantly monitor free memory?

    Thanks!
    Last edited by PhilK; 09-24-2020 at 08:05 PM.

  2. #2
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    631
    I would like to see a global flag that is set if any allocation ever fails.

  3. #3
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,615
    I believe maybe @FrankB may have library to help show memory usage and the like...

    I do have an example sketch in the ST7735 library (uncannyEyes_asyc_st7789_240x240... which has some stuff I was doing back then to see if I am running out of stack space.

    Again T4.x code, that has a function to call at the start of setup(DumpMemoryInfo) and one that I use in loop to see how far a stack has gone.... EstimateStackUsage...
    Code:
    // from the linker
    //  extern unsigned long _stextload;
    extern unsigned long _stext;
    extern unsigned long _etext;
    //  extern unsigned long _sdataload;
    extern unsigned long _sdata;
    extern unsigned long _edata;
    extern unsigned long _sbss;
    extern unsigned long _ebss;
    //  extern unsigned long _flexram_bank_config;
    extern unsigned long _estack;
    
    void DumpMemoryInfo() {
    #if defined(__IMXRT1062__) && defined(DEBUG_MEMORY)
      uint32_t flexram_config = IOMUXC_GPR_GPR17;
      Serial.printf("IOMUXC_GPR_GPR17:%x IOMUXC_GPR_GPR16:%x IOMUXC_GPR_GPR14:%x\n",
                    flexram_config, IOMUXC_GPR_GPR16, IOMUXC_GPR_GPR14);
      Serial.printf("Initial Stack pointer: %x\n", &_estack);
      uint32_t dtcm_size = 0;
      uint32_t itcm_size = 0;
      for (; flexram_config; flexram_config >>= 2) {
        if ((flexram_config & 0x3) == 0x2) dtcm_size += 32768;
        else if ((flexram_config & 0x3) == 0x3) itcm_size += 32768;
      }
      Serial.printf("ITCM allocated: %u  DTCM allocated: %u\n", itcm_size, dtcm_size);
      Serial.printf("ITCM init range: %x - %x Count: %u\n", &_stext, &_etext, (uint32_t)&_etext - (uint32_t)&_stext);
      Serial.printf("DTCM init range: %x - %x Count: %u\n", &_sdata, &_edata, (uint32_t)&_edata - (uint32_t)&_sdata);
      Serial.printf("DTCM cleared range: %x - %x Count: %u\n", &_sbss, &_ebss, (uint32_t)&_ebss - (uint32_t)&_sbss);
      Serial.printf("Now fill rest of DTCM with known pattern(%x - %x\n", (&_ebss + 1), (&itcm_size - 10)); Serial.flush(); //
      // Guess of where it is safe to fill memory... Maybe address of last variable we have defined - some slop...
      for (uint32_t *pfill = (&_ebss + 32); pfill < (&itcm_size - 10); pfill++) {
        *pfill = 0x01020304;  // some random value
      }
    #endif
    }
    void EstimateStackUsage() {
    #if defined(__IMXRT1062__) && defined(DEBUG_MEMORY)
      uint32_t *pmem = (&_ebss + 32);
      while (*pmem == 0x01020304) pmem++;
      Serial.printf("Estimated max stack usage: %d\n", (uint32_t)&_estack - (uint32_t)pmem);
    #endif
    }
    As for figuring out Heap usage, I will sometimes call the _sbrk function with asking for 0 increment, which will return the current start of the heap.
    This is in startup.c.
    Code:
    #include <errno.h>
    
    // from the linker script
    extern unsigned long _heap_start;
    extern unsigned long _heap_end;
    
    char *__brkval = (char *)&_heap_start;
    
    void * _sbrk(int incr)
    {
            char *prev = __brkval;
            if (incr != 0) {
                    if (prev + incr > (char *)&_heap_end) {
                            errno = ENOMEM;
                            return (void *)-1;
                    }
                    __brkval = prev + incr;
            }
            return prev;
    }
    Again this will NOT show you how much space has been freed up internally in your memory allocations.
    But sometimes I will add debug code that does something like:

    Serial.print((uint32_t)_sbrk(0), HEX);

    Or go a little more advanced like in my estimate code above, maybe save it and only print again if it changes, and can estimate how close you are to running out of memory. By comparing it to where the heap will end... As it will always be the same spot:
    From Linker scripts:
    _heap_end = ORIGIN(RAM) + LENGTH(RAM);
    as:
    RAM (rwx): ORIGIN = 0x20200000, LENGTH = 512K

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •