mikrocontroller.net

Forum: Compiler & IDEs Strings im oberen Flash-Bereich (> 64K)


Autor: Günter R. (galileo14)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
        ldi r22,lo8(c.1607)
        ldi r23,hi8(c.1607)
        clr r24
        sbrc r23,7
        com r24
        mov r25,r24
        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.

Autor: Günter R. (galileo14)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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)));
//----------------------------------------------------------
// Macros to access strings defined in PROGMEM above 64kB
//----------------------------------------------------------
#define FAR(var)                                      \
({                                                    \
    uint_farptr_t tmp;                                \
                                                      \
    __asm__ __volatile__(                             \
                                                      \
            "ldi    %A0, lo8(%1)"           "\n\t"    \
            "ldi    %B0, hi8(%1)"           "\n\t"    \
            "ldi    %C0, hh8(%1)"           "\n\t"    \
            "clr    %D0"                    "\n\t"    \
        :                                             \
            "=d" (tmp)                                \
        :                                             \
            "p"  (&(var))                             \
    );                                                \
    tmp;                                              \
})


Autor: Günter R. (galileo14)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mag das vielleicht mal jemand als offiziellen Patch für avr-libc
einreichen?

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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)

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.