Entgegen (vielen) anders lautenden Meinungen, man sollte einen µC nicht mit dynamischer Speicherverwaltung "traktieren", habe ich mal eine wenig mehr rumgekugelt und dabei u. a. das hier gelesen:
http://forum.arduino.cc/index.php?topic=27536.msg204023#msg204023
Mit dieser Basis hab ich mal als eigentlich immer noch Arduino-Newbie heute mal ein wenig rumgebastelt und mir folgende daraus zusammengestellt:
void GetMemInfo()
{
extern unsigned int __data_start;
extern unsigned int __data_end;
extern unsigned int __bss_start;
extern unsigned int __bss_end;
extern unsigned int __heap_start;
extern void *__brkval;
// extern void *__malloc_heap_start; --> apparently already declared as char*
// extern void *__malloc_margin; --> apparently already declared as a size_t
// RAMEND and SP seem to be available without declaration here
Serial.println("--------------------------------------------");
// ---------------- Print memory profile -----------------
int16_t ramSize=0; // total amount of ram available for partitioning
int16_t dataSize=0; // partition size for .data section
int16_t bssSize=0; // partition size for .bss section
int16_t heapSize=0; // partition size for current snapshot of the heap section
int16_t stackSize=0; // partition size for current snapshot of the stack section
int16_t freeMem1=0; // available ram calculation #1
int16_t freeMem2=0; // available ram calculation #2
// summaries:
ramSize = (int) RAMEND - (int) &__data_start;
dataSize = (int) &__data_end - (int) &__data_start;
bssSize = (int) &__bss_end - (int) &__bss_start;
heapSize = (int) __brkval - (int) &__heap_start;
stackSize = (int) RAMEND - (int) SP;
freeMem1 = (int) SP - (int) __brkval;
freeMem2 = ramSize - stackSize - heapSize - bssSize - dataSize;
Serial.println("----- GET MEMORY INFORMATIONS -----");
Serial.println("");
Serial.println("--- max. available memory by hardware ---");
Serial.print("ram total = "); Serial.print( ramSize, DEC ); Serial.println(" bytes");
Serial.println("--- DATA ---");
Serial.print("data_start = 0x"); Serial.print((int) &__data_start, HEX ); Serial.print(" / "); Serial.println( (int) &__data_start, DEC);
Serial.print("data_end = 0x"); Serial.print((int) &__data_end, HEX ); Serial.print(" / "); Serial.println( (int) &__data_end, DEC);
Serial.print("data size = "); Serial.println( dataSize, DEC );
Serial.println("--- BSS ---");
Serial.print("bss_start = 0x"); Serial.print((int) & __bss_start, HEX ); Serial.print(" / "); Serial.println( (int) &__bss_start, DEC);
Serial.print("bss_end = 0x"); Serial.print((int) &__bss_end, HEX ); Serial.print(" / "); Serial.println( (int) &__bss_end, DEC);
Serial.print("bss size = "); Serial.println( bssSize, DEC );
Serial.println("--- HEAP ---");
Serial.print("heap_start =0x"); Serial.print((int) &__heap_start, HEX ); Serial.print(" / "); Serial.println( (int) &__heap_start, DEC);
Serial.println("heap_margin = ? ? ?");
// Serial.print("\n__malloc_margin=[0x"); Serial.print( (int) &__malloc_margin, HEX ); Serial.print("] which is ["); Serial.print( (int) &__malloc_margin, DEC); Serial.print("] bytes decimal");
Serial.print("heap end = 0x"); Serial.print((int) __brkval, HEX ); Serial.print(" / "); Serial.println( (int) __brkval, DEC);
Serial.print("heap size = "); Serial.println(heapSize, DEC );
Serial.println("--- STACK ---");
Serial.print("stack start = 0x"); Serial.print((int) SP, HEX ); Serial.print(" / "); Serial.println((int) SP, DEC);
Serial.print("stack end = 0x"); Serial.print( (int) RAMEND, HEX ); Serial.print(" / "); Serial.println( (int) RAMEND, DEC);
Serial.print("stack size= "); Serial.println( stackSize, DEC );
Serial.println("--- FREE MEMORY ---");
Serial.print("free size1 = "); Serial.println( freeMem1, DEC );
Serial.print("free size2 = "); Serial.println( freeMem2, DEC );
// --- free_memory ---
Serial.println("");
Serial.println("--- calculated with free_memory:");
int free_memory;
if((int)__brkval == 0)
free_memory = ((int)&free_memory) - ((int)&__bss_end);
else
free_memory = ((int)&free_memory) - ((int)__brkval);
Serial.print("free size3 = "); Serial.println(free_memory);
// --- check-memory ---
Serial.println("");
Serial.println("--- calculated with check_memory:");
uint8_t *heapptr, *stackptr;
uint16_t diff=0;
stackptr = (uint8_t *)malloc(4); // use stackptr temporarily
heapptr = stackptr; // save value of heap pointer
free(stackptr); // free up the memory again (sets stackptr to 0)
stackptr = (uint8_t *)(SP); // save value of stack pointer
Serial.print("heap strat = 0x"); Serial.print( (int) heapptr, HEX); Serial.print(" / "); Serial.println( (int) heapptr, DEC);
Serial.print("stackptr = 0x"); Serial.print( (int) stackptr, HEX); Serial.print(" / "); Serial.println( (int) stackptr, DEC);
diff=stackptr-heapptr;
Serial.print("free size4 = "); Serial.println( (int) diff, DEC);
}
Das funktioniert hier auch einwandfrei auf (m)einem UNO und MEGA.
Allerdings läuft das nicht in der LOOP, sondern erst nach einer speziellen Anfrage via Seriell.
Den restlichen Code hab ich hier mal der übersichtlichkeit weggelassen.
Dazu hab ich mein eigenes Steuerprogramm in Delphi, was aber auch nix anderes wie ein lauschendes Terminal macht und ich kann mit div. Buttons spezielle Befehle absenden ...
Ergebnis auf dem MEGA:
----- GET MEMORY INFORMATIONS -----
--- max. available memory by hardware ---
ram total = 8191 bytes
--- DATA ---
data_start = 0x200 / 512
data_end = 0x566 / 1382
data size = 870
--- BSS ---
bss_start = 0x566 / 1382
bss_end = 0x866 / 2150
bss size = 768
--- HEAP ---
heap_start =0x866 / 2150
heap_margin = ? ? ?
heap end = 0x866 / 2150
heap size = 0
--- STACK ---
stack start = 0x21D2 / 8658
stack end = 0x21FF / 8703
stack size = 45
--- FREE MEMORY ---
free size1 = 6508
free size2 = 6508--- calculated with free_memory:
free size3 = 6509--- calculated with check_memory:
heapptr = 0x868 / 2152
stackptr = 0x21D2 / 8658
free size4 = 6506
Ergebnis auf dem UNO:
----- GET MEMORY INFORMATIONS -----
--- max. available memory by hardware ---
ram total = 2047 bytes
--- DATA ---
data_start = 0x100 / 256
data_end = 0x46A / 1130
data size = 874
--- BSS ---
bss_start = 0x46A / 1130
bss_end = 0x56C / 1388
bss size = 258
--- HEAP ---
heap_start =0x56C / 1388
heap_margin = ? ? ?
heap end = 0x56C / 1388
heap size = 0
--- STACK ---
stack start = 0x8D7 / 2263
stack end = 0x8FF / 2303
stack size = 40
--- FREE MEMORY ---
free size1= 875
free size2 = 875--- calculated with free_memory:
free size3 = 876--- calculated with check_memory:
heap strat = 0x56E / 1390
stackptr = 0x8D7 / 2263
free size4 = 873
Was hier jedoch zunächst auffält, das beim max. RAM-Speicher jeweils 1 Byte zur eigentlich gesamt verfügbaren Menge fehlt.
Ebenso beim verfügbaren Speicher:
MEGA: 6508, 6509 oder 6506 - UNO: 875, 876, 873. Siehe Source, wie das jeweils berechnet wird.
Woher stammen denn da die Unterschiede aus 2 bis 3 Bytes, welche sicher NICHT unerheblich sind, wenn Heap und STack zusammenlaufen.
Ein einziges Byte in der Überlappung der Zeiger ist da schon tödlich !
Wenn ich das bisher richtig verstanden habe, wird der Speicher in einem Arduino wie folgt belegt:
Offset(0x200h) --- Data_Start --- Data_End/BSS-Start --- BSS_End/HeapPointer --- Freier Speicher --- StackPointer --- Max_Speicher.
Einiges versteh ich ja schon - aber:
- Warum steht der Speicher im Start beim UNO bei 0x100 und beim MEGA bei 0x200 ?
- Data_End und BSS-Start sollten sich doch eigentlich um 1 (ein) Byte unterscheiden ?
- Dito BSS_End und Heap_Start !
- Warum fehlt am Gesamtspeicher 1 Byte ? (.... NULL für String_ende ?)
- .... und die 2-3 Byte tödliche Heap-Stack-Differenz siehe oben.
.... ich gönn mir mal nen Gerstensaft und warte auf die wissenden "EggsBährden" .... ![]()