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.
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. * * *"));
}