Forum: Gesperrte Threads pgm_read_byte_far


von Jens (Gast)


Lesenswert?

Habe viele Konstanten im Programmspeicher abgelegt, es werden nicht alle 
ausgelesen.

a = pgm_read_byte_far(&TabMidiSong6[CounterMidiBytes]);

Diese Zeile wird mit Warnung versehen.

Was muss ich machen damit ich ByteVariablen in Programmspeicher bekomme 
mit extra langer Adresse.

: Verschoben durch Moderator
von Carsten W. (eagle38106)


Lesenswert?

Wie lautet die Warnung?

von Detlef Freckel (Gast)


Lesenswert?

Welcher µC?

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Probier mal
1
a = pgm_read_byte_far(&TabMidiSong6+CounterMidiBytes); 
2
// oder gleich
3
a = pgm_read_byte_far(&TabMidiSong6+CounterMidiBytes++); 
4
// oder
5
uint8_t *MySongPointer = TabMidiSong6;
6
a = pgm_read_byte_far(MySongPointer+CounterMidiBytes++);
Sollte alles funktionieren.

von Jens (Gast)


Lesenswert?

Entschuldigung - vielleicht etwas verwirrend das Beispiel.

ich nutze ein Board mit dem ATMega1280.

Die Zeile könnte auch so sein:
1
a = pgm_read_byte(&TabDaten1[NrByte]);

abgelegt vorher im Programmspeicher
1
 uint8_t TabDaten1[] PROGMEM={3,6,5,1,13, .... usw.};

mit NrByte suche ich mir dann einzelne Bytes raus.

Ich habe soviele Tabellen im Programmspeicher über PROGMEM abgelegt, das 
der uC zu 97% voll ist. Die Daten sind also da. Nur kann ich mit 
prm_read_byte nicht alle abrufen ab der Mitte etwa bekomme ich wieder 
Daten vom Anfang. Es sieht wie ein Überlaufen des Addresspointers aus.

von Stefan E. (sternst)


Lesenswert?

Matthias Sch. schrieb:
> Sollte alles funktionieren.

Nein. Keine der Varianten löst das Problem, dass ein Pointer nur 16-Bit 
hat.

1
#define GET_FAR_ADDRESS(var)                \
2
({                                          \
3
    uint32_t tmp;                           \
4
    __asm__ __volatile__(                   \
5
          "ldi  %A0, lo8(%1)"     "\n\t"    \
6
          "ldi  %B0, hi8(%1)"     "\n\t"    \
7
          "ldi  %C0, hh8(%1)"     "\n\t"    \
8
          "clr  %D0"              "\n\t"    \
9
        : "=d" (tmp)                        \
10
        : "p"  (&(var))                     \
11
    );                                      \
12
    tmp;                                    \
13
})
14
15
16
a = pgm_read_byte_far(GET_FAR_ADDRESS(TabMidiSong6)+CounterMidiBytes);

von Georg G. (df2au)


Lesenswert?

Gib doch bitte mal die Warnung bekannt und poste den Code, der deinen 
Pointer und die Tabellen definiert.

Ein uint32_t als Pointer funktioniert. Vermutlich kastrierst du den 
irgendwo.

von g457 (Gast)


Lesenswert?

> Vermutlich kastrierst du den irgendwo.

Er rechnet in 16Bits, da braucht man nix abzuschneiden dass es nicht 
funktioniert :-)

Wird im Doppelpost-Fred [0] schon diskutiert.

[0] Beitrag "PROGMEM -- liest ab bestimmten Array nicht mehr aus"

von Falk B. (falk)


Lesenswert?

@ Georg G. (df2au)

>Ein uint32_t als Pointer funktioniert. Vermutlich kastrierst du den
>irgendwo.

Eben. Man muss aber aus dem Variablennamen die 32 Bit Adresse ableiten. 
Wenn AVR-GCC aber alles mit 16 Bit Adressen rechnet, weiß der Geier 
warum, wird es problematisch. Darum dieses komische Makro.

Irgendwie hat man den Eindruck, dass der Zugriff jenseits von 64kB beim 
AVR nur drangefrickelt wurde, sowohl in der Hardware als auch Software.

von Falk B. (falk)


Lesenswert?

Was aber vollkommen unverständlich ist, warum in der offizellen DOku 
bzw. in den Includedateien das nicht mal klar dargestellt ist und DORT 
auch das Makro für die 32 Bit Adressermittlung drin ist. Das ist doch 
vollkommen unbrauchbar und inkonsistent?!?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?


Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.