Forum: Compiler & IDEs Code optimieren und delay Funktionen beibehalten?!


von rubbellos (Gast)


Lesenswert?

Hi,

mein Code ist etwas umfangreicher geworden, so dass er nicht mehr auf 
den Chip passte. Mit Optimierung auf höchster Stufe spare ich 50% Memory 
ein, aber meine Wartefunktionen aus der delay.h sind jetzt viel 
schneller und warten nicht die gewünschte Zeit.

Kann ich irgendwie dem Compiler sagen, dass er bei der delay.h und ihren 
Funktionen nichts Optimieren soll?

von Krapao (Gast)


Lesenswert?

AVR-GCC (WINAVR)?

Es gab mal ähnliche Probleme, allerdings 2007. Und eine so alte Tolchain 
setzt du nicht ein, oder?

Den offensichtlichen Fehler hast du bestimmt auch nicht gemacht - die 
delays ohne Optimierungsstufe zufällig passend zu einem falsch 
eingestellten Takt und jetzt mit irgendeiner Optimierung sind sie zu 
schnell.

Wenn du ein nachvollziehbares Beispiel (Minisource und mehr Angaben zur 
Toolchain inkl. Optimierungsstufe) hast, kann vielleicht jemand der 
Sache nachgehen.

An das Disassemblat bist du wohl noch nicht rangegangen, um zu sehen, ob 
der delay-Code noch im Programm vorhanden ist. Kannst du auch mal 
machen.

Auch wäre es hilfreich, wenn du den Beschleunigungsfaktor ermitteln 
kannst - 4x so schnell wäre ein sehr verdächtiger Wert für eine 
bestimmte Toolchain mit defektem delay.

Ich hoffe man sieht bereits etwas im Simulator, ansonsten bräuchte man 
auch noch Angaben zur Schaltung.

von Rolf M. (rmagnus)


Lesenswert?

rubbellos schrieb:
> Mit Optimierung auf höchster Stufe spare ich 50% Memory
> ein, aber meine Wartefunktionen aus der delay.h sind jetzt viel
> schneller und warten nicht die gewünschte Zeit.
>
> Kann ich irgendwie dem Compiler sagen, dass er bei der delay.h und ihren
> Funktionen nichts Optimieren soll?

Das ist eher ungewöhnlich, denn eigentlich ist für die delay-Funktionen 
die Optimierung notwendig. Die Delays stimmen nur bei eingeschalteter 
Optimierung.

von Werner (Gast)


Lesenswert?

rubbellos schrieb:
> Kann ich irgendwie dem Compiler sagen, dass er bei der delay.h und ihren
> Funktionen nichts Optimieren soll?

Ganz im Gegenteil!
Wenn du in der delay.h nachliest, steht da geschrieben:
"In order for these functions to work as intended, compiler 
optimizations must be enabled, and the delay time must be an 
expression that is a known constant at compile-time."

Kennt deine delay.h die richtige CPU-Frequenz und verwendest du die 
aktuelle delay-Bibliothek?

von (prx) A. K. (prx)


Lesenswert?

Da er über die Auswahl des Forums grad mal nahegelegt hat, dass es sich 
um den GCC handeln dürfte, nicht aber für welche Architektur, sollte man 
evtl. abwarten, bis er mehr darüber verrät.

von Klaus W. (mfgkw)


Lesenswert?

bis dahin kann man ja mal wieder raten :-)
Ich tippe auf Nichtkonstanten beim Aufruf.

von rubbellos (Gast)


Lesenswert?

Benutze AVR Studio 5 mit AVR GCC. Hab nur #indlude <avr/delay.h> 
geschrieben und dann mit _delay_ms(200) aufgerufen.

von Matthias K. (mkeller)


Lesenswert?

Sie sind schneller, ja. Aber davor waren sie langsamer als du eigentlich 
erwartet hast.

Übrigends ist es jetzt <util/delay.h>

von Oliver (Gast)


Lesenswert?

rubbellos schrieb:
> Mit Optimierung auf höchster Stufe

Alles ausser -Os ist bei einem AVR selten sinnvoll.

Oliver

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Oliver schrieb:
> Alles ausser -Os ist bei einem AVR selten sinnvoll.

Wenn man genügend freien Flash hat, kann man das Programm mit -O3
sauschnell bekommen. ;-)

von Peter D. (peda)


Lesenswert?

Jörg Wunsch schrieb:
> Wenn man genügend freien Flash hat, kann man das Programm mit -O3
> sauschnell bekommen. ;-)

Was ist denn sauschnell?

Schleifen aufdröseln spart gerademal DEC+BRNE (3 Zyklen) pro Durchlauf. 
Das ist lächerlich wenig und völlig unmerkbar.


