Guten Abend, robo_wolf!
:-) nee, stehst Du nicht: Du bist nur über die Gemeinheiten der Speicherorganisation bei ATMELs MCs gestolpert.Zitat:
Zitat von robo_wolf
Guck' mal:
Offenbar ist im Flash-Speicher unter jeder Adresse je ein 2-Byte-Wort gespeichert.Zitat:
Zitat von robo_wolf
Deshalb ist der Programmzähler (PC) so aufgebaut, dass PC+1 auf das nächste 2-Byte-Wort nach PC zeigt. Beim Inkrementieren springt der PC um zwei Bytes weiter. So sind auch die Adresse 0x0019 aus Deinem Beispiel zu verstehen: Es ist die Adresse eines 2-Byte-Wortes.
Im Gegensatz dazu ist im RAM unter jeder Adresse je ein 1-Byte-Wort gespeichert.
Deshalb sind die Zeigerregister zh:zl, yh:yl und xh:xl so aufgebaut, dass sie beim Inkrementieren um ein 1-Byte-Wort weiterspringen.
Beim Auslesen des Flash-Speichers mit der „lpm“-Anweisung muss man zh:zl als Zeigerregister verwenden. Das führt zu Schwierigkeiten: zh:zl kann nur auf einzelne Bytes zeigen, die Flashspeicher-Adressen beziehen sich aber immer auf ein 2-Byte-Wort. Also muss man die Flashadresse in zh:zl verdoppeln, dann zeigt zh:zl auf das LSB des gespeicherten Doppelbytes.
Beispiel: Das MSB des unter 0x0019 im Flash gespeicherten Wortes soll ausgelesen werden
Du hast also recht: Der PC zeigt auf gerade wie ungerade Adressen im Flashspeicher. Ich bezog mich auf die Verwendung von zh:zl im Flashspeicher. Da steht das LSB immer unter der geraden Adresse und das MSB unter der ungeraden.Code:ldi zh,HIGH(0x0019)
ldi zl,LOW(0x0019)
add zl,zl ; Zeiger verdoppeln
adc zh,zh ; jetzt zeigt er auf das LSB
; lpm r16,z ; diese Anweisung würde jetzt das LSB (0xCD) nach r16 befördern
adiw zh:zl,0x0001 ; wir wollen ans MSB kommen, also noch eins draufaddieren
lpm r16,z ; so, jetzt landet das MSB (0xAB) in r16.
Am Besten, Du probierst's direkt im Simulator und mit einem Glas Wein gleich 'mal aus ;-) .
Ciao,
mare_crisium