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
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.
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.
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); |
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.
> 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"
@ 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.
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?!?