Peter

von Oliver (Gast)


Lesenswert?

Gefühlt ist es aber viel schneller ;)

Oliver

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:

> Was ist denn sauschnell?

Hängt natürlich immer vom Umfeld ab, aber bis zu 2:1 habe ich schon
erlebt.  Allerdings hat man reichlich selten wirklich Zeitprobleme
auf einem AVR.

von (prx) A. K. (prx)


Lesenswert?

Peter Dannegger schrieb:

> Was ist denn sauschnell?

Beispielsweise
- Agressiveres Inlining kann Berechnungen erheblich eindampfen, wenn aus 
Parametern Konstanten werden.
- Duplizierung von Schleifen, um invariante Bedingungen rauszuwerfen.

von Karl H. (kbuchegg)


Lesenswert?

Klaus Wachtler schrieb:
> bis dahin kann man ja mal wieder raten :-)
> Ich tippe auf Nichtkonstanten beim Aufruf.

Ich tipp auf Optimizer aus, gepaart mit:
Oooch, die delays. Da probier ich jetzt einfach ein paar Zahlenwerte 
durch, bis es mir passt. Was schert mich ob 500 Millisekunden auch 500 
Millisekunden sind, das Ergebnis muss passen.

Und jetzt ist der Optimizer ein, 500 ms sind auch wirklich ca. 500 ms. 
Und das Geschrei ist groß, dass die mühsam durch Versuch und Irrtum 
angepassten Delay-Zeiten nicht mehr brauchbar sind.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:
> Und jetzt ist der Optimizer ein, 500 ms sind auch wirklich ca. 500 ms.

Vielleicht sind es jetzt ja auch 62,5 ms. ;-)

von rubbellos (Gast)


Lesenswert?

Gibt es keine Präprozessor Befehle mit denen man den Teil der nicht 
optmiert werden soll einklammern kann?

Sowas wie:
1
#dont_optimizize
2
code
3
#end_dont_optimizize

von Εrnst B. (ernst)


Lesenswert?

rubbellos schrieb:
> Gibt es keine Präprozessor Befehle mit denen man den Teil der nicht
> optmiert werden soll einklammern kann?

Jein. erstens macht das nicht der Präprozessor. Der macht nur 
Textersetzungen und optimiert nicht.
Als #pragma/Funktionsattribut geht das.

=> GCC dokumentation lesen.

aber Vorher: Wenn du sowas brauchst, ist es ein fast 100%iges Zeichen 
dafür, dass dein Programmcode FALSCH ist. Behebe lieber die Fehler, 
anstatt an den Symptomen rumzudoktorn.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

rubbellos schrieb:
> Gibt es keine Präprozessor Befehle mit denen man den Teil der nicht
> optmiert werden soll einklammern kann?

Der Präprozessor?  Der optimiert noch gar nichts.

Ja, es gibt in neueren GCC-Versionen pragmas dafür.

Nein, die brauchst du nicht.  Du versuchst gerade, eine Kopfschmerz-
tablette zu nehmen, statt die Ursache der Kopfschmerzen zu
beseitigen.  Ja, ich weiß, dass diese Art der "Krankheitsbekämpfung"
modern ist, aber du tust dir damit keinen Gefallen.  Weder bei den
Kopfschmerzen noch bei den delays.

von Krapao (Gast)


Lesenswert?

Das ist IMHO der falsche Ansatz so lange die Ursache noch unbekannt ist.

Um deine Neugier zu stillen:

