Hallo zusammen. Ich komme im Moment nicht weiter und stelle mal hier meine Frage. Hoffe das mir jemand eine Hilfestellung geben kann. Ich habe einen ATmega1284P den ich an einem Farbgrafik-Display angeschlossen habe. Jetzt habe ich einige kleine BMP Bilder in Assemblercode umgewandelt und in den Flash Speicher (Programmspeicher) abgelegt. Alles funktionierte auch bestens, bis.... bis ich ein weiteres BMP Bild integriert habe und damit über die 64K hinausgekommen bin. Das ganze verhält sich jetzt so, das ich mit dem LPM befehl das Bild zwar laden kann, aber wenn die 64k überschritten werden, wird der Rest des Bildes was über den 64k liegt nicht angezeigt bzw. nur Schrott im Display an dieser Stelle zu sehen ist. Jetzt ist mir klar, das der Programmzähler nur 64k kann und das es auch den Befehl ELPM für den oberen Bereich geben tut. Allerdings habe ich nur sehr wenige Informationen zu dem ELPM Befehl gefunden und das Beispiel aus den Unterlagen von Atmel hilft mir nicht wirklich weiter. Kann mir jemand erklären, wie der ELPM Befehl genau funktioniert und wie ich mehrere Grafiken bzw. kleine BMP Bilderchen damit ansprechen kann? Muß ich das Bild dann vorher exakt an eine bestimmte Adresse im oberen Flash legen? Und wenn ja wie mache ich das? Eventuell mit "org."? Die Bilder liegen im Moment so im Flash: testbild: .db 0x00,0x00,0xFF usw. Angesprochen werden die Bilder dann mit: ldi ZH, HIGH(testbild*2) ldi ZL, LOW(testbild*2) lpm r16, Z+ usw.... getestet habe ich diese Möglichkeit, allerdings ohne Erfolg! ldi temp, 1 out RAMPZ, temp ldi ZH, HIGH(testbild*2) ldi ZL, LOW(testbild*2) elpm lcd_h, Z+ Bin für alle Informationen sehr Dankbar. Ich denke das Problem hat (hatte) doch bestimmt jeder, der von ATmega32,64 auf 128 bzw. 256 gewechselt hat, oder?
Gast
#3498252
Wie wäre es mit: ldi temp,byte3(testbild*2) out RAMPZ,temp ldi ZH,high(testbild*2) ldi ZL,low(testbild*2) elpm lcd_h,z+
Gast
#3498322
Und in der Befehlssatzbeschreibung 'AVR Instruction Set' steht es unter 'ELPM' noch eleganter, nämlich ohne Zuhilfenahme eines 'temp'.
Am einachsten legt man die Daten nach vorne hinter die Interrupttabelle und den Code ans Ende.
der alte Hanns schrieb: > Wie wäre es mit: > > ldi temp,byte3(testbild*2) > out RAMPZ,temp > ldi ZH,high(testbild*2) > ldi ZL,low(testbild*2) > elpm lcd_h,z+ Hallo Hanns. Dein Programmbeispiel ist genau das richtige was ich benötigt hatte. Mit dieser Art der Verwendung des ELPM Befehls und des "spezial" Registers RAMPZ funktioniert es nun prächtig. Danke für die schnelle Hilfe. Habe mir auch die Assembler Instruktionen noch mal angesehen und frage mich jetzt, warum ich das Beispiel am Ende nicht gesehen habe. Da wird das ZL Register als Zwischenspeicher für RAMPZ verwendet, was ein Register erspart. Jetzt funktioniert es zwar, aber ich habe noch nicht verstanden, wie es im ATmega1284 bzw. einem Atmega2560 für die Programmierung funktioniert. Bedeutet das, das ich jetzt alle Bilder, die im oberen Bereich abgelegt werden, immer mit ELPM ansprechen muß und alle anderen Bilder die im unteren 64k Bereich liegen mit LPM? Woher weis ich dann welche Daten im unteren bzw. oberen Bereich liegen? Oder benutzt man bei einem ATmega128 bzw. 256 sowieso immer den ELPM Befehl anstelle des LPM, um sicher zu stellen, das alles über den kompletten Bereich von 128k bzw. 256k geladen werden kann? Dann gibt es ja auch noch RAMPY und RAMPX sowie EICALL und anderes, was den erweiterten Adressbereich anspricht. Werden auch diese Befehle grundsätzlich bei der Programmierung eines 128er oder 256er verwendet? Ich möchte mich schon hier bei der Antwort und Hilfe bedanken.
Gast
#3499249
Thomas W. schrieb: > Jetzt funktioniert es zwar, aber ich habe noch nicht verstanden, wie es > im ATmega1284 bzw. einem Atmega2560 für die Programmierung funktioniert. > Bedeutet das, das ich jetzt alle Bilder, die im oberen Bereich abgelegt > werden, immer mit ELPM ansprechen muß Ja, natürlich. > und alle anderen Bilder die im > unteren 64k Bereich liegen mit LPM? Nein. Auf diesen Bereich kann man mit lpm oder mit elpm zugreifen. Die von Hanns gepostete elpm-Routine funktioniert für den gesamten Flash-Bereich gleichermaßen und da der Overhead gegenüber einem Zugriff mit lpm nur einmal pro Bild anfällt, lohnt es auch nicht, eine speziellere Routine mit lpm für den unteren Bereich zu benutzen. > Dann gibt es ja auch noch RAMPY und RAMPX Nicht bei den "normalen" AVRs, das gibt's nur bei den XMegas. > sowie EICALL und anderes, was > den erweiterten Adressbereich anspricht. Werden auch diese Befehle > grundsätzlich bei der Programmierung eines 128er oder 256er verwendet? Solange es nicht auf den letzten Takt Geschwindigkeit ankommt, kann man der Einfachheit halber immer die "e"-Befehle verwenden. Wenn allerdings Geschwindigkeit ein Rolle spielt (in ISRs tut es das immer), dann sollte man die entsprechende Daten- oder Codebereiche nach Möglichkeit in den ersten 64k (bzw. 128k) ansiedeln und die Befehle ohne "e" verwenden. Das erspart es inbesondere auch, das RAMPZ-Register in ISRs sichern und wiederherstellen zu müssen.
Hallo zusammen. Also besten Dank an alle die mir geholfen haben. Das ging ja schneller wie ich gedacht hatte.... :-) Es macht halt schon sehr viel aus, wenn man andere Spezialisten fragen kann und nicht alleine im Regen steht. Jetzt verstehe ich auch, wie die ATmegas intern funktionieren und wie der Wechsel zwischen den Speicherbereichen funktioniert. Was mich aber ein bisschen erstaunt hat, ist das selbst die ATxmegas ebenfalls mit diesen Befehlen arbeiten. Bei den ATxmegas hätte ich angenommen, das diese wenigstens intern mit einem größeren Adresszähler für die größeren Flash-Speicher ausgestatte wären. Die ATxmegas sind ja schließlich nach den ATmegas gekommen und Atmel hatte irgendo geschrieben, das man die Wünsche der Kunden in den ATXmegas berücksichtigt hätte. Naja sei es wie es sei, jetzt wissen wir ja wie es geht... :-) Hat mich sehr gefreut, diese hilfreichen Hinweise von euch zu bekommen. Hoffe euch auch einmal helfen zu können. Gruß Thomas
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.