Hallo Forum,
ich habe ein meiner Meinung nach seltsames und (für mich) unerklärbares
Problem.
Ausgangssituation: Ein ATmega2560 (mit eben 256k Flash-Speicher) hat ein
etwas größeres Display angeschlossen. In seinem Flash liegen die Bilder
(im RGB-Format), die der AVR dann anzeigen soll.
Das kopieren geschieht mittels
Das funktioniert bis 64k auch ganz normal mit dem PROGMEM-Attribut.
Über der 64k-Grenze sind die Daten ja nicht mehr mit 16bit adressierbar,
was einen anderen Zugriff erfordert. Die avr-libc bietet dafür
folgendes:
Das funktioniert auch so weit, ABER:
Nur ohne -flto, also ohne link-time-optimizations
Wenn man lto aktiviert werden zwar immer noch die richtigen Daten
adressiert, aber wohl falsch gelesen.
Das äußert sich darin, dass das Display falsche RGB Werte anzeigt. Grün
wird beispielsweise blau.
Ein Blick ins Disassembly verät aber, dass die Daten korrekt im Flash
stehen.
Also muss der Zugriff irgendwie fehlerhaft sein.
Gibt es irgendwas, was man bei dem Zugriff auf Daten im Flash > 64k
beachten muss?
Oder könnte das etwa ein Bug im Compiler sein?
Mit freundlichen Grüßen,
N.G.
Eckdaten: avr-gcc-5.3.1, binutils 2.25
N. G. schrieb:> Gibt es irgendwas, was man bei dem Zugriff auf Daten im Flash > 64k> beachten muss?
Wenn deine Daten nicht in die ersten 64 KiB passten, dann gilt das
womöglich auch für andere Daten im .progmem. Als erstes würd ich also
mal das Map-File checken, ob noch andere Daten nicht mehr per LPM
erreichbar sind.
...und prinzipiell hast du auch die Möglichkeit, __flash1, __flash2 oder
__flash3 zu verwenden, was auch 16-Bit Zeiger erzeugt; eben im
entsprechenden Segment.
Allerdings brauchst du dann ein passendes Linker Description File, weil
es keine "one fits all" Lösung gibt und die standard-Beschreibung
.progmem1.data etc. nicht adäquat behandelt.
Johann L. schrieb:> Wenn deine Daten nicht in die ersten 64 KiB passten,
Tun sie nicht, sind bisher 200kB.
> dann gilt das> womöglich auch für andere Daten im .progmem. Als erstes würd ich also> mal das Map-File checken, ob noch andere Daten nicht mehr per LPM> erreichbar sind.
Ich greife generell auf alle PROGMEM-Daten mittels dem _PF, also den
far-pointer-Funktionen zu. Das sollte doch eigentlich immer gehen.
pgm_get_far_address() erzeugt ja einen 32bit Pointer (wovon aber glaube
ich nur 24 benutzt werden, weil das oberste Register immer auf 0 gesetzt
wird).
Johann L. schrieb:> ...und prinzipiell hast du auch die Möglichkeit, __flash1, __flash2 oder> __flash3 zu verwenden, was auch 16-Bit Zeiger erzeugt; eben im> entsprechenden Segment.
Ja, diese Möglichkeit ist mir bekannt, aber ich möchte die Daten
eigentlich nicht in ein bestimmtes Segment verweisen (außer es geht
nicht anders). Das müsste ich ja dann tun, mittels
> passendem Linker Description File
Bleibt aber die Frage, warum es ohne LTO geht, mit aber nicht.
N. G. schrieb:> Johann L. schrieb:>> Wenn deine Daten nicht in die ersten 64 KiB passten,>> Tun sie nicht, sind bisher 200kB.
Zu beachten ist auch, dass Zeiger immer noch 16 Bits breit sind, d.h.
jegliche zeiger-Arithmetik zu vermeiden ist und stattdessen händische
Adressberechnung angezeigt ist.
> Ich greife generell auf alle PROGMEM-Daten mittels dem _PF, also den> far-pointer-Funktionen zu. Das sollte doch eigentlich immer gehen.
Das war nicht die Frage. Auch der Compiler oder Bibliotheken können
Daten in .progmem erzeugen, und für deren Zugriff wird eben kein _PF
verwandt.
> Bleibt aber die Frage, warum es ohne LTO geht, mit aber nicht.
Möglich ist auch, dass es garnix mit progemem zu tun hat, sondern ein
Bug in deiner Anwendung, der erst durch LTO offengelegt wird. Ums
Debuggen wirst du also schwerlich rumkommen.
Johann L. schrieb:> Zu beachten ist auch, dass Zeiger immer noch 16 Bits breit sind, d.h.> jegliche zeiger-Arithmetik zu vermeiden ist und stattdessen händische> Adressberechnung angezeigt ist.
Das hätte ich jetzt tatsächlich übersehen, aber ich verwende das sowieso
nicht. Aber gut zu wissen und eigentlich sollte es ja klar sein...
Johann L. schrieb:> Auch der Compiler oder Bibliotheken können> Daten in .progmem erzeugen, und für deren Zugriff wird eben kein _PF> verwandt.
Okay, auch wieder klar, aber habe ich vernachlässigt.
Woran erkenne ich denn die Objekte mit dem falschen Zugriff? An der
Objektadresse > 64k?
Johann L. schrieb:> Möglich ist auch, dass es garnix mit progemem zu tun hat, sondern ein> Bug in deiner Anwendung, der erst durch LTO offengelegt wird.
Das ist das woran ich als erstes gedacht habe. Ich vermute generell nie
Fehler beim Compiler, erst wenn es einen seehr begründeten Verdacht
gibt.
Allerdings fallen mir auf Anhieb keine Gründe für ein solches Verhalten
ein.
Aber das einfachste wäre zu Debuggen, wie du schon gesagt hast.
Leider ist mein Board ein Arduino mega ADK Board (wird aber ohne
Arduino-Umgebung mittels Eclipse+Makefile programmiert), und ich muss
erst mal einen Debugger organisieren und irgendwie anschließen (das ist
aber das kleinere Problem).
Danke schon mal für deine Hilfe bis jetzt.
N.G.
>und ich muss>erst mal einen Debugger organisieren und irgendwie anschließen
Du könntest dir auch ein STM32 Discovery Board besorgen.
Bei ARMs gibt es diese nervigen Verrenkungen mit PROGMEM nicht.
SCNR;)
holger schrieb:>>und ich muss>>erst mal einen Debugger organisieren und irgendwie anschließen>> Du könntest dir auch ein STM32 Discovery Board besorgen.
Habe ich, nutzt mir jedoch nichts. Man kann nicht immer einfach das
machen, was einem am liebsten wäre. Und wenn schon ARM, dann eher von
NXP, die finde ich persönlich besser.
> Bei ARMs gibt es diese nervigen Verrenkungen mit PROGMEM nicht.
Nervig finde ich es jetzt nicht, man muss halt wissen was man tut. Und
in dem Fall liegt das "Problem" ja nicht an den getrennten Adressräumen,
sondern an den zu kleinen Pointern (was natürlich auf nem ARM mit 32bit
Pointern auch wieder nicht so ist, ich weiß).
Trotzdem muss ich beim AVR bleiben, schon alleine wegen der Zeit.
Debugger habe ich Privat schon, aber natürlich zur Zeit verliehen. Und
in der Firma habe ich bis jetzt noch keinen gesehen, aber da sind AVRs
(abgesehen von Arduino) eine Seltenheit, ich glaube es gibt hier
(Bootloader sei Dank) nicht mal einen normalen ISP-Programmer.
Ich melde mich dann nächste Woche wieder, wenn das Debuggen brauchbare
Ergebnisse liefert.
N.G. (nicht angemeldet)