Hab vorhin ein Problem mit der Optimierung in gcc 4.0.1 gefunden. Ich
bin nicht ganz klar, ob man es als Bug in gcc oder in avr-libc werten
soll. Ich habe allerdings gesehen, daß jemand es bereits als Bug bei
der avr-libc gemeldet hat.
Die Auswirkungen sind recht "krass".
Also, folgendes Programm:
1 | #define F_CPU 8000000L
|
2 |
|
3 | #include <avr/delay.h>
|
4 | #include <avr/io.h>
|
5 |
|
6 | int main()
|
7 | {
|
8 | DDRB = 0xff;
|
9 |
|
10 | PORTB |= _BV(PB5);
|
11 |
|
12 | _delay_ms(10);
|
13 |
|
14 | PORTB &= !_BV(PB5);
|
15 |
|
16 | // _delay_ms(10);
|
17 | }
|
Compiliert und die Codegröße angezeigt:
$ avr-gcc -Os -mmcu=attiny2313 test.c
$ avr-size
text data bss dec hex filename
120 0 0 120 78 a.out
Jetzt ohne den Kommentar:
1 | #define F_CPU 8000000L
|
2 |
|
3 | #include <avr/delay.h>
|
4 | #include <avr/io.h>
|
5 |
|
6 | int main()
|
7 | {
|
8 | DDRB = 0xff;
|
9 |
|
10 | PORTB |= _BV(PB5);
|
11 |
|
12 | _delay_ms(10);
|
13 |
|
14 | PORTB &= !_BV(PB5);
|
15 |
|
16 | _delay_ms(10);
|
17 | }
|
$ avr-gcc -Os -mmcu=attiny2313 test.c
$ avr-size
text data bss dec hex filename
3610 8 0 3618 e22 a.out
Das Programm ist auf einmal bei weitem zu groß für den Flash-Speicher.
Ich hab mittlerweile rausgefunden, wo der Grund liegt:
Die delay-Funktion ist als _inline_ markiert, welches aber vom
Compiler bei -Os nur dann berücksichtigt wird, wenn die Funktion nur
einmal aufgerufen wird. Bei mehreren Aufrufen versucht er, Platz zu
sparen, indem er das Inlining nicht durchführt. Dadurch können aber die
in der Funktion eingebauten Fließkomma-Operationen nicht mehr im
Compiler, sondern muß zur Laufzeit durchgeführt werden. Deshalb muß
massenweise Code für die Fießkomma-Berechnung gelinkt werden.
Das ist die mit Abstand schlechteste Größen-"Optimierung", die ich je
gesehen hab.
Das Problem kann man lösen, indem man nicht auf Größe optimiert, denn
bei -O3 wird das Inlining immer gemacht.
Alternativ kann man in avr/delay.h alle Vorkommen von _inline_ durch
__attribute__((always_inline)) ersetzen.