Forum: Mikrocontroller und Digitale Elektronik ASM-Problem bei Speicher >16 Bit


von Bruno M. (brumay)


Lesenswert?

Ich arbeite z.Zt. mit einem ATMega128 (128K Flash). Das bedeutet, daß 
HIGH und LOW nicht ausreichen um die oberen Bereiche des Speichers 
anzusprechen. Wie kann ich diesen Bereich trotzdem erreichen?

von spess53 (Gast)


Lesenswert?

Hi

>Wie kann ich diesen Bereich trotzdem erreichen?

Womit? Falls du LPM meinst, dann RAMPZ0 im RAMPZ-Register setzen.

MfG Spess

von Route_66 H. (route_66)


Lesenswert?

Hallo!
Der 128 ist organisiert zu 64K x 16Bit, also alles über HIGH und LOW 
erreichbar.
EDIT: der Flash

von spess53 (Gast)


Lesenswert?

Hi

>Der 128 ist organisiert zu 64K x 16Bit, also alles über HIGH und LOW
>erreichbar.

Nein. Z.B. für LPM ist er 128x8 organisiert.

MfG Spess

von Bruno M. (brumay)


Lesenswert?

Herzlichen Dank für die schnellen Antworten! Das muß ich erst einmal 
verdauen.
Gruß Bruno

von Route_66 H. (route_66)


Lesenswert?

spess53 schrieb:
> Hi
>
>>Der 128 ist organisiert zu 64K x 16Bit, also alles über HIGH und LOW
>>erreichbar.
>
> Nein. Z.B. für LPM ist er 128x8 organisiert.
>
> MfG Spess

Stimmt. Ich hatte es nur aus Instruction-Pointer-Sicht betrachtet; bei 
Tabellen hast Du recht.

von Reinhard Kern (Gast)


Lesenswert?

Route 66 schrieb:
> Stimmt. Ich hatte es nur aus Instruction-Pointer-Sicht betrachtet; bei
> Tabellen hast Du recht.

Dann würde ich erst mal die Tabellen im unteren Bereich unterbringen - 
falls das reicht, natürlich.

Gruss Reinhard

von spess53 (Gast)


Lesenswert?

Hi

>Das muß ich erst einmal verdauen.

Lass es doch einfach den Assembler machen:
1
  .macro load_z
2
    ldi ZL,Low(@0)
3
    ldi ZH,High(@0)
4
    .if Low(@0)+ 256*High(@0) < $8000
5
      clr r16
6
    .else
7
      ldi r16,1              
8
    .endif
9
      out RAMPZ,r16
10
  .endmacro

MfG Spess

von spess53 (Gast)


Lesenswert?

Hi

Korrektur:
1
  .macro load_z
2
    ldi ZL,Low(@0*2)
3
    ldi ZH,High(@0*2)
4
    .if Low(@0)+ 256*High(@0) < $8000
5
      clr r16
6
    .else
7
      ldi r16,1              
8
    .endif
9
    out RAMPZ,r16
10
  .endmacro

MfG Spess

von spess53 (Gast)


Lesenswert?

Hi

Einfacher:
1
  .macro load_z
2
    ldi ZL, Byte3(@0*2)
3
    out RAMPZ, ZL
4
    ldi ZH, Byte2(@0*2)
5
    ldi ZL, Byte1(@0*2)
6
  .endmacro

MfG Spess

von Bruno M. (brumay)


Lesenswert?

Hallo Spess,

zum besseren Verständnis mein Problem:

Ich habe den Speicher mit Bilddaten gefüllt, die ich jetzt von oben 
(d.h. höchste Adresse) nach unten auslesen und zu einem Controller 
übertragen will.

Wenn ich es richtig verstehe, dann kann ich durch setzen des RAMPZ Bits 
den Zeiger auf die oberste Adresse setzen und dann mit lpm (oder elpm?) 
und sbiw nach unten gehen. Muß ich dann bei Erreichen der 64K Grenze das 
RAMPZ Bit wieder löschen?

Gruß Bruno

von spess53 (Gast)


Lesenswert?

Hi

>Wenn ich es richtig verstehe, dann kann ich durch setzen des RAMPZ Bits
>den Zeiger auf die oberste Adresse setzen und dann mit lpm (oder elpm?)
>und sbiw nach unten gehen.

Ja.

Muß ich dann bei Erreichen der 64K Grenze das RAMPZ Bit wieder löschen?

Ja. Allerdings würde ich das 'automatisieren':
1
  clr r2    ; Null
2
3
  .....
4
5
  ldi ZL,1
6
  mov r3,ZL           ;
7
  out RAMPZ,r3        ; RAMPZ laden
