Stack vs. RAM beim Mega8

Gast #307377
Lesenswert?

... 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
Gast #307380
Lesenswert?

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.
Gast #307381
Lesenswert?

... 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!
Gast #307382
Lesenswert?

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 :-)
Gast #307383
Lesenswert?

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?
#307385
Lesenswert?

> 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
Gast #307386
Lesenswert?

@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.
Gast #307388
Lesenswert?

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.
#307389
Lesenswert?

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.

...
Gast #307391
Lesenswert?

@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?
#307393
Lesenswert?

@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.

...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren