Go Down

Topic: Getting heap size, stack size and free RAM from Due (Read 166 times) previous topic - next topic

tec_freakz

Oct 12, 2020, 09:42 pm Last Edit: Oct 12, 2020, 09:48 pm by tec_freakz
Hello Community,

i want to create a memory checkup on my Due do get RAM informetions about free ram, used heap and used stack.

This works for stack, but not for heap memory. I got memory adresses after calloc() nearby the adresses of stack adresses.

global variables definition:
Code: [Select]
unsigned long FirstAdressHeap;
unsigned long FirstAdressStack;
unsigned long previousMillisMemoryStatePrint;
const unsigned long WaitingTimeMemoryStatePrint = 10000;


running one time at begin in setup():
Code: [Select]
FirstAdressHeap = getLatestHeapAdress();
FirstAdressStack = getLatestStackAdress();



running in loop:
Code: [Select]
if (millis() - previousMillisMemoryStatePrint > WaitingTimeMemoryStatePrint)
 {
 PrintRAMstate();
 previousMillisMemoryStatePrint = millis();
 }


Defined functions:
Code: [Select]
void PrintRAMstate()
{
 unsigned long currentHeapSize;
 unsigned long currentStackSize;
 unsigned long currentFreeRAM;
 currentHeapSize = getLatestHeapAdress() - FirstAdressHeap;
 currentStackSize = FirstAdressStack - getLatestStackAdress();
 currentFreeRAM = getFreeRam();
 Serial.print(stringDebugState + "currentHeapSize: ");
 Serial.print(currentHeapSize);
 Serial.print(" currentStackSize: ");
 Serial.print(currentStackSize);
 Serial.print(" currentFreeRAM: ");
 Serial.println(currentFreeRAM);
}

unsigned long getFreeRam()
{
 int* heapVar = (int*)malloc(sizeof(int));
 unsigned long stackVarAndHeapAdress = (unsigned long)&heapVar;  
 free(heapVar);

 return (unsigned long)&stackVarAndHeapAdress - stackVarAndHeapAdress;
}

unsigned long getLatestStackAdress()
{
 byte stackVar;
 Serial.print(stringDebugState + "Stack Adress got: ");
 Serial.println((unsigned long)&stackVar);
 return (unsigned long)&stackVar;
}

unsigned long getLatestHeapAdress()
{
 int* heapVar=(int*)calloc(1,sizeof(int));
 unsigned long heapAdress = (unsigned long)&heapVar;
 free(heapVar);
 Serial.print(stringDebugState + "Heap Adress got: ");
 Serial.println(heapAdress);
 return heapAdress;
}


This prints out in serial monitor (not plausible):
Code: [Select]
[Debug state] Heap Adress got: 537427840
[Debug state] Stack Adress got: 537427852
[Debug state] currentHeapSize: 4294967240 currentStackSize: 56 currentFreeRAM: 4


Old solutions from about 2016 are not compiling with Due, like this:

Code: [Select]
int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}



Compile-Error prints in console:

Compiling 'SOAP_Server' for 'Arduino Due (Programming Port)'

Error linking for board Arduino Due (Programming Port)
Build failed for project 'SOAP_Server'
 
SOAP_Server.cpp.o: In function freeRam()
SOAP_Server.ino:2087: undefined reference to __brkval
SOAP_Server.ino:2087: undefined reference to __heap_start
 
collect2.exe*: error: ld returned 1 exit status


Does anybody have an idea, how i can get this thee memory informations in running program?
flupp.

ard_newbie

#1
Oct 13, 2020, 04:55 am Last Edit: Oct 13, 2020, 04:56 am by ard_newbie
I have this sketch to check free RAM available from the 96 K:

Code: [Select]
#include <malloc.h>

extern char _end;
extern "C" char *sbrk(int i);
char *ramstart = (char *)0x20070000;
char *ramend = (char *)0x20088000;

