Hallo,
ich beschäftige mich gerade mit den ATxmegas dabei ist mir bei der neuen
API der AVRLibC eine schlechte Optimierung aufgefallen.
Beispiel:
1
SPIE.DATA=0xAA;
Wird zu:
1
LDI R24,0xAA Load immediate
2
LDI R30,0xC0 Load immediate
3
LDI R31,0x0A Load immediate
4
STD Z+3,R24 Store indirect with displacement
Aber warum?
Viel Sinnvoller wäre doch:
1
LDI R24,0xAA Load immediate
2
STS 0x0AC3,R24 Store direct to data space
Die AVRLibC iox128a1.h sieht so aus:
1
#define SPIE (*(SPI_t *) 0x0AC0) /* Serial Peripheral Interface E */
2
3
typedefvolatileuint8_tregister8_t;
4
5
/* Serial Peripheral Interface */
6
typedefstructSPI_struct
7
{
8
register8_tCTRL;/* Control Register */
9
register8_tINTCTRL;/* Interrupt Control Register */
10
register8_tSTATUS;/* Status Register */
11
register8_tDATA;/* Data Register */
12
}SPI_t;
Ich verstehe nicht warum der GCC nicht auf eine statische Adresse
Optimiert. Denn die Adresse ändert sich ja nicht sondern nur der Inhalt.
z.B. bei:
1
SPIE.CTRL=0xBB;
Macht der GCC es richtig und setzt dafür eine statische Adresse ein.
1
LDI R25,0xBB Load immediate
2
STS 0x0AC0,R25 Store direct to data space
Aber bei SPI.INTCTRL, SPI:STATUS ... nicht mehr.
Um das Problem zu lösen muss ich nun immer auf die "alte" API
zurückgreifen. Sprich: SPIE_DATA = 0xAA;
Ich verwende:
Atmel AVR Studio 5
Atmel AVR Toolchain 3.2.3.314
Windows
AVR 8-bits GNU Binutils 2.20.1
AVR 8-bits GNU Compiler Collection (avr-gcc) 4.5.1
AVRLibC 1.7.1
AVR 8-bits GNU Debugger (avr-gdb) 6.7.1
Gibt es dazu einen Patch o.ä.?
Julius F. schrieb:> Um das Problem zu lösen muss ich nun immer auf die "alte" API> zurückgreifen. Sprich: SPIE_DATA = 0xAA;
Bist du beim Speicher tatsächlich so knapp dran, dass diese 2 Bytes zum
echten "Problem" werden?
Ein Motiv für solche Adressierung ist, dass die Basisadresse ggf.
mehrfach verwendet werden kann, wenn auf benachbarte Register ebenfalls
zugegriffen wird. Das ist freilich bei AVRs aufgrund deren Knappheit an
Adressregistern seltener möglich als bei anderen Architekturen.
>Bist du beim Speicher tatsächlich so knapp dran, dass diese 2 Bytes zum>echten "Problem" werden?
Es geht mir nicht um die 2Byte Codegröße sondern um die Geschwindigkeit.
Immerhin sind es 2Takte mehr pro aufruf. Und das ganze beschränkt sich
ja nicht nur auf die SPI Struct sondern auf alle Bereiche.
Es macht einen unterschied ob ich einen Pin in 2Takten oder in 4Takten
Toggeln kann.
Yep, unschön, insbesondere weil die relative Adressierung an Stelle des
STS hier tatsächlich sinnvoll wäre, wenn Z für alle 4
Lade/Speicher-Operationen nur einmal geladen würde.
Rechne aber lieber nicht damit, dass sich das in absehbarer Zeit ändert,
denn fehlende Optimierung auf AVR in einem minder schweren Fall hat
vmtl. nicht grad hohe Priorität bei den Entwicklern.
Und wo hast du den Assembler-Code her? Vielleicht irgendwo aus dem
AVR-Studio-5-Debugger? Ist dir klar, dass das Studio5 den Debug-Build
mit -O0 übersetzt?
> Und wo hast du den Assembler-Code her? Vielleicht irgendwo aus dem> AVR-Studio-5-Debugger? Ist dir klar, dass das Studio5 den Debug-Build> mit -O0 übersetzt?
Ja aus dem AVR-Studio 5 Disassembler bzw. der *.lss Datei aber ich glaub
nicht der er mir -O0 Code anzeigt denn wenn ich den Code mit -Os oder
-O3 übersetzte kommt auch ein anderer ASM Code dabei raus.
habe nun meine #define geändert:
1
#define SPI_SEND(modul, data) while(!(modul.STATUS & SPI_IF_bm)){}; modul.DATA = data
in
1
#define SPI_SEND(modul, data) while(!(modul##_STATUS & SPI_IF_bm)){}; modul##_DATA = data
Diese 4.5.1 ist eine von Atmel gepatchte Version des Compilers, d.h. der
entsprechende Bug-Report gehört nach atmel.com.
Auf einem "suberen" avr-gcc lässt sich dies nicht übersetzten und damit
auch nicht nachvollziehen.
Mit einer angepassten Quelle sehe ich das auch mit 4.3, 4.5 und 4.6.
1
typedefstruct
2
{
3
volatileunsignedchara,b,c,d;
4
}SPI_t;
5
6
#define SPIE (*(SPI_t*) 0x0AC0)
7
8
voidfoo(void)
9
{
10
SPIE.d=0xAA;
11
while(!(SPIE.c&0x80));
12
13
SPIE.d=0xBB;
14
while(!(SPIE.c&0x80));
15
}
Wenn du magst, kannst du einen Bug-Report bei GCC machen. Da es nur ein
Optimierungsproblem ist, wird das frühestens in 4.7 behoben — zumindest
im GCC und falls es in 4.7 noch besteht. Oder du musst eben selber
Patches machen, besorgen oder zurückportieren, sobald es in 4.7/4.8
behoben ist.
Mit 4.7 habe ich es noch nicht getestet, und ich kann auch (noch) nicht
sagen, ob es am AVR-Teil hängt oder nicht.
> Diese 4.5.1 ist eine von Atmel gepatchte Version des Compilers, d.h. der> entsprechende Bug-Report gehört nach atmel.com.> Auf einem "suberen" avr-gcc lässt sich dies nicht übersetzten und damit> auch nicht nachvollziehen.
Mit WinAVR 20100110 besteht das Problem auch.
Werde gleich mal aufm Linux System einen "sauberen" avr-gcc compilieren
mal gucken wie es dort aussieht.
> Wenn du magst, kannst du einen Bug-Report bei GCC machen.
Mein Schrift-Englisch ist jetzt nicht so gut das ich es machen würde.
Ich würde mich freuen wenn einer von euch es dort Posten könnte.
> Eigentlich gehört das ins GCC-Forum.
Ja, richtig. Hab es leider aus Reflex / Gewohnheit hier gepostet. Ein
Mod könnte es ja verschieben.
Julius F. schrieb:>> Wenn du magst, kannst du einen Bug-Report bei GCC machen.>> Mein Schrift-Englisch ist jetzt nicht so gut das ich es machen würde.> Ich würde mich freuen wenn einer von euch es dort Posten könnte.
Ist PR50448.