8
  ldi ZL,Low(xy*2)
9
  ldi ZH,High(xy*2)   ; Z laden
10
11
  ....
12
13
  lpm r16,Z           ; Byte holen
14
  sbiw Z,1
15
  sbc r3,r2
16
  out RAMPZ,r3        ; (RAMPZ:Z) - 1

also keine Vergleiche und bedingte Sprünge.

>Ich habe den Speicher mit Bilddaten gefüllt, die ich jetzt von oben
>(d.h. höchste Adresse) nach unten auslesen und zu einem Controller
>übertragen will.

Die ungedrehte Reihenfolge wäre besser. Dann könntest du
1
  elpm r16,Z+

benutzen. Bei elpm wird Z und PAMPZ als 24 Bit Register benutzt und du 
brauchst dich nicht um die 64K-Grenzen zu kümmern. Allerdings kennt elpm 
nur das postincrement.

MfG Spess

von Bruno M. (brumay)


Lesenswert?

Herzlichen Dank für die tolle Information!

Gruß
Bruno

von Bruno M. (brumay)


Lesenswert?

Hallo Spess,

Ich habe doch noch eine Frage:

spess53 schrieb:

>
1
>   lpm r16,Z           ; Byte holen
2
>   sbiw Z,1
3
>   sbc r3,r2
4
>   out RAMPZ,r3        ; (RAMPZ:Z) - 1
5
>

Woher kommt der Wert in r2 wenn die Adresse von Z nach - geht??

Gruß
Bruno

von Spess53 (Gast)


Lesenswert?

Hi

>Woher kommt der Wert in r2 wenn die Adresse von Z nach - geht??

Von hier:

Beitrag "Re: ASM-Problem bei Speicher >16 Bit"

  clr r2    ; Null

Wenn Z = $0000 ist und das sbiw ausgeführt wird enthält Z den Wert $FFFF 
und das Carry-Flag wird gesetzt. sbc subtrahiert dadurch 1 (0 + C-Flag) 
von r3. Mit dem 'out RAMPZ, r3' wird dann das RAMPZ0-Bit gelöscht. Damit 
zeigt dann Z auf die oberste Adresse der unteren 64k.

MfG Spess

von Bruno M. (brumay)


Lesenswert?

Hi,

so weit war mir das klar. Was ich aber nach wie vor nicht verstehe ist, 
warum das Carry Flag von Z in r2 gesetzt wird.

Gruß Bruno

von spess53 (Gast)


Lesenswert?

Hi

>Was ich aber nach wie vor nicht verstehe ist,
>warum das Carry Flag von Z in r2 gesetzt wird.

Nicht in r2. Das ist immer Null.

Dir ist anscheinend sbc (Subtract with Carry) nicht so richtig geläufig.

Mal mit Zahlen:

C-Flag = 0   sbc 5,2       Ergebnis: 3
C-Flag = 1   sbc 5,2       Ergebnis: 2

Solange Z>=1 ist wird bei sbiw Z,1 das Carry-Flag nicht gesetzt. r3 
bleibt damit unverändert (1-0/0-0). Bei einem negativen Überlauf (Z=0 - 
1) setzt sbiw das Carry-Flag. Und in dem Fall wird von r3 (0+1) 
abgezogen. Bei out wird dann RAMPZ0 gelöscht.

MfG Spess

von amateur (Gast)


Lesenswert?

Ich würde Dir dringend empfehlen, so Du weiterhin in Assembler 
programmieren willst, Dir die Beschreibung der Befehle anzuschauen.
Der Prozessor schleppt einen ganzen Sack voll Flags mit sich herum, die, 
in der Hauptsache, von arithmetischen Operationen gesetzt bzw. gelöscht 
werden.

von Bruno M. (brumay)


Lesenswert?

Ich meine ich habe es verstanden.
Das Carry Flag oder auch andere Flags sind unabhängig von den Registern 
und werden beim nächsten Carry-Befehl wirksam. In unserem Beispiel 
könnte somit statt r2 auch jedes andere Register stehen, soferne es 0 
ist.

Danke für die Geduld!

von spess53 (Gast)


Lesenswert?

Hi

Bis auf 'beim nächsten Carry-Befehl wirksam'. Die Flags sind bis zum 
nächsten Befehl, der diese beeinflußt gültig. Die Auswertung sollte 
daher möglichst unmittelbar erfolgen.

Für die Befehle lege ich dir nahe das

http://www.atmel.com/images/doc0856.pdf

gründlich zu studieren.

MfG Spess

von amateur (Gast)


Lesenswert?

@Bruno

>Ich meine ich habe es verstanden.

