Per Zufall habe ich entdeckt, daß WinAVR 2 gleichwertige Codierungsmöglichkeiten völlig unterschiedlich übersetzt. Hier das Testbeispiel: union hPuffer { uint8_t Ges[12]; struct { uint8_t Feld1[6]; uint8_t Feld2[6]; }; } Puffer; uint8_t Erg[12]; void main (void) { for (uint8_t i=0; i<6; i++) { Erg[i] = Puffer.Ges[6+i]; // Version a) 112Byte // Erg[i] = Puffer.Feld2[i]; // Version b) 140Byte } } Bei Version a) wird auf den Puffer mit dem Offset 6 direkt zugegriffen, bei Version b) muß der Compiler den Offset aus der union berechnet. Die Ergebnisse sind total unterschiedlich: Version a) 56: e6 e0 ldi r30, 0x06 ; 6 58: f1 e0 ldi r31, 0x01 ; 1 5a: ac e0 ldi r26, 0x0C ; 12 5c: b1 e0 ldi r27, 0x01 ; 1 for (uint8_t i=0; i<6; i++) { Erg[i] = Puffer.Ges[8+i]; // -> 112Byte 5e: 81 91 ld r24, Z+ 60: 8d 93 st X+, r24 62: 81 e0 ldi r24, 0x01 ; 1 64: ec 30 cpi r30, 0x0C ; 12 66: f8 07 cpc r31, r24 68: d1 f7 brne .-12 ; 0x5e <main+0x8> Version b) for (uint8_t i=0; i<6; i++) { // Erg[i] = Puffer.Ges[8+i]; // -> 112Byte Erg[i] = Puffer.Feld2[i]; // -> 140Byte 56: 80 91 06 01 lds r24, 0x0106 ; -> Puffer+6 5a: 80 93 0c 01 sts 0x010C, r24 ; -> Erg 5e: 80 91 07 01 lds r24, 0x0107 ; -> Puffer+7 62: 80 93 0d 01 sts 0x010D, r24 ; -> Erg+1 66: 80 91 08 01 lds r24, 0x0108 ; -> Puffer+8 6a: 80 93 0e 01 sts 0x010E, r24 ; -> Erg+2 6e: 80 91 09 01 lds r24, 0x0109 ; -> Puffer+9 72: 80 93 0f 01 sts 0x010F, r24 ; -> Erg+3 76: 80 91 0a 01 lds r24, 0x010A ; -> Puffer+10 7a: 80 93 10 01 sts 0x0110, r24 ; -> Erg+4 7e: 80 91 0b 01 lds r24, 0x010B ; -> Puffer+11 82: 80 93 11 01 sts 0x0111, r24 ; -> Erg+5 } Getestet mit ATMEGA88 und WinAVR-20100110 mit folgenden Optionen: ## Compile options common for all C compilation units. CFLAGS += -Wall -gdwarf-2 -Os -DF_CPU=8000000UL CFLAGS += -std=gnu99 -fno-inline-small-functions -Wno-main Gibt es einen Grund, warum Version b) ineffizenter übersetzt wird - obwohl es eigentlicher eleganter ist - , und gibt es Regeln, damit solche Dinge vermieden werden können? Harald
.. eben nicht. Es geht nur in 2. Linie um effizienten Code. Mir ist wichtiger, daß das Programm übersichtlicher ist. Ein C-Programm ist nun 'mal leichter verständlich als Assembler. Trotzdem wüßte ich in diesem Fall mehr über Hintergründe. Am besten ist natürlich leicht verständlicher (soweit mit C möglich) und kompakter Code.
Harald P. schrieb: > Gibt es einen Grund, warum Version b) ineffizenter übersetzt wird - Ich vermute mal, dass der Compiler hier die Schleife ausrollt (unroll loop), weil er bei allen Indizes erkennt, dass sie konstant sind. Compilier doch mal mit -O2 und/oder mit -fno-unroll-loops, was macht der Compiler dann draus? Warum das so ist - keine Ahnung, interessiert mich auch nicht wirklich(tm). ;o)
Harald P. schrieb: > Gibt es einen Grund, warum Version b) ineffizenter übersetzt wird - Ineffizienter in welcher Hinsicht? Version b ist deutlich schneller.
Harald P. schrieb: > Gibt es einen Grund, warum Version b) ineffizenter übersetzt wird - > obwohl es eigentlicher eleganter ist - , Das scheint ein "Feature" von GCC 4.4.x zu sein. GCC 4.5.4, 4.6.3 und 4.7.2 liefern für beide Fälle jeweils den gleichen Code: Mit -Os oder -O2 wird beidesmal eine Schleife erzeugt, mit -O3 wird die Schleife in sechs einzelne Kopieraktionen ungerollt, also genau so wie man es erwartet (-O3 beeinhaltet -funroll-loops, -O2 und -Os nicht). > und gibt es Regeln, damit solche Dinge vermieden werden können? Date doch einfach mal den Compiler auf eine etwas jüngere Version up :)
Hier kann man sich den 4.7.2 laden: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=115337 Peter
Peter Dannegger schrieb: Ein Link zu avr-gcc 4.7.2 für Windows und eine kurze Beschreibung wird gegeben in fer avr-gcc Mailing-Liste [1]: http://lists.gnu.org/archive/html/avr-gcc-list/2012-09/msg00024.html [1] https://lists.gnu.org/mailman/listinfo/avr-gcc-list
Vielen Dank für eure Hilfe! avr-gcc 4.7.2 kann ich jetzt benutzen, nachdem ich mein Programm umgestellt habe: prog_* entfernt, zusätzliche casts, um lästige Warnungen verschwinden zu lassen... Seltsamerweise funktioniert das damit übersetzte Programm nicht mehr im Debugger des AVR-Studios V4.18. AVR-Studio stürtzt beim Laden ab (unbekannter SW-Fehler ..). Schade, mit dem Simulatur des Studios bin ich gut klar gekommen. Harald
Welches Debug-Format unterstützt dieser Debugger denn, und welches läst du erzeugen?
Es sind die Standard-Optionen, die über Studio eingestellt werden: ## General Flags PROJECT = AnzD640 MCU = atmega32 TARGET = AnzD640.elf CC = avr-gcc CPP = avr-g++ ## Options common to compile, link and assembly rules COMMON = -mmcu=$(MCU) ## Compile options common for all C compilation units. CFLAGS = $(COMMON) CFLAGS += -Wall -gdwarf-2 -std=gnu99 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d also dwarf-2. Wechsele ich den Compiler (geht ruck-zuck mittels junction-Befehl, wie hier früher mal beschrieben wurde), dann funktioniert das Debugging. Eben noch einmal probiert. Der Fehler ist reproduzierbar. Die Options sind gleich geblieben.
Harald P. schrieb: > CFLAGS += -Wall -gdwarf-2 -std=gnu99 > also dwarf-2. Nö. Dwarf-2 mit GNU-spezifischen Erweiterungen. Dwarf-2 ist -gdwarf-2 -gstrict-dwarf, was hier vermutlich nicht hilft, denn... > Wechsele ich den Compiler [...] dann funktioniert das Debugging. ...AFAIK scannt der Atmel-Debugger Instruktionssequenzen anstatt Debug-Information zum Erkennung von CFI-Info etc. zu bekommen. Heisst konkret: Sobald der Compiler auch nur ein einzige unerwartete Instruktion ausgibt oder die Abfolge der Instruktionen ändert, ist dieser Debugger verwirrt; egal wie vollständig oder korrekt die erzeugte Debug-Info des Compilers auch sein mag. Evtl. einen Debugger verwenden, der tatsächlich in der Lage ist, Debug-Informationen auszuwerten anstatt hartcodierte Instruktionssequenzen abzuscannen und bei der kleinsten Abweichung abschmiert. Bei der Entwicklung der Tools (GCC, Binutils, GDB, ...) geht es darum, die Tools weiter zu entwickeln. Wenn ein Debugger-Hersteller da irgendwelche Hacks in seine Software einbaut, die nirgends spezifiziert sind, und damit riskiert, daß seine Software bei der kleinsten Änderung nicht mehr tut — sorry, ich werd mich um solche Sonderlocken nicht kümmern, und ich wüsste auch keinen anderen GCC-Entwickler, der das tut oder unterstützen würde. Falls der Atmel-Debugger sich einzig auf Debug-Info verlässt und keine solchen Scans gegen bestimmte Instruktionssequenzen veranstaltet, lasse ich mich gerne eines Besseren belehren.
.. perfekt. Die Option -gstrict-dwarf (wohl nur erlaubt für die neueren Compiler-Versionen) sorgt dafür, daß der Atmel-Debugger nicht mehr abstürzt. Vielen Dank an die Spezialisten, die hier im Forum mitarbeiten. PS: in der Version 4.7.2 (mit mingw) kennt avr-size nicht die für AVR nützliche Option C. Man kann aber einfach ein älteres avr-size in das entsprechende Verzeichnis kopieren.
Harald P. schrieb: > .. perfekt. Die Option -gstrict-dwarf (wohl nur erlaubt für die neueren > Compiler-Versionen) sorgt dafür, daß der Atmel-Debugger nicht mehr > abstürzt. Diese Option gibt es in allen supporteten Versionen von GCC und sogar schon in der 4.5, d.h. seit 2 1/2 Jahren. Schafft der Debugger auch dwarf-3 oder gar dwarf-4? > in der Version 4.7.2 (mit mingw) kennt avr-size nicht die für AVR > nützliche Option C. Falls es um die o.g. http://lists.gnu.org/archive/html/avr-gcc-list/2012-09/msg00024.html geht: das steht im Fineprint: >> The package contains no extra patches [...]
Mit dwarf-3 (mit oder ohne -gstrict-dwarf) läuft der Debugger, eben ausprobiert. Aber das Debugging geht nicht auf Source-Code Ebene, ist also (fast) unbrauchbar. Mit dwarf-4 (mit oder ohne -gstrict-dwarf) stürzt der Debugger ab.
Hallo zusammen, da ich gerade beim Debuggen mit AS6 ICE3 & MKII eine Verzweifelung nach der nächsten bekommen schaue ich mir gerade die Alternativen an. Ich habe versucht herauszubekommen, was DARF-2, 3 und 4 unterscheidet. Von letzterem habe ich nur gelesen, dass man GDB 7.0 benötigt. Kennt irgendwer Details? Ciao Knut
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.