Hallo GccNewbiee
PROGMEM Strukturen sind immer "const", da sich die Daten nicht wirklich
im Arbeitsspeicher sondern lediglich im Flash befinden.
Eine Pointeroperation (Adressaufloesung) mittels "&variablenname"
liefert zwar einen gültigen Pointer, aber dessen Adresse hat nichts mit
den Daten im RAM zu tun und könnte sogar höher sein, als der RAM selbst
groß ist.
(Damit wird um die C-Philosophie: "alles in einen Speicher"
herumgewerkelt.)
Ein Zugriff auf die Daten ist daher nur mit speziellen AVR-libc
Funktionen möglich:
http://nongnu.org/avr-libc/user-manual/pgmspace.html
Wenn du mit den PGM Funktionen arbeiten willst, nutze in deinem Code
bitte das Makro "FLASHEND" um zwischen den FAR und NEAR Version zu
switchen.
Ein Beispiel aus dem Updater des USBaspLoaders (
https://github.com/baerwolf/USBaspLoader/blob/master/updater/updater.c
):
1 | #if (FLASHEND > 65535)
|
2 | a=pgm_read_word_far((void*)&new_firmware[i]);
|
3 | b=pgm_read_word_far(NEW_BOOTLOADER_ADDRESS+i);
|
4 | #else
|
5 | a=pgm_read_word((void*)&new_firmware[i]);
|
6 | b=pgm_read_word(NEW_BOOTLOADER_ADDRESS+i);
|
7 | #endif
|
"new_firmware" ist dabei:
1 | extern const uint16_t usbasploader[SIZEOF_new_firmware>>1] PROGMEM;
|
2 | const uint8_t *new_firmware = (void*)&usbasploader;
|
Der Pointer den C liefert, müsste immer als 32Bit verwendbar sein, aber
nach " http://nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html
" benutzt du dann wahlweise short oder long als Adresse im Flash selbst.
Wo dann deine Firmware im speziellen gelinkt ist, ist egal, da von
überall auf überall im Flash gelesen werden kann.
(Insofern du die FAR Funktionen bei Flash > 64KB verwendest. Immer FAR
verwenden funktioniert aber nicht, das AVRs mit weniger als 64K diese
FAR Funktionen ggf. nicht anbieten...)
MfG