Etwas vereinfacht ausgedrückt kann man sagen:
a) Es gibt Befehle, die die Flags beeinflussen und
b) Befehle, die diese unverändert lassen.

Man muss dabei aber höllisch aufpassen. Z.B.

LDI  R16,20       ; Lade 20 nach R16, keine Flagänderung
SUBI    R16,20       ; Subtrahiere 20 von R16, Flags verändert (Z)
; Ein BREQ XXX an dieser Stelle würde zu einer Verzweigung führen
; da Z=1 (stimmt ja auch)
LDI     R16,10       ; Lade 10 nach R16, keine Flagänderung
; Ein BREQ XXX an dieser Stelle würde zu einer Verzweigung führen
; da immer noch Z=1 - Obwohl R16 mittlerweile 10 ist.

von Jonas B. (jibi)


Lesenswert?

>; Ein BREQ XXX an dieser Stelle würde zu einer Verzweigung führen
>; da Z=1 (stimmt ja auch)
>LDI     R16,10       ; Lade 10 nach R16, keine Flagänderung
>; Ein BREQ XXX an dieser Stelle würde zu einer Verzweigung führen
>; da immer noch Z=1 - Obwohl R16 mittlerweile 10 ist.

Das kann ich mir nicht vorstellen. Hast du das mal ausprobiert?

Gruß Jonas

von spess53 (Gast)


Lesenswert?

Hi

>Das kann ich mir nicht vorstellen. Hast du das mal ausprobiert?

Ist schon richtig so. Ein ldi-Befehl beeinflusst keine Flags. Um auf das 
veränderte Register r16 zu reagieren müsste ein 'tst r16' gemacht 
werden.

MfG Spess

von Oliver (Gast)


Lesenswert?

http://www.atmel.com/images/doc0856.pdf

Runterladen. Lesen. Verstehen. Nochmal lesen. Und beim programieren 
solange immer wider konsultieren, bis man es auswendig kann.

Oliver

von Bruno M. (brumay)


Angehängte Dateien:

Lesenswert?

Hi,

ich muß mich noch einmal melden!
In der Zwischenzeit habe ich versucht meinen Code arbeitsfähig zu 
machen, was mir letztendlich auch gelungen ist.
Ich bin dabei allerdings auf ein Problem gestoßen, das ich mir wieder 
einmal nicht erklären kann.

Ich habe zuerst versucht die Version von Spess zu realisieren u.z.wie 
folgt:
1
Bild_loop:
2
  elpm  temp, Z
3
  st  X+, temp
4
  sbiw  Z, 1
5
  sbc  r3, r2
6
  out  RAMPZ, r3
7
  cp  XH, temp1
8
  brne  Bild_loop
9
  ret

mit X und temp1 wird die Speicheradresse neu eingestellt und hat hiermit 
eigentlich nichts zu tun.

Das Ergebnis ist in Bild1 zu sehen, wobei jetzt aber auch noch 
Spiegelungen von der Kamera enthalten sind. Bei Vergrößerung sind die 
Fehler im Mittelteil aber deutlich zu sehen. Dazu kommen noch die 
Doppelungen oben und unten, die auf einen Speicherfehler hindeuten.
Erklären kann ich mir das nicht, da ich mit dem Debugger eigentlich 
keinen Fehler finden konnte.

Funktioniert hat es letztendlich damit:
1
Bild_loop:
2
  elpm  temp, Z
3
  st  X+, temp
4
  sbiw  Z, 1
5
  cpi  ZH, 0
6
  breq  RAMP
7
_Bild_loop:  
8
  cp  XH, temp1
9
  brne  Bild_loop
10
  ret
11
RAMP:
12
  cpi  ZL, 0
13
  brne  _Bild_loop
14
  clr  r3
15
  out  RAMPZ, r3
16
  rjmp  _Bild_loop

Das Ergebnis sieht man in Bild2

Hat jemand eine Erklärung?

Mfg Bruno

von Spess53 (Gast)


Lesenswert?

Hi

>Hat jemand eine Erklärung?

Bist du sicher, das du r2 auf Null gesetzt hast?

MfG Spess

von Bruno M. (brumay)


Lesenswert?

Hallo Spess,

> Bist du sicher, das du r2 auf Null gesetzt hast?

Ich muß gestehen, daß ich es nicht ausdrücklich auf Null gesetzt habe, 
da ich es im restlichen Programm nicht benutzt habe. Das ist natürlich 
Lotterie, ich weiß. Ich melde Dir das Ergebnis nach Korrektur.

Gruß Bruno

von Bruno M. (brumay)


Lesenswert?

Das war natürlich des Rätsels Lösung. Herzlichen Dank.

Gruß Bruno

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
Noch kein Account? Hier anmelden.