Wenn man für einen ATmega128 einen Bootloader programmiert und dieser soll etwas am LCD-Display anzeigen, so müssen die Strings ja im oberen 64K-Flashbereich liegen; die normalen "_p"-Funktionen sind dann ja nicht anwendbar, bzw. Konstrukte der Art "PutTextOnLCD(PSTR("blablah"));", da ja schon das PSTR-Makro nur bis 64K geht. Ich hatte vor längerer Zeit lange herumgebastelt, um dafür eine Lösung zu finden, und ich fand folgendes heraus: #define PSTRX(s) (__extension__({static const char c[] PROGMEM = (s); (uint32_t)(c);})) void PutTextOnLCD(uint32_t s) { char cc; ... cc=pgm_read_byte_far(s); .. } // Verwendung: PutTextOnLCD(PSTRX("Hallo!")); Ich hatte also ein eigenes PSTR-Makro gebastelt, das hier PSTRX ("X" für "eXtended") heißt. PSTR und PSTRX machen ja nichts anderes, als daß sie einen String unter einem nach außen unbekannten Namen im Flash ablegen und dessen Adresse abliefern. Diese Lösung habe ich jahrelang unter einer 2006er WinAVR-Version problemlos (und warnungslos) angewandt. Als ich kürzlich auf WinAVR-20090313 umgestiegen bin, kommen jetzt plötzlich Warnungen der Art "cast from pointer to integer of different size" die sich auf das PSTRX-Makro beziehen. Das Programm funktioniert durchaus, aber die Warnung stört mich, und sie zeigt auch, daß der Compiler nicht ganz zufrieden ist. Hat jemand eine Idee, wo man drehen müßte? Oder wie man das ganze anders (aber ebenso elegant) löst? Günter
Günter R. wrote:
> Hat jemand eine Idee, wo man drehen müßte?
Nö, auf Anhieb nicht. Aber bist du dir sicher, dass das wirklich
funktioniert? Wenn ich das compiliere, dann generiert er
mir:
1 | ldi r22,lo8(c.1607) |
2 | ldi r23,hi8(c.1607) |
3 | clr r24 |
4 | sbrc r23,7 |
5 | com r24 |
6 | mov r25,r24 |
7 | call PutTextOnLCD |
c.1607 ist dabei der Label für das anonyme String-Objekt. Es ist gut zu sehen, dass nur dessen untere 16 bits benutzt werden, während die oberen 16 bits vorzeichenerweitert aus den unteren als 0 oder 0xffff eingefügt werden. Das ist sicher nicht das, was du wolltest.
Hallo Jörg, kenne mich im AVR-Assembler nicht so aus (nach 8080/Z80/8051/TLCS-900 habe ich Assembler nicht "weitergepflegt - wäre aber wohl doch nützlich :|). Trotzdem habe ich in meinem Listing genau die Assembler-Folge gefunden, die Du oben hingeschrieben hast. Es ist also wohl so, daß der Adressoperator nur 16 Bits weitergibt? Und daß durch den uint32_t-Cast wohl 0xffff auf die oberen Adressen erweitert wird? Dadurch würde das Programm funktionieren, wenn auch vielleicht nur "zufällig" (soetwas ist immer schlecht, das weiß ich, und geht mir auch immer gegen den Strich). Die Methode erfordert, daß man 32-Bit-Adressen bekommt. Kann man dann möglicherweise in AVR-C gar keine 32-Bit-Adressen eines Datenobjekts ermitteln (Datenobjekte, die im Flash liegen, somit natürlich in einem anderen Adreßraum)? Günter
Ich hatte da einst ein Makro verwendet, um eine 24-Bit Addresse (bzw 32 Bit) von einem progmem Pointer zu erhalten. Eventell hilft Dir dieses makro weiter... Beispiel: UART_puts_PF(FAR(*PSTR(pgmemstr)));
1 | //----------------------------------------------------------
|
2 | // Macros to access strings defined in PROGMEM above 64kB
|
3 | //----------------------------------------------------------
|
4 | #define FAR(var) \
|
5 | ({ \
|
6 | uint_farptr_t tmp; \
|
7 | \
|
8 | __asm__ __volatile__( \
|
9 | \
|
10 | "ldi %A0, lo8(%1)" "\n\t" \
|
11 | "ldi %B0, hi8(%1)" "\n\t" \
|
12 | "ldi %C0, hh8(%1)" "\n\t" \
|
13 | "clr %D0" "\n\t" \
|
14 | : \
|
15 | "=d" (tmp) \
|
16 | : \
|
17 | "p" (&(var)) \
|
18 | ); \
|
19 | tmp; \
|
20 | })
|
Hallo, Peter, Dein Makro sieht sehr gut aus, funktioniert perfekt, und spart noch Platz gegenüber meiner ursprünglichen (unperfekten) Lösung. Vielen Dank! Gruß, Günter
Mag das vielleicht mal jemand als offiziellen Patch für avr-libc einreichen?
Gern geschehen, es freut mich, dass das Makro auch noch mit aktuellem AvrGcc funktioniert. @Jörg: Ich will mich da nicht mit fremden Lorbeeren schmücken, ich hatt das Makro einst ebenfalls in einem Forum erhalten. Ist aber schon 3 Jahre her und ich weiss nicht mehr woher. Ich habe seinerseits vorgeschlagen das Makro in die avrlibc aufzunehmen "pgmspace.h" oder direkt auf geeignete Weise in die xyz_P() Funktionen zu integrieren, stiess aber damals auf kein "Gehöhr". Das Problem taucht aber immer wieder in den Foren auf. Ich weiss nicht, wie und wo man sowas als offiziellen Patch oder Erweiterung einreichen kann, aber ich denke das ganze ist bei Dir, als "Vater" der avrlibc gut aufgehoben... ;o)
Peter wrote: > Ich weiss nicht, wie und wo man sowas als offiziellen Patch oder > Erweiterung einreichen kann, https://savannah.nongnu.org/patch/?group=avr-libc Je einfacher es zu integrieren ist (Patch als Ausgabe von diff -u zwischen alter und neuer Datei liefern, Dokumentation nicht vergessen -- kann man per copy&paste von den existierenden Einträgen nehmen), um so größer ist die Chance, dass es beim nächsten Release berücksichtigt werden kann. Ich habe für die Vorbereitung eines Releases immer einen endlichen Zeitfonds, in dem kann ich entweder dann z. B. einen Patch integrieren, der mich 4 Stunden kostet (die sind mit allen Tests schnell zusammen) oder 8 Patches, die mich eine halbe Stunde jeweils kosten. > aber ich denke das ganze ist bei Dir, als > "Vater" der avrlibc gut aufgehoben... ;o) Nein, er ist noch nicht ,,bei mir''. Dafür muss er in einem Patchtracker landen (d. h. bei obiger URL eingereicht sein). Ich kann beim nächsten Release unmöglich noch alle Forums-Diskussionen des letzten halben Jahres durchsehen (nach welchem Stichwort denn überhaupt?) nach irgendwelchen Vorschlägen. Das ist kein Unwillen oder gar Desinteresse, aber anders lässt sich das nicht organisieren.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.