mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik (Adress-) Springen im SRAM


Autor: Kai-uwe Wilke (riffuchs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

Ansich sinds drei kleine Fragen die aber thematisch zusammenhängen. Ich 
mag nich rumspamen, daher stopf ich sie all4 in ein Post (hoffe das 
stört nicht).

Ich schreibe über den UART Daten in den SRAM (ATmega8, also maximal 
1Kb). Nach jedem neuen Byte erhöhe ich den Pointer um 1 (logisch, damit 
er nicht immer in die gleiche Zelle schreibt). Irgendwann ist der 
Pointer z.B. bei 681 (Byte). Soweit alles okay. Jetzt bekomme ich aber 
einen neuen Datensatz und muss von Byte 0 an schreiben. Hieraus ergibt 
sich die erste Frage:

Gibt es eine Möglichkeit direkt den Pointer (z.B. von Z) zu 
Manipulieren, und mit ihm an eine beliebige Stelle im RAM zu springen? 
Der Pointer sollte dort denn auch bleiben, so das ich durch manuelles 
incrementieren weiterarbeiten kann.

Das manuelle Z+ (oder Z-) frist eben emens viele Zyklen, wenn man bei 
681 ist und zu 0 will.

Frage zwei ergibt sich auch gleich daraus: kann ich auslesen, wo der 
Z-Pointer sich gerade befindet? Also z.b. den Positionswert von Z in r16 
laden. Auch hier wieder das Problem, das ein manuelels Mitzählen 
unnötige Takte zieht. Für das Programm ist es sehr wichtig as es 
schnellst wie möglich ist, ich aber immer weiß wo sich der Pointer 
befindet (und weiß wieviele Byte im RAM stehen, weil ich den neuen 
Datensatz dann genau bis dahin lese udn alles weitere ignoriere)

Frägelchen 3 ist eher eine Verständnissfrage:

Wenn ich eienn Stack nutzen will, muss ich ihn ja Initalieieren. Ein 
Stack liegt im SRAM und wächst vom RAM-Ende zum RAM-Anfang. Wenn ich nun 
den RAM generell für Daten nutze (Z.b. für Messwerte) muss ich sicher 
aufpassen das ich immer unter dem gerade vom Stack belegten wert bleibe, 
weil der RAM meinen Stack überschreibt oder umgekehrt. Richtig? (Z.B. 
habe ich 50 Werte im Stack (mir verbleiben also 950 Byte RAM zur freien 
Nutzung. Würde ich nun 951 Byte ins RAM  schreiben, hätte ich meinen 
letzten Wert im Stack (Wert 50) überschrieben. Stimmt meine Überlegung?)

gespannt auf die Antworten

Gruß,
Uwe Wilke


Autor: Besenstil (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gibt es eine Möglichkeit direkt den Pointer (z.B. von Z) zu
Manipulieren, und mit ihm an eine beliebige Stelle im RAM zu springen?

z:=0;

usw...

B

Autor: Michael U. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich fange mal hinten an: ja, darauf musst Du selber aufpassen, sonst 
passiert genau das.

Zum Z-Register: das sind ZH und ZL, also R30/R31, damit kannst Du 
logischerweise machen, was Du willst.

clr ZL
clr ZH

ist eine mögliche Version, Z auf 0 zu bekommen.

Wenn Z auf eine bestimmte Adresse setzen willst, dann mach es eben.

ldi ZH,high($0150)
ldi ZL,low($0150)

lädt Z mit $0150 usw. usw.

Gruß aus Berlin
Michael

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Kai-uwe Wilke

Ich nehme mal an du programmierst in Assembler.

>Gibt es eine Möglichkeit direkt den Pointer (z.B. von Z) zu
>Manipulieren, und mit ihm an eine beliebige Stelle im RAM zu springen?

ldi zl,0xwhatever
ldi zh,0xwhatever

>Frage zwei ergibt sich auch gleich daraus: kann ich auslesen, wo der
>Z-Pointer sich gerade befindet? Also z.b. den Positionswert von Z in r16

Z ist nur eine andere Bezeichung für r31/r30. Dementsprechend kann man 
alle Operationen damit ausführen (Load/Store/Compare/Whatever).

>aufpassen das ich immer unter dem gerade vom Stack belegten wert bleibe,
>weil der RAM meinen Stack überschreibt oder umgekehrt. Richtig? (Z.B.

Ja.

>habe ich 50 Werte im Stack (mir verbleiben also 950 Byte RAM zur freien
>Nutzung. Würde ich nun 951 Byte ins RAM  schreiben, hätte ich meinen
>letzten Wert im Stack (Wert 50) überschrieben. Stimmt meine Überlegung?)

Ja.

MfG
Falk

Autor: Kai-uwe Wilke (riffuchs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Antworten, das brachte viel Licht ins Dunkel! :)

Ja, ich schreibe direkt ist Assembler.

Hmm, stimmt,  X, Y und Z sind ja nicht anderes als Registerpaare. Das 
ich mit denen anstellen kann was ich will ist auch logisch. Ein 
Typischer Fall von: mal wieder den Wald vor Bäumen nicht gesehen.

Logisch kann ich da Direkte Aderssangaben mit 0x$addr machen. Gibts die 
Möglichkeit das auch direkt in DEZIMAL anzugeben?  Ich meine, klar kann 
ich Pro Register "0" bis "255" schreiben. Mich interessiert nun ob ich 
für den 16 Bit wert auch eine vergleichbare zahl (die praktischerweise 
auch gleich die Speicherzelle angibt) verwenden kann? Und zwar in einer 
Zeile (z.B. LDI ZL:ZH, "720") - in dem Fall 720 für Byt 720 im RAM. Klar 
könnt ich mir was basteln, was das tut. Würde aber wieder zusätzliche 
Rechenzeit verbrauchen. Notfalls reichst schon wenn ich die Adresse 
=x$addr in einer Zeile angeben könnt, insofern das geht.

Wie schauts mit dem Stack aus, gibts dort eien art Zähler der mir sagt 
"zxy elemente auf dem Stack"?. Zu wissen wieviele Elemente auf dem Stack 
liegen (und wieviel weniger Bytes ich dementsprechen für den RAM habe) 
ist relevanter als zu wissen wieviel RAM ich belegt habe (und wieviel 
Stack mir bleibt) da halt der Stack das absolut wichtigere ist. Ich 
könnt nun einfachsagen "50 Stackplätze reservieren", aber ist mir etwas 
unsicher. Ein Angabe, wieviel gerade belegt sind (und womit ich den 
RAM-Platz dann dynamisch Einschränken kann) wäre vorteilhafter, denk 
ich.

Grüß aus Berlin,
Uwe

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Normalerweise muss man Register einzeln laden. Mir wäre jedenfalls 
nichts bekannt, womit man 2 Register auf einmal mit einem Wert 
beschreiben kann. Mal von Multiplikation und so zeug abgesehen.

Zum Stack:
Du hast den Stackpointer den du auslesen kannst. Der richtige Ansatz 
wäre aber, nachzuzählen, wie groß der Stack maximal wird. Normalerweise 
brauchst du ihn doch nur für Interrupts. Der Speichert also 2 Byte 
(glaub ich). Dann wirst du noch eine gewisse Zahl an registern sichern. 
Ich bin bisher noch nie über 5 Byte Stackgröße gekommen, denn: Wenn ein 
Interrupt ausgelöst hat, sind die anderen blockiert. Außer natürlich 
wenn du da manuell rumpfuscht.
Noch ne Wors-case-rechnung: Du sicherst im Interrupt ALLE Register, also 
32 Byte. Dann kommst du auf 34 Byte Stack. Außer wenn du sonst noch 
Daten auf den Stack pushst.
Und immer dran denken: Am Ende des Interrupts MUSS ein reti stehen.

Sebastian

Autor: Kai-uwe Wilke (riffuchs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Sebastian:

Naja es gibt ja (z.B.):

adiw ZH:ZL, 1

vondaher ging ich einfach davon aus, dass sich das auf andere Sachen 
anwenden lässt . Interessanterweise motzt der Assembler bei "ldi ZH:HL, 
100" nicht - morgen mal gucken was er in der Simulation damit tut. 
(werds dann sagen, was er macht)

Mit dem Stack hast Du natürlich recht. Generell würd ich 50 reservieren 
(das ist mehr als viel). Aber es ist immer interessant zu wissen "was 
geht und was nicht", falls es mal relevant wird (z.b. bei dem ATtiny mit 
64 Byte RAM). He, ja, RETI mit RET zu verwechseln hat lustige Folgen :)

Gruß,
Uwe Wilke

Autor: Hauke Radtki (lafkaschar) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die einfachste version sieht so aus:

ldi ZL,LOW(zahl)
ldi ZH,HIGH(zahl)

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Kai-uwe Wilke

>Logisch kann ich da Direkte Aderssangaben mit 0x$addr machen. Gibts die
>Möglichkeit das auch direkt in DEZIMAL anzugeben?  Ich meine, klar kann

Denk dran, mit absoluten Speicheradressen sollte man möglichst wenig 
hantieren, das geht schief wenn man mal was ändert (Variablen im RAM). 
Nimm lieber die professionelle Lösung mit Labels. Den Rest macht der 
Assembler. Ist auch wesentlich intutiver lesbar.


.dseg
.org 0x60

my_buffer: .db 500

.cseg

ldi zl,low(my_buffer)
ldi zh,high(my_buffer)


>könnt ich mir was basteln, was das tut. Würde aber wieder zusätzliche
>Rechenzeit verbrauchen. Notfalls reichst schon wenn ich die Adresse

Auf einer 8 Bit CPU kannst du nur 8 Bit Werte dirket beschreiben. Aber 
zwei LDIs tun niemandem weh.

>Wie schauts mit dem Stack aus, gibts dort eien art Zähler der mir sagt
>"zxy elemente auf dem Stack"?. Zu wissen wieviele Elemente auf dem Stack

Der Stack selber! Einfach die Differenz bilden aus

Stack_am_anfang-stack_aktuell

MfG
Falk

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> my_buffer: .db 500

my_buffer: .byte 500

könnte bei AVR-Studio wirksamer sein...

...

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Hannes Lux

>my_buffer: .byte 500

>könnte bei AVR-Studio wirksamer sein...

Kleiner Aufmerksamkeitstest ;-)

MfG
Falk

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.