Archiv verlassen und diese Seite im Standarddesign anzeigen : avr-gcc optimiert gleiche Ausdrücke weg - abstellen?
Hallo allerseits,
ich habe mal eine kurze Frage an die gcc - Kenner:
Wenn ich z.B. in einem Programm schreibe:
PORTC = 0x01;
PORTC = 0x01;
PORTC = 0x01;
also eben mehrfach das gleiche, dann optimiert das der GCC auf nur einen Ausdruck, was ja prinzipiell auch sinnvoll ist.
Doch das darf bei mir nicht sein, weil sich dann die Ausführungszeit ändert.
Der Hintergrund ist folgender:
Ich experimentiere ein bisschen mit DDS - Funktionsgeneratoren per AVR, und ich habe ein kleines Programm (Computerprogramm) geschrieben, das mir die Tables(in Form von vielen "PORTC = ...") für verschiende Signalverläufge generiert. Der AVR mit dann mit einem veränderbaren Oszillator getaktet, somit kann man die Frequenz des Signals ändern.
Nun muss es aber so sein, dass er manchmal den gleichen Wert mehrfach ausgibt, wenn das Signal eine kleine Steigung hat (z.B. beim Sinus - Maximum), sonst verzerrt sich natürlich der Verlauf.
Deshalb die Frage: kann man das abstellen, bzw. wie könnte ich es sonst machen?
Ach ja: Im Makefile habe ich natürlich OPT = 0 eingestellt, aber das nützt anscheinend nichts.
Bascom ist da nicht schlau genug, dort funktionierts, aber ich würde halt gerne bei C bleiben.
Danke für eure Antworten!
Mfg Thegon
also eben mehrfach das gleiche, dann optimiert das der GCC auf nur einen Ausdruck, was ja prinzipiell auch sinnvoll ist.
Sicher nicht. PORTC ist als volatile gekennzeichnet, der Compiler muss jeden Zugriff darauf ausführen. Dass -O0 den Fehler nicht beseitigt deutet auf eine andere Ursache hin, ohne Optimierung kann eigentlich nichts weggelassen werden.
mfG
Markus
Sicher nicht. PORTC ist als volatile gekennzeichnet, der Compiler muss jeden Zugriff darauf ausführen.
Das ist so nicht richtig.
Der Compiler muß, wenn eine Variable volatile ist, damit rechnen, daß sie außerhalb des aktuellen Programmkontextes geändert werden kann. Da sie aber wieder überschrieben wird, ist dreimal schreiben logisch das gleiche wie einmal schreiben, solange nicht gelesen wird. Er darf zwischen zwei Lesevorgängen die Variable nicht in einem Register halten, sondern muß sie immer neu lesen. Hier wird nie gelesen, also ist alles korrekt.
Es könnte funktionieren, wenn statt einer Konstanten eine Variable geschrieben würde. Diese müsste dann aber volatile sein, damit der Compiler nicht davon ausgehen kann, daß sie konstant ist. Oder man schreibt die Elemente eines Arrays auf den Port.
also eben mehrfach das gleiche, dann optimiert das der GCC auf nur einen Ausdruck, was ja prinzipiell auch sinnvoll ist. Doch das darf bei mir nicht sein, weil sich dann die Ausführungszeit ändert.
Das läßt sich in einer höheren Sprache nicht formulieren. Die Ausführungszeit läßt sich nicht vorgeben. Eine höhere Programmiersprache garantiert die logische Richtigkeit der Programmausführung, nicht mehr. Bei einem einfachen µC kann man sich mit Assembler helfen, bei einem größerem System mit mehreren (auch internen) Bussen oder Busmastern (z.B. DMA) geht das dann auch nicht mehr. Da hilft nur noch dedizierte Hardware, im einfachsten Fall ein (Timer)Interrupt.
MfG Klebwax
Das ist so nicht richtig.Doch, ist es.
Der Compiler muß, wenn eine Variable volatile ist, damit rechnen, daß sie außerhalb des aktuellen Programmkontextes geändert werden kann.Nein. Er muss damit rechnen, dass auf sie außerhalb zugegriffen wird, egal ob schreibend oder lesend. Und das wiederum bedeutet, dass jeder Zugriff tatsächlich ausgeführt werden muss, auch schreibende.
Er muss damit rechnen, dass auf sie außerhalb zugegriffen wird, egal ob schreibend oder lesend. Und das wiederum bedeutet, dass jeder Zugriff tatsächlich ausgeführt werden muss, auch schreibende.
Solange der andere Kontext nur liest, ist einmal schreiben gut genug. Aber:
In C und C++ wird durch diesen Typqualifikator spezifiziert, dass sich der Wert der Variable jederzeit ändern kann, beispielsweise durch andere Prozesse oder Threads
MfG Klebwax
Solange der andere Kontext nur liest, ist einmal schreiben gut genug.volatile bedeutet, dass jeder Zugriff für den Compiler nicht einsehbare Seiteneffekte haben kann, und daher durchgeführt werden muss. Ob Schreiben oder Lesen spielt dabei keine Rolle. Es spielt auch keine Rolle, ob dieser "Seiteneffekt" nun ein anderer Software-Kontext ist, der ebenfalls auf die Variable zugreift, oder ob es ein Hardware-Effekt ist, weil die Variable in Wirklichkeit ein Register ist.
Aber:
In C und C++ wird durch diesen Typqualifikator spezifiziert, dass sich der Wert der Variable jederzeit ändern kann, beispielsweise durch andere Prozesse oder ThreadsUnd? Nur weil etwas irgendwo steht, ist es noch lange nicht richtig. Das Zitierte ist jedenfalls mindestens unvollständig, um nicht zu sagen falsch.
An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects
Ok, mit side effects dürftest du recht haben. Je länger ich darüber nachdenke, meist schreibt man zwar auf einen Port oder Register aus einem Buffer, aber mehrere Male hintereinander die gleiche Konstante sollte durch volatile auch abgedeckt sein. Hab also zu schnell geantwortet
MfG Klebwax
Hmm, jetzt kenne ich mich selber nicht mehr aus:
Gerade wollte ich einen Screenshot vom Oszi machen, wo gestern noch eindeutig zu erkennen war, dass der ganze Sinus besonders im Maximum und Minimung dreiecksförmig war, was ja eindeutig heißen würde, dass hier Ausdrücke wegoptimiert wurden (oder zumindest schneller ausgeführt wurden als andere, was aber sohl sehr seltsam wäre)
Und ich schrieb wäre, weil:
Jetzt ist der Sinus sinusförmig! Gleich noch einen kleinen Test geflasht, wo fünf mal aus und einmal ein stand: Tastverhältnis 1:5.
Und ich verspreche, dass es gestern nicht so war, sonst hätte ich den Thread ja nicht gestartet. Ich hab auch nicht das falsche Makefile geändert, das ist alles gleich wie gestern. Villeicht der Neustart vom Computer?
Peinlich jetzt natürlich, ich hoffe ihr seid mir jetzt nicht böse...
Wie mir Klebwax empfohlen hat, werde ich es aber auf jeden fall einmal mit Assembler versuchen, das Programm ist ja nicht kompliziert, und sonst braucht der AVR ja nichts zu tun, Anzeige und so weiter möchte ich in einem Zweiten machen.
Danke auf jeden Fall für eure Hilfe, ich werde berichten, falls sich doch noch etwas tut.
Mfg Thegon
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.