Forum: Compiler & IDEs AVR-GCC: Problem mit volatile und delay loop


von Chris W. (Gast)


Angehängte Dateien:

Lesenswert?

hallo,

ich glaube ein problem mit volatile in verbindung mit delay loops
(z.b. _delay_us()) im avr gcc gefunden zu haben.

der angehaengte code tut nicht das, was er meiner meinung nach tun
sollte - das delay stimmt einfach nicht immer.

mit der mit 'nicht ok' markierten zeile funktionierts nie, mit
der 'ok' markierten zeile funktionierts, wenn ich die optimierung
auf s schalte - ohne optimierung funktionierts nie...

nicht funktionieren heisst: an nen logic-analyzer angeschlossen
sieht man, dass das delay scheinbar beliebig (auf jeden fall viel
zu lang) ist...unabhaengig vom wert von val.

verwende das aktuelle WinAVR von avrfreaks...

ach ja, volatile, weil auch aus einer interrupt-routine darauf
zugegriffen wird - ich hab den code nur der uebersichtlichkeit
halber aufs notwendige reduziert.

kann das ein compiler-bug sein oder versteh ich irgendwas nicht?

von Stefan Kleinwort (Gast)


Lesenswert?

Ohne jetzt in die Doku zu schauen - bist Du Dir sicher, dass delay_us
ein double erwartet?

Stefan

von OldBug (Gast)


Lesenswert?


von Stefan Kleinwort (Gast)


Lesenswert?

Tatsächlich: double ... nehme alles zurück ...

Stefan

von Jörg Wunsch (Gast)


Lesenswert?

Gleitkommaargumente sind nur im konstanten Kontext zugelassen, bei dem
der Compiler das wegoptimieren kann.  Ansonsten müssen die Argumente
in der Tat uint16_t sein, weil das der Datentyp ist, den die fertige
Schleife selbst nehmen will.  Nee, Moment mal, _delay_us benutzt ja
_delay_loop_1, da ist es sogar uint8_t (bzw. wird auf den reduziert).

Sorry, das müsste man wohl in der Doku noch ein wenig hervorheben, ist
mir bislang auch noch nicht untergekommen.  Kannst ja gern einen
Bugreport dafür schreiben.

Der wesentliche Sinn dieser inline-Funktionen ist die Realisierung
kurzer fester Verzögerungen, nicht ihr universeller Einsatz an
Stellen, wo ein Timer deutlich angebrachter wäre.

Übrigens: __us hat in einem Anwenderprogramm nichts verloren.
Schreibe bitte us, microseconds, micro_seconds, u_s oder was auch
immer -- aber nichts, was mit einem Unterstrich anfängt.  Du kommst
sonst über kurz oder lang in Teufels Küche.

von Jörg Wunsch (Gast)


Lesenswert?

Selbst für mehrere kurze Verzögerungen würde ich das übrigens nicht so
machen.  Du hättest dann zur Laufzeit Multiplikationen und/oder
Divisionen.  Der Sinn der _delay_us und _delay_ms Funktionen ist, dass
der Compiler diese (teuren) Operationen zur Compilezeit auflösen kann.

Besser vielleicht eine switch-Anweisung, die mehrere delay-Werte
vorgibt oder die delay-Werte in einem Array hinterlegen.

von Chris W. (Gast)


Lesenswert?

@OldBug

die helfen mir leider nicht weiter...


@Jörg

das mit den __ ist von cut&paste uebriggeblieben...

auch wenn ich alle doubles zu uint8_t s mache passiert
dasselbe...irgendwas stimmt einfach nicht - ich muss
doch auch die variable als parameter uebergeben koennen
ohne das dann nix mehr richtig geht???

ach ja, wenn ichs mit der 'ok' zeile kompiliere ist das
file ca. 200 gross - mit der 'nicht ok' zeile ca. 900...

auch wenn man prinzipiell den timer nehmen sollte, so
sollte das aber doch auch funktionieren oder?
ein array wuerde mir nichts bringen, weil die werte
wirklich immer unterschiedlich sind.

von Chris (Gast)


Lesenswert?

> das mit den __ ist von cut&paste uebriggeblieben...

Dann ist der Code, von dem du kopiert hast, der Übeltäter und sollte
verbessert werden. Führende Unterstriche sind wirklich böse in C und
C++, gewöhn dir das am besten gar nicht erst an.

Hinten angehängte Unterstriche kann man eh besser lesen. ;-)

> ach ja, wenn ichs mit der 'ok' zeile kompiliere ist das
> file ca. 200 gross - mit der 'nicht ok' zeile ca. 900...
Kein Wunder, bei letzterem muss das Programm Gleitkommaarithmetik
betreiben und braucht dafür natürlich viel mehr Code.

> auch wenn ich alle doubles zu uint8_t s mache passiert
> dasselbe...irgendwas stimmt einfach nicht - ich muss
> doch auch die variable als parameter uebergeben koennen
> ohne das dann nix mehr richtig geht???

Hm, vielleicht verlangt delay_us wirklich Compile-Time-Konstanten als
Parameter, da ansonsten Divisionen und/oder Multiplikationen zur
Laufzeit ausgeführt werden müssten. </IMHO>

von Jörg Wunsch (Gast)


Lesenswert?

> Hm, vielleicht verlangt delay_us wirklich Compile-Time-Konstanten
> als Parameter, da ansonsten Divisionen und/oder Multiplikationen zur
> Laufzeit ausgeführt werden müssten.

Habe eben nochmal nachgesehen: genau so ist es.  Damit vervielfacht
sich natürlich die Verzögerung heftig.  In dem Falle muss man dann
doch wieder selbst auf die low-level Funktionen _delay_loop_1 und
_delay_loop_2 zurückgreifen und die Berechnung der Zeitkonstanten
selbst vornehmen.  Allerdings würde ich auch hier jede Art von
Division zur Laufzeit vermeiden, auch im Integer-Bereich ist die für
den Anwendungsfall immer noch viel zu teuer.

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.