Erst GCC ab Version 4.4 (also nicht für WinAVR2010... inklusive! Aber 
möglicherweise mit der Atmel AVR Toolchain) bietet ein #pragma zur 
Einstellung von Optimierungen auf Funktionsebene an 
(http://gcc.gnu.org/onlinedocs/gcc/Function-Specific-Option-Pragmas.html#Function-Specific-Option-Pragmas).

von Rolf M. (rmagnus)


Lesenswert?

Das wird aber alles gar nichts bringen. Der Grund für das Einschalten 
der Optimierungen war ja der zu große Flashbedarf. Ein mit ziemlicher 
Sicherheit erheblicher Teil dieses Flashbedarfs resultiert aber aus de 
Nutzung der Delay-Funktionen ohne Optimierung. Wenn er also jetzt die 
Optimierungen gezielt nur für die Delays ausschaltet, wird auch der 
Flashbedarf wieder stark ansteigen.
Es wird also nichts anderes übrigbleiben, als die die bisher falsch 
eingestellten Delay-Zeiten zu korrigieren.

von Dante (Gast)


Lesenswert?

Suche nach Gcc Function Attributes...dort gibt es folgendes:
optimize
    The optimize attribute is used to specify that a function is to be 
compiled with different optimization options than specified on the 
command line. Arguments can either be numbers or strings. Numbers are 
assumed to be an optimization level. Strings that begin with O are 
assumed to be an optimization option, while other options are assumed to 
be used with a -f prefix. You can also use the `#pragma GCC optimize' 
pragma to set the optimization options that affect more than one 
function. See Function Specific Option Pragmas, for details about the 
`#pragma GCC optimize' pragma.

von Simon K. (simon) Benutzerseite


Lesenswert?

Dante schrieb:
> Suche nach Gcc Function Attributes...dort gibt es folgendes:
> optimize

Maaahaaa! Nein, tue es bitte nicht. siehe Posts hier vor.

Code her, alles Andere ist Murks und keine richtige Lösung.

von Dante (Gast)


Lesenswert?

Yo Simonsen haste Recht. Hab mich verlesen, "compiler optimization must 
be turned ON".

Wenn es mit util/delay.h nicht funzt dann schreibs halt selber.
Inline Assembler, mit #if die Anzahl von Nops vom Takt abhängig machen 
und gut ist.

von Dante (Gast)


Lesenswert?

UND DANN optimierung für die delay-Funktion abschalten ;)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Dante schrieb:
> Inline Assembler, mit #if die Anzahl von Nops vom Takt abhängig machen
> und gut ist.

Schon hast du <util/delay.h> wiedererfunden. ;-)  OK, NOPs werden
eher nicht benutzt, man bräuchte für 200 ms auch ziemlich viele.
<util/delay_basic.h> für die, die sich die Anzahl der Zyklen lieber
selbst ausrechnen möchten.

von fdssd (Gast)


Lesenswert?

dann werf die delays weg und nimm nen timer ^^

abgesehen von irgendwelchen einschaltdelays hab ich bisher nie die delay 
dinger gebraucht

und da tut es auch ein for(xxx); mit einer lokalen volatile
die nach der init im nirvana verschwindet

von Peter D. (peda)


Lesenswert?

fdssd schrieb:
> und da tut es auch ein for(xxx); mit einer lokalen volatile
> die nach der init im nirvana verschwindet

Soso.
Und wie gebe ich dann die Dauer an?

Die delay.h funktioniert einwandfrei, wenn man folgende Sachen beachtet:
- nicht die alte von AVRStudio5 nehmen (4-mal zu schnell)
- Vorher F_CPU definieren
- Optimierung: "-Os"


Peter

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

fdssd schrieb:
> hab ich bisher nie die delay
> dinger gebraucht

Für sehr kurze Verzögerungen (wie man sie bspw. beim Ansteuern von
LC-Displays hat) lohnt sich oft das Anwerfen eines Timers gar nicht.

Für 200 ms ist das natürlich was anderes.

von Vlad T. (vlad_tepesch)


Lesenswert?

Peter Dannegger schrieb:
> Die delay.h funktioniert einwandfrei, wenn man folgende Sachen beachtet:
> - nicht die alte von AVRStudio5 nehmen (4-mal zu schnell)

kannst du dafür einen Link geben?
ich krieg die Worte "alt" und "von Studio5" nicht zusammen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Vlad Tepesch schrieb:
> ich krieg die Worte "alt" und "von Studio5" nicht zusammen.

Die AVR Toolchain, die mit AVR Studio 5 direkt ausgeliefert wird,
hat eine buggige Version der avr-libc erwischt, in der die
delay-Routinen 4mal zu schnell waren (mea culpa).  Ich glaube, es
gibt mittlerweile von Atmel eine neue Version der AVR Toolchain, die
eine neuere Version der avr-libc mitbringt.

von Dante (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> OK, NOPs werden
> eher nicht benutzt, man bräuchte für 200 ms auch ziemlich viele.

schonmal was von Schleifen gehört. Btw durch den bedingten Sprung 
braucht man noch weniger NOPs ;)

von Klaus (Gast)


Lesenswert?

Dante schrieb:
> schonmal was von Schleifen gehört. Btw durch den bedingten Sprung
> braucht man noch weniger NOPs ;)

Du bist so kluk. Nun warum genau braucht man jetzt NOPs in den 
Schleifen? Achja, ein bedingten Sprung verbraucht ja keine Zeit, das tun 
nur die NOPs...

von Dante (Gast)


Lesenswert?

danke Klaus du ....

