Hallo, ich bin mir beim Entwicklen bei folgender Frage nicht ganz sicher. Wieviel flüchtigen Variablenspeicher hat z.B. ein ATTiny45, 256Byte aus SRAM? Kann ich dann z.B. 256 int8_t oder 128 int16_t oder 32 uint64_t bzw. eine Mixture welche in Summe nicht über 256Byte kommt verwenden?Der avr-gcc kümmert sich dann um die optimale Anordnung/Verwendung im ATTiny45_Prtogramm.hex? Über Tipps und Infos wäre ich sehr dankbar. Gruß Markus
mgolbs schrieb: > Kann ich dann z.B. 256 int8_t oder 128 int16_t oder 32 uint64_t bzw. > eine Mixture welche in Summe nicht über 256Byte kommt verwenden? ja, aber dann musst du in ASM ohne stack arbeiten. Du brauchst du C noch ram für den Stack. solltest auf jeden fall unter 200byte bleiben.
Hallo, danke für die Info, besonders auch für die Aussagen zum Stack. Wenn ich also nur 50% des SRAM für Variablen verwende, sollte es keine Probleme in dieser Hinsicht geben? Gruß und Dank Markus
mgolbs schrieb: > Wenn ich > also nur 50% des SRAM für Variablen verwende, sollte es keine Probleme > in dieser Hinsicht geben? kann man leider nicht pauschal sagen. Wenn du dann versucht weiter 200byte auf den Stack zu legen geht es nicht mehr. Das ist als Abhänig von Programm.
Hallo, danke für die Antwort. Gibt es eine Doku, wo was zur Abschätzung bezüglich Stack Größe zu finden ist? Welche Vorgänge, Methoden,... benötigen viel Platz für den Stack? Gruß und Dank Markus
mgolbs schrieb: > danke für die Antwort. Gibt es eine Doku, wo was zur Abschätzung > bezüglich Stack Größe zu finden ist? keine ahnung, kann man eigentlich im Kopf überschlagen > Welche Vorgänge, Methoden,... > benötigen viel Platz für den Stack?
1 | int Foo( int a, int b, int c ) { |
2 | char* tmp[20]; |
3 | sprintf(tmp, "%d %d %d", a, b, c ) |
4 | return 0; |
5 | }
|
braucht schon mal mindestens Stack: 20 byte für tmp 6 byte für paramter 8 byte für printf parameter 2 byte für stackpointer Ram: 9byte für "%d %d %d"
mgolbs schrieb: > Welche Vorgänge, Methoden,... benötigen viel Platz für den Stack? Eine endlose Rekursion benötig endlos viel Stack. ;-) Scherz beiseite, das soll nur aufzeigen, dass es extrem von deinem tatsächlichen Code abhängt, wieviel Stack du benötigst. Man kann in den Startup-Code eine kleine Schleife einbauen, die den SRAM mit einem Muster vorbelegt. Dann kann man, nachdem die Applikation eine Weile gelaufen ist, nachsehen, wie weit dieses Muster „nach unten“ durch den Stack überschrieben worden ist und auf diese Weise ganz praktisch abschätzen, wie viel man dafür wirklich einplanen sollte. Bei so einem kleinen Controller nicht vergessen, die Funktion main() als “__attribute__((OS_main))” zu deklarieren, damit der Stack nicht noch zusätzlich durch das für main() unnötige Retten irgendwelcher Register belastet wird.
Jörg Wunsch schrieb: > Scherz beiseite, das soll nur aufzeigen, dass es extrem von > deinem tatsächlichen Code abhängt, wieviel Stack du benötigst. > Man kann in den Startup-Code eine kleine Schleife einbauen, die > den SRAM mit einem Muster vorbelegt. Dann kann man, nachdem die > Applikation eine Weile gelaufen ist, nachsehen, wie weit dieses > Muster „nach unten“ durch den Stack überschrieben worden ist und > auf diese Weise ganz praktisch abschätzen, wie viel man dafür > wirklich einplanen sollte. Wie kann ich das eigentlich nachsehen?
Nicolas S. schrieb: > Wie kann ich das eigentlich nachsehen? Entweder online mit einem geeigneten Debugger (via debugWIRE bei den von dir benutzten Controllern), oder du musst dir irgendwas in deine Applikation dafür einbauen. Wenn du sowieso einen Kanal zur Kommunikation nach draußen hast (RS-232 oder dergleichen), dann kannst du natürlich einfach einen kompletten Hexdump des SRAM rübersenden. Ansonsten halt eine Funktion implementieren, die den SRAM von oben nach unten durchläuft, bis sie auf wenigstens einigen hintereinander gelegenen Adressen das während der Initialisierung geschriebene Bytemuster gefunden hat, und dann diese Adresse nach draußen kommunizieren.
Hallo Jörg, danke für den Tipp. Hatte mich genau das gefragt ("Wie kann ich ohne DebugWIRE oder JTAG einen Speicher-Dump machen? Gibt es da einen Trick?"), habe aber mal wieder zu kompliziert gedacht. Kann ja auf den gesamten Speicher bequem per Pointer zugreifen. Viele Grüße Nicolas
Hallo, danke für die vielen Hinweise. Da werde ich noch gehörig dazulernen müssen.
1 | int Foo( int a, int b, int c ) { |
2 | char* tmp[20]; |
3 | sprintf(tmp, "%d %d %d", a, b, c ) |
4 | return 0; |
5 | } |
6 | braucht schon mal mindestens |
7 | Stack: |
8 | 20 byte für tmp verstanden |
9 | 6 byte für paramter int = int16_t = 2byte * 3 ??? |
10 | 8 byte für printf parameter nicht verstanden ??? |
11 | 2 byte für stackpointer ist halt so |
12 | |
13 | Ram: |
14 | 9byte für "%d %d %d" 3*2byte +3*1byte??? |
Zuerst kommt mal main(OS_main) rein. Kann man diese SRAM Auslastungen im AVRStudio 5.1 Simulator auch ermitteln? Gruß & Dank Markus
mgolbs schrieb: > 8 byte für printf parameter nicht verstanden ??? sprintf ruft intern vfprintf auf. > Kann man diese SRAM Auslastungen im AVRStudio 5.1 Simulator auch > ermitteln? Solange deine Applikation simulierbar ist (also nicht von externen Ereignissen abhängt, die du nicht in die Simulation rein bekommst), sollte das gehen, denn schließlich kannst du dir ja auch damit den kompletten SRAM-Inhalt anzeigen lassen.
Hallo, danke. Dann werde ich das mal tun. Mein Progrämmchen ist etwas ADC, IO _delay_ms() while(1){}... Habe mit dem Simulator schon etwas probiert. Mal sehen was dann so im SRAM steht. Gruß & Dank Markus
Peter II schrieb: > int Foo( int a, int b, int c ) { > char* tmp[20]; Schreibfehler? Damit es nicht falsch stehen bleibt: Mit der obigen Deklaration wäre tmp ein Array aus char-Pointern und benötigte 20 * sizeof(char *), beim AVR also 40 Bytes. char tmp[20]; würde 20 Byte belegen. Grüße Stefan
Nochmal zum Thema Speicherbelegung anzeigen: Ich könnte ja am Anfang meines main()-Programms den ganzen Speicher mit 0xAAs füllen und irgendwann, wenn mich die Belegung interessiert, das Muster z.B. auf einem Grafikdisplay darstellen. Bis auf das, was das Display braucht, kann ich so ja auf einen Blick feststellen, wie weit Variablenraum und Stack noch voneinander entfernt sind. Und wie weit überhaupt der Variablenraum die Speicherbelegung verändert hat. Den ganzen Speicher? Besser nicht. Schon am Anfang von main() sind ja schon Sachen initialisiert, die ich besser nicht überschreibe. Wie weit ich am Ende auffüllen darf, verrät mir der Stackpointer. Aber wo darf ich anfangen? Viele Grüße Nicolas
Nicolas S. schrieb: > Wie weit > ich am Ende auffüllen darf, verrät mir der Stackpointer. Aber wo darf > ich anfangen? Bei __bss_end.
1 | extern uint8_t __bss_end; |
2 | |
3 | uint8_t *ptr = &__bss_end; |
Nicolas S. schrieb: > Den ganzen Speicher? Besser nicht. Schon am Anfang von main() sind ja > schon Sachen initialisiert, die ich besser nicht überschreibe. Wie weit > ich am Ende auffüllen darf, verrät mir der Stackpointer. Aber wo darf > ich anfangen? in dem Artikel zu dem Link, den ich am 27.6. gepostet habe, steht doch alles beschrieben. Die Funktion init_mem() wird vor dem Start von main() ausgeführt (dann ist noch nichts initialisiert); die beschreibt den Speicher mit einem Muster. Mit get_mem_unused() kannst du dann bei Bedarf den freien Platz feststellen. Anhand des Quelltextes kann man auch lernen, wie man so etwas macht.
Josef D. schrieb: > in dem Artikel zu dem Link, den ich am 27.6. gepostet habe, steht doch > alles beschrieben. Beitrag "Re: Größe des möglichen flüchtigen Variablenspeichers der ATTiny 25.85"
Danke! Hatte es irgendwie überlesen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.