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?
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.
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.
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?
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.
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. ;-)
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
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
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
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.
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.
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.
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 ;)
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...
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.
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.
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. ;-)
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.
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.