aber mal im Ernst: Jörg hat ja recht, es wäre ein Remake von delay.h, 
aber stört es euch nicht dass die Include-Datei zwingend -Os fordert? 
Wenn es anders herum wäre würde es mir eher einleuchten (also eine 
delay.h die ohne Optimierung kompiliert werden müsste).
Ob man jetzt nur ne Schleife macht und die Zyklenanzahl vom Takt 
abhängig ist oder Noppels in der Schleife vom Takt abhängig...das 
schenkt sich ja nix.

von Dante (Gast)


Lesenswert?

Jörg, warum braucht delay.h die Einstellung -Os ????

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Dante schrieb:
> Jörg, warum braucht delay.h die Einstellung -Os ????

Weil es die nutzerfreundliche Variante von <util/delay_basic.h> ist.
Bei dieser muss man alles selbst ausrechnen, delay.h will dem Nutzer
die Arbeit abnehmen.  Zur Nutzerfreundlichkeit gehört für mich dazu,
dass man eben auch _delay_ms(2.5) angeben kann, genauso wie
#define F_CPU 3.68E6 (denn auf dem Quarz steht 3.68 MHz, nicht
3680000 Hz drauf).  Die Zahlen, die man als Ingenieur für gewöhnlich
benutzt, sind nun einmal in aller Regel Gleitkommazahlen.  Warum
soll ich denn meinen Kopf verbiegen, wenn der Compiler das stattdessen
tun kann?

Wer nicht optimiert, braucht ohnehin keine delays. :-)

Ich verstehe einfach bis heute nicht, warum man bei einem Prozessor
wie dem AVR (der ziemlich RISC ist von der Art und Weise, wie die
Befehle gebaut sind) freiwillig auf die Optimierungen des Compilers
verzichtet.

von (prx) A. K. (prx)


Lesenswert?

Wer die Freuden des Debuggings per IDE und Simulator/JTAG/DW wirklich 
geniessen will, der muss da manchmal durch. Nicht jeder kann sich mit 
dem wirren Gehüpfe durch optimierten Code wirklich anfreunden, oder 
kapiert auch nur warum das so seltsam läuft und Variablen sich so 
seltsam benehmen.

Und dann sind da natürlich noch jene, deren Code optimiert nicht läuft, 
was selbstverständlich nur am Compiler liegen kann. ;-)

von Dante (Gast)


Lesenswert?

Ok Jörg, das sehe ich ein. Schließlich will nicht jeder Atmega-Neuling 
Takte abzählen. Da ich eher Informatiker als Ingenieur bin bevorzuge ich 
diskrete Zahlen statt Floating, aber jedem das seine.

Jörg Wunsch schrieb:
> Wer nicht optimiert, braucht ohnehin keine delays. :-)

Ein netter Scherz, aber du vergisst es soll ja sogar (zeitkritische) 
Routinen geben soll, die KEINE smart optimization wollen. Oder 
abgefahrene (wenn auch zugegebenermaßen bestimmt sehr seltene) Projekte, 
in denen der Schreiberling sich nicht die Asm-Instruktionen vom Compiler 
durcheinanderwürfeln lassen mag.

Aber für den Otto-Normal-AvrLib-User und in fast 100% aller Fälle hast 
schon recht.

von Rolf M. (rmagnus)


Lesenswert?

Dante schrieb:
> Ok Jörg, das sehe ich ein. Schließlich will nicht jeder Atmega-Neuling
> Takte abzählen. Da ich eher Informatiker als Ingenieur bin bevorzuge ich
> diskrete Zahlen statt Floating, aber jedem das seine.

Du kannst ja auch jederzeit die angesprochenen delay_basic.h-Funktionen 
verwenden. Die kommen ganz ohne Gleitkommarechnung und F_CPU aus. Dafür 
muß man eben selbst ausrechnen, wieviele Schleifendurchläufe man für die 
gewünschte Delay-Zeit braucht.

> Jörg Wunsch schrieb:
>> Wer nicht optimiert, braucht ohnehin keine delays. :-)
>
> Ein netter Scherz, aber du vergisst es soll ja sogar (zeitkritische)
> Routinen geben soll, die KEINE smart optimization wollen.

Wenn sie so zeitkritisch sind, müssen sie sowieso in Assembler 
geschrieben werden, und da wird nix mehr optimiert. C-Code so 
hinzufrickeln, daß das Timing so exakt paßt, ist Murks und wird einem 
spätestens bei der nächsten Compiler-Version oder auch nur irgendeiner 
Änderung der Optionen nach hinten losgehen.

> Oder abgefahrene (wenn auch zugegebenermaßen bestimmt sehr seltene)
> Projekte, in denen der Schreiberling sich nicht die Asm-Instruktionen vom
> Compiler durcheinanderwürfeln lassen mag.

Auch dann muß er sie in Assembler schreiben.

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
Noch kein Account? Hier anmelden.