void setup() {
  Serial.begin(250000);
  
  char *heapend = sbrk(0);
  register char * stack_ptr asm ("sp");
  struct mallinfo mi = mallinfo();
  printf("\nDynamic ram used: %d\n", mi.uordblks);
  printf("Program static ram used %d\n", &_end - ramstart);
  printf("Stack ram used %d\n\n", ramend - stack_ptr);
  printf("My guess at free mem: %d\n", stack_ptr - heapend + mi.fordblks);
}

void loop() {

}



tec_freakz

#2
Oct 13, 2020, 07:36 am Last Edit: Oct 13, 2020, 08:10 am by tec_freakz
Where did ou get malloc.h?

I think it's currently in latest Arduino versions a part of standard lib, no seperate lib yet.
flupp.

westfw

Quote
Where did you get malloc.h?
It's part of the standard libc stuff.  Much of that is pre-included for Arduino sketches by Arduino.h, but it looks like that doesn't include the malloc-semi-internal stuff from malloc.h

The ARM chips generally use some version of newlib-nano, and newlib seems to always include the mallinfo() function.

tec_freakz

mh... it's not compiling...

Code: [Select]
sketch_oct13a:1:10: fatal error: malloc.h: No such file or directory
 #include <malloc.h>
          ^~~~~~~~~~
compilation terminated.
exit status 1
malloc.h: No such file or directory
flupp.

tec_freakz

#5
Oct 15, 2020, 06:51 pm Last Edit: Oct 15, 2020, 08:58 pm by tec_freakz
Hey guys,

good news, i solved this Problem!

I'm using the VM IDE, which has found 3 malloc.h libs on my hard drives in this constellation. Caused on this, the compiler writes in debug line, that nothig has been found... To solve it, I must to specifiy, which of this malloc.h libs i want to use (giving file path to compiler).

Now it works very well!

For the future if some users want to find out RAM issues on Due with Ethernet lib 2.0, here is my full code solution:

Including:
Code: [Select]
#include <malloc.h>

Define global variables:
Code: [Select]
unsigned long previousMillisStatePrint;
const unsigned long WaitingTimeStatePrint = 1000;
uint32_t MaxUsedHeapRAM;
uint32_t MaxUsedStackRAM;
uint32_t MaxUsedStaticRAM;
uint32_t MinfreeRAM;
extern char _end;
extern "C" char* sbrk(int i);
char* ramstart = (char*)0x20070000;
char* ramend = (char*)0x20088000;


Define two funktions:
Code: [Select]
void saveRamStates()
{
 char* heapend = sbrk(0);
 register char* stack_ptr asm("sp");
 struct mallinfo mi = mallinfo();
 if (MaxUsedStaticRAM < &_end - ramstart)
 {
 MaxUsedStaticRAM = &_end - ramstart;
 }
 if (MaxUsedHeapRAM < mi.uordblks)
 {
 MaxUsedHeapRAM = mi.uordblks;
 }
 if (MaxUsedStackRAM < ramend - stack_ptr)
 {
 MaxUsedStackRAM = ramend - stack_ptr;
 }
 if (MinfreeRAM > stack_ptr - heapend + mi.fordblks || MinfreeRAM == 0)
 {
 MinfreeRAM = stack_ptr - heapend + mi.fordblks;
 }
}

//Execute this function on different places in your code to get real stack/heap size infos in running cases
void PrintRAMstates()
{
 Serial.print(stringDebugState + "Max Used RAM STATIC: ");
 Serial.print(MaxUsedStaticRAM);
 Serial.print(" HEAP: ");
 Serial.print(MaxUsedHeapRAM);
 Serial.print(" STACK: ");
 Serial.print(MaxUsedStackRAM);
 Serial.print(" Min FREE RAM: ");
 Serial.println(MinfreeRAM);
}


Put this into loop():
Code: [Select]
if (millis() - previousMillisStatePrint > WaitingTimeStatePrint)
 {
 PrintRAMstates();
 previousMillisStatePrint = millis();
 }


Special thanks for helping to ard_newbie and westfw!

Kind regards
Fabian
flupp.

Go Up