Stringmaster Flash schrieb:
> Ich beschäftige mich derzeit mit AVRs und und dem avr-gcc. Soweit
> funktioniert auch alles, ich frage mich jedoch wann es Sinn macht
> Strings im Flash abzulegen (so wie im Tutorial beschrieben).
Dazu wurde ja schon einiges geschrieben.  Der Grund dafür, read-only 
Daten (.rodata) im RAM abzulegen und nicht im Flash, ist, dass man bei
| 1 | char readc (const char *c)
 | 
| 2 | {
 | 
| 3 |     return c;
 | 
| 4 | }
 | 
Nicht weiß, ob ausm RAM per LD oder ausm Flash per LPM gelesen werden 
muss.  readc kann nämlich auch für veränderliche Daten aufgerufen 
werden.  Das const char* sagt ja nur, dass diese Funktion *c nicht 
ändert.
Manche neuere AVR-Derivate wie ATtiny40 (Reduced Tiny -mmcu=avrtiny) und 
ATtiny1616 etc. (-mmcu=avrxmega3) haben einen linearen Adressraum, wo 
das Flash im RAM-Adressbereich sichbar ist.  Auf diesen Devices kann man 
auf __flash und PROGMEM / PSTR etc. ohne Overhead verzichten.
| 1 | const int i = 2;
 | 
| 2 | 
 | 
| 3 | __attribute((noinline,noclone))
 | 
| 4 | int readi (const int *pi)
 | 
| 5 | {
 | 
| 6 |     return *pi;
 | 
| 7 | }
 | 
| 8 | 
 | 
| 9 | int main (void)
 | 
| 10 | {
 | 
| 11 |     return readi (&i);
 | 
| 12 | }
 | 
 
Zunächst für ein "normales" Device mit .rodata im RAM:
 
| 1 | $ avr-gcc  foo.c -o foo.elf -mmcu=attiny25 -Os -save-temps -Wl,-Map,foo.map
 | 
| 2 | $ avr-objdump -d foo.elf
 | 
 
| 1 | Disassembly of section .text:
 | 
| 2 | ...
 | 
| 3 | 
 | 
| 4 | 00000042 <readi>:
 | 
| 5 |   42:  fc 01         movw  r30, r24
 | 
| 6 |   44:  80 81         ld  r24, Z
 | 
| 7 |   46:  91 81         ldd  r25, Z+1
 | 
| 8 |   48:  08 95         ret
 | 
| 9 | 
 | 
| 10 | 0000004a <main>:
 | 
| 11 |   4a:  80 e6         ldi  r24, 0x60
 | 
| 12 |   4c:  90 e0         ldi  r25, 0x00
 | 
| 13 |   4e:  f9 cf         rjmp  .-14       ; 0x42 <readi>
 | 
 
i liegt also an Adresse 0x60, das ist die erste RAM-Adresse des 
ATtiny25.  Im Flash liegt i an Adresse 0x54 (direkt nach dem Code), und 
der Startup-Code kopiert es an RAM-Adresse 0x60.
 
| 1 | .data           0x00800060        0x2 load address 0x00000054
 | 
| 2 | ...
 | 
| 3 |  .rodata        0x00800060        0x2 foo.o
 | 
| 4 |                 0x00800060                i
 | 
| 5 | ...
 | 
| 6 |                 0x00000054                __data_load_start = LOADADDR (.data)
 | 
| 7 |                 0x00000056                __data_load_end = (__data_load_start + SIZEOF (.data))
 | 
 
Das gleiche Programm compilert für einen ATtiny40:
 
| 1 | $ avr-gcc  foo.c -o foo.elf -mmcu=attiny40 -Os -save-temps -Wl,-Map,foo.map
 | 
| 2 | $ avr-objdump -d foo.elf
 | 
 
| 1 | Disassembly of section .text:
 | 
| 2 | ...
 | 
| 3 | 
 | 
| 4 | 00000040 <main>:
 | 
| 5 |   40:  8a e4         ldi  r24, 0x4A
 | 
| 6 |   42:  90 e4         ldi  r25, 0x40
 | 
| 7 |   44:  f8 cf         rjmp  .-16       ; 0x36 <readi>
 | 
 
| 1 | .rodata         0x0000404a        0x2 load address 0x0000004a
 | 
| 2 |  .rodata        0x0000404a        0x2 foo.o
 | 
| 3 |                 0x0000404a                i
 | 
| 4 | ...
 | 
| 5 | .data           0x00800040        0x0 load address 0x0000004c
 | 
| 6 | ...
 | 
| 7 |                 0x0000004c                __data_load_start = LOADADDR (.data)
 | 
| 8 |                 0x0000004c                __data_load_end = (__data_load_start + SIZEOF (.data))
 | 
 
Hier liegt i an Flash-Adresse 0x4a, was per RAM-Adresse 0x404a 
zugegriffen wird.  Das RAM beginnt bei 0x40, enthält hier aber keine 
Daten.  Wenn es welche hätte, würde es vom Startup-Code mit Flash-Daten 
ab 0x4c initialisiert werden.