Memory monitoring uno R4 wifi

Is there a way to display the actual RAM heap via serial monitor ?

Please read and use this link: How to get the best out of this forum - Development Tools / IDE 1.x - Arduino Forum

I didn't find anything on a quick search. The problem is that the code differs per architecture, and the R4 is newish, so maybe nobody bothered to port the R3 code yet. The other way might be to use the FreeRTOS functions at
HERE

The basic "free memory" function appears to work on R4

extern "C" char* sbrk(int incr);

int freeRam() {
  char top;
  return &top - reinterpret_cast<char*>(sbrk(0));
}

void setup() {
  Serial.begin(115200);
}

void loop() {
  delay(750);
  static bool once;
  if (!once) {
    once = true;
    Serial.println("start!");
  }
  Serial.println(freeRam());
  new uint8_t[1024]; // LEAK!
}

Builds on my board with

leaving 26020 bytes for local variables

which then prints

start!
25635
24603
23571
22539
21507
20475
19443
18411
17379
16347
15315
14283
13251
12219
11187
10155
9123
8091
7059
6027
4995
3963
2931
1899

It locks up before getting below 1024. Looking at that freeRam function, it compares a pointer on the stack, &top, with a value for the heap. So that means the more deeply nested your calls are at a given moment, the lower the amount will be. This can be seen with an alternate loop and helper function

void recurse(unsigned count, size_t extra) {
  uint8_t pad[extra];
  if (count) {
    recurse(--count, extra);
  } else {
    Serial.print(reinterpret_cast<uintptr_t>(pad), HEX);
    Serial.print('\t');
    Serial.println(freeRam());
  }
}

void loop() {
  delay(750);
  static bool once;
  if (!once) {
    once = true;
    Serial.println("start!");
  }
  static unsigned counter;
  recurse(++counter, 1024);
}

It actually gets a little further before it crashes. In any case, as indicated by the addresses shown (and the math in the code), the stack grows down, and the heap grows up. The code does not account for holes in the heap, which would be fragments of free memory.

R4 does not use FreeRTOS by default. I tried the only R4 example, Arduino_FreeRTOS > FreeRTOS-Blink. Put the freeRam function and a little extra code at the top of loop

extern "C" char* sbrk(int incr);

int freeRam() {
  char top;
  return &top - reinterpret_cast<char*>(sbrk(0));
}

void loop()
{
  if (Serial.available()) {
    while (Serial.available()) Serial.read();
    Serial.print("free heap: ");
    Serial.print(xPortGetFreeHeapSize());
    Serial.print("\t");
    Serial.println(freeRam());
    Serial.print(pvPortMalloc(1000) ? "pvPortMalloc worked" : "pvPortMalloc failed");
    Serial.print("\t");
    Serial.println(malloc(1000) ? "malloc worked" : "malloc failed");
  }

which built

leaving 17376 bytes for local variables

almost 9KB less. Pressing Enter in the Serial Monitor repeatedly

free heap: 5488	-14005
pvPortMalloc worked	malloc worked
free heap: 4480	-15013
pvPortMalloc worked	malloc worked
free heap: 3472	-16021
pvPortMalloc worked	malloc worked
free heap: 2464	-17029
pvPortMalloc worked	malloc worked
free heap: 1456	-18037
pvPortMalloc worked	malloc worked
free heap: 448	-19045
pvPortMalloc failed	malloc worked
free heap: 448	-20053
pvPortMalloc failed	malloc worked
free heap: 448	-21061
pvPortMalloc failed	malloc worked
free heap: 448	-22069
pvPortMalloc failed	malloc worked
free heap: 448	-23077
pvPortMalloc failed	malloc worked
free heap: 448	-24085
pvPortMalloc failed	malloc worked
free heap: 448	-25093
pvPortMalloc failed	malloc worked
free heap: 448	-26101
pvPortMalloc failed	malloc worked
free heap: 448	-27109
pvPortMalloc failed	malloc worked
free heap: 448	-28117
pvPortMalloc failed	malloc worked
free heap: 448	-29125
pvPortMalloc failed	malloc failed

There's 5KB of memory set aside by FreeRTOS, accessible through their allocator. The calculation in freeRam results in negative numbers, because the relative position of the FreeRTOS stack has changed, but it does report about a 15KB range.

1 Like

Hi kenb4,
thank you very much for your detailed reply. Unfortunately, as you already mentioned, this does not work reliably on the Uno R4 WiFi.
In the meantime, I realized that I should have phrased my question in the forum much better. The requirement should have been: how can I detect that a RAM leak is about to occur in the near future, so that I can still react in time. In the meantime, I have found the corresponding code. My problem is therefore solved.

Thanks again for your effort.

P.S. Sorry for using the wrong site.

void WatchdogRamReserve() {
  // Versuch, 1 KB Reserve RAM vorĂĽbergehend zu reservieren
  funktionStart = millis();
  Serial.print(F("\nFUNKTION: CheckIRamReserve()\n"));

  uint8_t* block = new (std::nothrow) uint8_t[1024];

  if (block == nullptr) {
    // Speicher ist voll → reagieren
    Serial.println(F("!!! Speicher knapp, Neustart !!!"));
    delay(1000);
    NVIC_SystemReset(); // Reset beim Uno R4 WiFi
  }
  else {
    // Erfolg → Block nutzen
    Serial.println(F("RAM Speicher erfolgreich reserviert..."));
    delay(500);

    // Nach Benutzung wieder freigeben → KEIN Leak
    delete[] block;
    Serial.println(F("... und wieder freigegeben"));
    delay(500);
  }

  delay(1000);
  Serial.print(F("* * * Done in "));Serial.print(millis() - funktionStart);Serial.println(F(" mSek. * * *"));
}