Gast
#5623316
Hallo,
ich programmiere schon seit längerem an einem größerem Programm für den
atmega328p in C++. Letzeres einfach, weil ich das größere Projekt
objektorientiert umsetzen wollte und templates etc. nutzen wollte ...
war auch quasi ein Art test wie gut das mit C++ auf einem 8bit
Microcontroller funtkioniert. (Eig. sehr gut muss ich sagen, abgesehen
von fehlender OOP Integration für Interrupts).
Nun kam ich plötzlich gestern an den Punkt an, dass meine Serial Library
nicht mehr funktionierte, was ich als RAM Problem ausfindig gemacht
habe. Da ich da wenig Ahnung habe, habe ich ein paar Experimente gemacht
mit folgendem Code
#include "Stream.h"
int freeRam();
void useRam();
//2015 Bytes RAM, wenn useRam() Methode auskommentiert ist
//1535 Bytes RAM mit useRam() Methode, aber nicht aufgerufen
//1535 Bytes RAM mit useRam() Methode und 1032 Bytes RAM während dem
Aufruf
int main() {
useRam();
avr::cout << freeRam() << '\n';
while(1);
}
int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int)
__brkval);
}
void useRam() {
float points[][3] = {{15, 0, 0}, {7.5, 0, 0}, {15, 0, 0} , {0, 0,
0},
{0, -15, 0}, {0, -7.5, 0}, {0, -15, 0}, {0, 0,
0},
{0, 0, 15}, {0, 0, 7.5}, {0, 0, 15}, {0, 0,
0},
{0, 15, 15}, {0, 0, 0}, {0, -15, 15}, {0, 0,
0},
{0, -15, -15}, {0, 0, 0}, {0, 15, -15}, {0, 0,
0},
{-15, 0, 0}, {-7.5, 0, 0}, {-15, 0, 0}, {0, 0,
0},
{0, 15, 0}, {0, 7.5, 0}, {0, 15, 0}, {0, 0,
0},
{0, 0, -15}, {0, 0, -7.5}, {0, 0, -15}, {0, 0,
0},
{0, -15, -15}, {0, 0, 0}, {0, 15, -15}, {0, 0,
0},
{0, 15, 15}, {0, 0, 0}, {0, -15, 15}, {0, 0,
0}};
for(float (&point)[3]: points) {
for(float& value: point ) {
avr::cout << value << '\n';
}
}
avr::cout << freeRam() << '\n';
}
Dabei ist mir folgendes aufgefallen. Habe ich die Methode mit dem
übergroßen array auskommentiert, habe ich 2015 Bytes zur Verfügung. Habe
ich die Methode aber rufe sie nicht auf, habe ich nur noch 1500 Bytes
zur Verfügung an RAM.Rufe ich sie auf, schrumpft der RAM während des
Ausrufs nochmal auf 1000 Bytes.
Deklariere ich das Array global statt lokal habe ich auch 1500 Bytes zur
Verfügung, bei Aufruf der Methode etwas weniger.
Letzeres kann ich sehr gut nachvollziehen. 120 float * 4 Bytes ... knapp
500 Bytes die dauerhaft belegt werden, da es global ist. Bei Aufruf der
Methode wird für etwas RAM verbraucht, um sich zu merken woher man kam
(soweit ich weiß). Auch bei der lokalen variante macht es Sinn, dass RAM
in Höhe von 500 Bytes belegt wird während dem Aufruf und anschließend
wieder freigegeben wird.
Was aber keinen Sinn für mich ergibt ist, dass das lokale Array
scheinbar wie das globale Array immer 500 Bytes belegt (selbst wenn die
Methode nicht aufgerufen wird). Ruft man die Methode auf, werden nochmal
während des Aufrufs 500 Bytes belegt.
Ich habe gelesen, dass das irgendwie Architektur bedingt ist, konnte den
Erklärungen aber nicht so ganz folgen. Es wäre sehr nett, wenn mir das
jemand nochmal in verständlich erläutert.
Außerdem die Frage, sollte dieses Verhalten korrekt sein, warum sollte
ich dann lokale Variablen verwenden, wenn sie im Gegensatz zu globalen
Variablen scheinbar doppelt so viel RAM belegen? (Neben dem kleinerem
scope ist doch eig der Vorteil an lokalen Variablen, dass sie nur
während dem Aufruf RAM belegen).
Vielen Dank!
Grüße
Leon