... kurze, hoffentlich nicht zu dumme Frage: Ich definiere im RAM meines Mega8 einige (so ca. 40) Speicherstellen z.B. .equ Pot1VAL = 0x0060+0 .equ Pot2VAL = 0x0060+1 ... um sie im Hauptprogramm mit STS / LDS anzusprechen. Danach initialisiere ich wie gewohnt den Stackpointer ldi temp, LOW(RAMEND) out SPL, temp ldi temp, HIGH(RAMEND) out SPH, temp Kann ich hierbei sicher gehen, dass sich die Speicherbereiche nicht "überschneiden" , also dass mit den darin gespeicherten Werten nichts schief geht? Bitte nicht zu sehr lachen ;-) Jan
... muß /kann ich dann den Stackpointer an einer höheren Speicherstelle initialisieren?
Höher geht nicht, da ist nichts mehr, und es ändert nichts am Problem. Du musst sicherstellen, dass der Stack nicht mehr als RAM-40 Bytes verbrät. Programmfehler mal ausnommen, ist ein Konflikt freilich arg unwahrscheinlich, zumal Assembler-Programme nicht zu exzessivem Stack-Konsum neigen.
... also werde ich sicherheitshalber noch mal zählen. Prinzipiell spricht wohl somit nichts gegen die von mir favorisierte Methode Speicherplätze zu benutzen, wenn nicht genug Register da sind ... Vielen Dank soweit!
ne, ist schon richtig. Und deswegen fängt man mit den Variablen unten, mit dem stack oben an, das gibt max. Nutzung. Treffen sie sich dennoch, musst du entweder dein Programm optimieren (temporäre Variablen, overlay bzw. die Stackbelastung geringer halten (Unterprogramme, ISR, Parameterübergabe, push/pop usw.) Reicht das alles nicht -> MC mit zu wenig RAM gewählt :-)
Kann man eigentlich rausfinden, ob der Speicher reicht. Oder sieht man das einfach daran, daß das Programm nicht mehr richtig läuft? Also ich denke mal, daß der Compiler das nicht abchecken kann. Wie würde man dann manuell eine Warnung ausgeben, wenn der Ram voll ist?
Das mit der Speicherreservierung kannst du übrigens etwas vereinfachen: .dseg Pot1VAL: .byte 1 Pot2VAL: .byte 1 ganz_viel_text: .byte 20 Statt "0x1234" kannst du nun direkt "Pot1VAL" usw. als Adresse verwenden, ohne selber herumrechnen zu müssen.
> Kann man eigentlich rausfinden, ob der Speicher reicht. Ans obere Ende der Variablen ein paar Dummy-Variablen legen und initialisieren. Wenn die Werte überschrieben wurden, war der böse Stack da ... > Wie würde man dann manuell eine Warnung ausgeben, wenn der Ram voll > ist? Die Frage ist: wieviel kann man dem System noch vertrauen, nachdem ein Stack-Überlauf aufgetreten war? Die Brute-Force Methode ist: auf Überlauf testen und ggf. in eine Endlos-Schleife gehen. Während dem Debuggen findet man den Fehler dann leicht. Beim Endprodukt hat man sicher eine Watchdog drin, die dann zuschlagen kann. Gruß, Stefan
@Andreas Schwarz: Wollte mal kurz fragen wie das mit den DSEG beim Programmieren abläuft, werden die Daten mit ins Flash geschrieben und beim Starten des Programms immer ins SRAM kopiert? Nehme mal stark an das die Daten der Variablen dann automatisch ans andere Ende im SRAM abgelegt werden.
"dseg" erlaubt dir, die Variablen zu plazieren. Das war's dann aber auch. Irgendwelche Initialisierungen sind dein Problem, der Anfangsinhalt ist vom Zufall bestimmt.
ok Anfangsinhalt ist ungewiss,weil ja noch nichts drinsteht. Mit platzieren meinst du warscheinlich die Reihenfolge, aber da ich ja die Variablen ansprechen kann spielt es ja für mich keine Rolle wierum sie sortiert sind hauptsache weit weg vom Stack.
Mit "platzieren" ist die Zuordnung zu Adressen gemeint. Mit .org legt man die erste zu benutzende Adresse fest. Mit dem Label legt man den Namen der Variable fest. Mit .byte oder .word legt man die Anzahl der benötigten Zellen fest. Man erreicht damit nur eine korrekte Zuordnung von Namen (Labels) und Adressen. Die Werte (Inhalte) musst du schon selbst initialisieren. Hangele dich mal im Help-Menü des AVR-Studios bis zum ACR-Assembler oder AVR-Assembler2 durch (jenachdem, welchen du zum Assemblieren benutzt), da gibt es mehr Informationen zu den ASM-Direktiven. ...
@Andreas: Die Möglichkeiten .equ Pot1VAL = 0x0060+0 und .dseg Pot1VAL: .byte 1 können doch beide im Programm gleich angesprochen (z.B. STS) werden? Nur die Anordnung ist im zweiten Fall einfacher, da automatisch?
@Thomas: Mach dich mal mit dem Stack und dem "Stackverbrauch" deiner Programme vertraut, dann wirst du sehen, dass deine Angst unbegründet ist. Jeder Interrupt braucht zwei Bytes Stack zum Aufruf und evtl. je ein weiteres Bytes für Push & Pop. Diese sind aber nur "geborgt" und werden zum Ende der ISR zurückgegeben. Jedes RCALL/CALL braucht zwei Bytes Stack, die beim RET zurückgegeben werden. Dazu kommt je ein Byte für eventuelles Push/Pop. Bis dahin ist der Stackbedarf überschaubar. Etwas aufpassen musst du allerdings, wenn du aus einem Unterprogramm ein weiteres Unterprogramm aufrufst und aus diesem ein weiteres Up. Dann addiert sich der jeweilige Stackbedarf, wird aber beim Verlassen der UPs wieder freigegeben. Übrigens ist es oberstes Gebot, dass der Stack "ausgeglichen" ist. Also jeder Interrupt oder UP-Aufruf (Call, Rcall) braucht definitiv seinen Rücksprung (Ret, Reti) und jedes Push braucht sein Pop. Ansonsten wächst der Stack und überschreibt dir zuerst das SRAM, dann den I/O-Bereich und zu guter Letzt auch die Register. ...
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.