Hallo Leute, hab als µc-Anfänger zur Nutzung von AVRStudio4 mal folgende Frage: Man kann, um die Codegröße zu optimieren, ja bei AVRSudio4 verschiedene Level einstellen. z.B. 00, -01, -02 usw. Kann man die in jedem Falle nutzen, um die Codegröße zu optimieren, oder kann dies auch zu Verwurstelungen führen, so das ein Programm, was im 0-Level läuft, z.B. im Level -03 nicht mehr richtig funktioniert ? Ich möchte diesbezüglich gern wissen, ob es Sinn macht, diese Optimierungsstufen einzusetzen oder besser nicht. Besten Dank entsprechende Tipps !! Mit freundlichen Grüßen J.M.
Zum kleinermachen kannst du nur -Os nehmen. Besonders -O2 erzeugt gern größeren Code, der aber schneller ist. Funktionieren wird das Programm auch mit allen Optimierungsstufen gleich, nur halt entsprechend schneller (falls keine Bugs drin sind). Manche böse Bugs treten aber z.B. erst bei -O2 zutage.
> ...so das ein Programm, was im 0-Level läuft, z.B. im Level -03 > nicht mehr richtig funktioniert? Ja, natürlich. Es gibt hinreichend Beispiele für ,,vergurkte'' Programme, die mit -O0 dann trotzdem noch funktionieren, obwohl sie eigentlich kaputt sind. Prominentestes Beispiel dafür sind natürlich vergessene volatile-Qualifier an Variablen, die in verschiedenen Codethreads (also z. B. main und Interrupt) wechselseitig benutzt werden. Andererseits kann bei zeitkritischen Dingen genau das Gegenteil eintreten: diese funktionieren nur mit mindestens -O1 vernünftig, weil der mit -O0 generierte Code so aufgeblasen und umständlich ist (eben eine geradlinige 1:1-Umsetzung des hingeschriebenen C-Codes), dass alle Messen für eine vernünftige Ausführungszeit gesungen sind. Meistens ist -Os das ,Optimum', bei dem sowohl geringe Codegröße als auch kurze Ausführungszeiten erreicht werden. Allerdings haben wir mal in einem Projekt Zeitwerte gemessen, -O3 hat bei ca. 10 % größerem Code dann auch nochmal ca. 10 % Zeiteinsparung im kritischen Pfad gebracht. Da man letztlich den gesamten ROM des gewählten Prozessors kaufen muss und keinen Bonus dafür erhält, wenn man einen Teil des ROMs nicht benutzt, kann das also am Ende schon eine Option sein.
Hi, also ich hab mit O0 schlechte Erfahrungen. Teilweise fehlerhafter Code. Keine Ahnung, ob das behoben wurde: http://www.mikrocontroller.net/forum/read-4-243641.html#265139
> also ich hab mit O0 schlechte Erfahrungen. Teilweise fehlerhafter > Code. Das ist eine Behauptung, deren Beweis du schuldig geblieben bist.
> also ich hab mit O0 schlechte Erfahrungen. Teilweise fehlerhafter > Code. Oja, ich hab auch schon viele Compilerfehler entdeckt! Nach einigem debuggen kam immer wieder raus, dass der Fehler in der Funktion read_keyboard() des Editors steckte! :-) SCNR
Okay. Witzig. Ich hab mal ein wenig gebuddelt. Hier mal ein Teil aus der S65-Library (um die ging es bei meinem Verweiß): O0: // setup SPI Interface SPCR = _BV(MSTR) | _BV(SPE) | _BV(SPR0); 272: 81 e5 ldi r24, 0x51 ; 81 274: 80 93 2d 00 sts 0x002D, r24 O3: // setup SPI Interface SPCR = _BV(MSTR) | _BV(SPE) | _BV(SPR0); 188: 81 e5 ldi r24, 0x51 ; 81 18a: 8d b9 out 0x0d, r24 ; 13 Fällts auf? BTW: Die GCC-Entwickler empfehlen selbst O0 nicht einzusetzen. Den Beitrag werd ich auch mal suchen. Grüße, Freakazoid
Und, was ist daran falsch :-) Der 'Port' ist auf 2 Wegen erreichbar. Entweder wird er als I/O Port angesprochen, dann liegt er auf I/O Port 0D. Oder aber er wird memory mapped angesprochen, dann liegt er auf Adresse 2D.
Ist er das wirklich? Bei mir ging es nicht ;-( Es kann natürlich trotzdem sein, daß mein Fehler noch woanders lag (siehe Tip von Fritz Ganter). Ich denke schon, daß der GCC da okay ist (hab mich wohl oben ein wenig zu undeutlich ausgedrückt). Fakt ist aber, daß das Programm erst mit O2 lief. Es gab keine Zeitschleifen oder sonstwie optimierungsabhängige Teile. Das mit dem 2-Wege-Port les ich mal nach. Übrigens: In einem anderen Forum wurde das so hingenommen. Ich finde es gut, daß mich mal jemand auf die '2 Wege' aufmerksam macht. Hätte man zwar auch selbst vermuten können, aber ich hab wohl ein wenig zu schnell die Flinte ins Korn geworfen. Wenn dem wirklich so ist, ist mein Vertrauen wieder da. Dachte schon ich müßte die ganze Zeit in Assembler programmieren ;-) Grüße, AK
Sehe auch kein Problem in dem O0-Code. sts erzeugt größeren und langsameren Code als out, klar: nicht optimiert ... Statt Dich still zu ärgern, melde doch beim nächsten Mal den "Bug" auf sourceforge. Entweder es war wirklich ein Bug: dann haben alle was davon, oder es war keiner: dann bekommst Du dort sicher die kompetenteste Antwort. Gruß, Stefan
Naja. Andersrum hätt ich auch mal besser debuggen können. Stattdessen hab ich lieber wieder auf Assembler gesetzt. Naja. War letztes Jahr. Jetzt mach ich ein paar Sachen besser.
Und hier die '5-Wege-Adressierung: ... The five different addressing modes for the Data memory cover: Direct, Indirect with Displacement, Indirect, Indirect with Pre-decrement, and Indirect with Post-increment. In the Register File, registers R26 to R31 feature the indirect addressing pointer registers. ... ... The 32 general purpose working registers, 64 I/O Registers, and the 64 bytes of internal data SRAM in the ATtiny13 are all accessible through all these addressing modes. The Register File is described in General Purpose Register File on page 8. ...
>> Der 'Port' ist auf 2 Wegen erreichbar. > Ist er das wirklich? Die MMIO-Zugriffe (memory-mapped IO) sind der einzige Weg, mit dem es garantiert ist, dass man alle IO-Ports erreichen kann. Je nach Prozessor ist nur ein Teil davon (nämlich die unteren 64 -- von vielleicht insgesamt 224 beim ATmega1280) via IN und OUT erreichbar, und wiederum davon kann nur die Hälfte davon (die ersten 32) auch mit SBI und CBI manipuliert werden. Daher arbeitet der Compiler intern erst einmal einheitlich mit MMIO. Der Optimierer erkennt dann daraus die Fälle (statische Portadressen im passenden Bereich, ggf. statische Bit-Nummern für Manipulation), in denen man statt des umständlichen MMIO mit kürzeren Befehlssequenzen auskommt.
Es ist immer wieder lustig, wieviele meinen der Compiler würde Müll machen. Dabei kann man ganz locker davon ausgehen, dass der Fehler in 99,99% der Fälle beim Compiler-Benutzer liegt und nicht beim Compiler. Der durchschnittliche Programmierer schreibt nur durschnittlichen Code der den Compiler auch nur vor durchschnittlichen Optiemierungsaufgaben stellt. Man muss schon ziemlich raffinierte Konstrukte bauen, um Compiler-Bugs zu triggern. Ist ja auch logisch: Das ganze Null-Acht-Fünfzehn-Zeug kompiliert so ein Compiler in vielen Installationen tagtäglich völlig problemlos. Da würden die trivialen Compiler-Fehler sofort auffallen. Im übrigen: Ein Programm das nur bei bestimmten Optimierungseinstellungen funktioniert ist definitiv fehlerhaft.
Kommt hinzu, dass wahrscheinlich 99 % der GCC-Bugs eher in einem "Internal Compiler Error" (ICE) enden, der zu einem Abbruch führt, statt einfach stillschweigend fehlerhaften Code zu generieren.
Natürlich ist ein Compiler auch nur ein Program und enthält Fehler. Allerdings kann man bei Compilern die etwas länger am Markt vorhanden sind, davon ausgehen, daß Fehler in den eher etwas 'esoterischen' Bereichen der Sprache zu finden sind. Bei den meisten C++ Compilern ist das der Bereich Metaprogrammierung und Templates. So was einfaches wie eine Zuweisung (und sei sie noch so kompliziert in Assembler umzusetzen) kriegt heutzutage jeder Compiler so zu sagen im Schlaf und mit links hin.
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.