Forum: Compiler & IDEs Probleme mit Statemachine


von Micha (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
ich versuche auf einem ATtiny45 den angehängten Code zu implementieren. 
Leider noch ohne Erfolg. Wenn ich den Code im Simulator debugge, springt 
er immer von State 0 in State 5. Ich hab glaub ich schon ne 
Denkblockade. Seht ihr auf Anhieb, wieso nicht erst in State1 gesprungen 
wird?

Vielen Dank und Grüße,
 Micha

von Stefan B. (stefan) Benutzerseite


Lesenswert?

> void TIMER1_Stop()
> {
>   TCCR1 &= 0xF0;
>
>   // Schalte Staemachine weiter
>   actState++; // schalten auf State2 oder State6 weiter
> }

Du manipulierst den Status in Userprogramm (main) und im Timer! Dein 
Timer und deine Statemachine in main laufen aber nebenläufig 
("gleichzeitig") und anders als du denkst. Überdenke dein Programmdesign 
noch mal.

Ich bin ehrlich gesagt zu faul, das Programmdesign aus dem Code 
rauszupfriemeln. Wenn du aber eine Beschreibung oder eine Zeichnung 
anhängst, schaue ich mir die Logik an.

von Rolf Magnus (Gast)


Lesenswert?

Mir fällt auf, daß hier bei einigen Variablen das volatile fehlt.

von Andreas F. (aferber)


Lesenswert?

Micha schrieb:
> Wenn ich den Code im Simulator debugge, springt
> er immer von State 0 in State 5. Ich hab glaub ich schon ne
> Denkblockade. Seht ihr auf Anhieb, wieso nicht erst in State1 gesprungen
> wird?

Der Optimizer des Compilers ist schlauer als du denkst, er erkennt, dass 
der Code für State 1 und State 5 komplett identisch ist, und fasst die 
beiden Fälle im generierten Code zusammen. Die Debuginfos/der Debugger 
können das nicht darstellen, sondern zeigen dir bei der Ausführung dann 
einen der beiden Fälle im C-Code an.

Andreas

PS: Die Sache mit volatile gilt natürlich trotzdem, so wie der Compiler 
arbeitet wird deine Hauptschleife von der Änderung von actState im 
Interrupt nie irgendwas mitbekommen. Die Variable wird lokal in einem 
Register gehalten, und nicht mehr aus dem Arbeitsspeicher geladen, 
solange die Schleife läuft.

PS2: Generell gilt, dass beim Singlesteppen von stark optimiertem Code 
die dollsten Dinge passieren können, beispielsweise dass Code scheinbar 
übersprungen wird, oder die Ausführung sich schonmal rückwärts zu 
bewegen scheint.

von Micha (Gast)


Lesenswert?

Stefan B. schrieb:
> Du manipulierst den Status in Userprogramm (main) und im Timer! Dein
> Timer und deine Statemachine in main laufen aber nebenläufig
> ("gleichzeitig") und anders als du denkst. Überdenke dein Programmdesign
> noch mal.

Das der Compliler zusammenfasst hätte ich gar nicht gedacht. Danke für 
den Hinweis.
Wie kann man denn neben dem volatile noch Daten zwischen einer 
Interruptroutine und dem sequentiellen Programm austauschen?

ps. Der Timer ist nur in 2 States (wahrscheinlich nach dem kompilieren 
nur in einem) aktiv.

Danke & Grüße

von manoh (Gast)


Lesenswert?

Micha schrieb:
> Wie kann man denn neben dem volatile noch Daten zwischen einer
> Interruptroutine und dem sequentiellen Programm austauschen?

Such mal nach "volatile" im Forum, da wird erklärt was Schlüsselwort 
volatile bedeutet...

1
actState=1;
 sinnvoll benannte enums würden das Lesen vereinfachen und sie helfen 
auch Leichtsinnsfehler zu verhindern.

von Rolf Magnus (Gast)


Lesenswert?

Micha schrieb:

> Wie kann man denn neben dem volatile noch Daten zwischen einer
> Interruptroutine und dem sequentiellen Programm austauschen?

Was paßt dir denn an volatile nicht?

von Micha (Gast)


Lesenswert?

Hab schon vorhin mal danach gesucht. Bei Wikipedia hab ich gefunden, 
dass der Compiler die volatile Variablen nicht optimieren soll.
Also macht ihr den Austausch zwischen einer ISR und dem Hauptprogramm 
nur über volatile-Variablen?

Danke & Grüße,
 Micha

von Micha (Gast)


Lesenswert?

Rolf Magnus schrieb:
> Was paßt dir denn an volatile nicht?

Ah ok. Gut danke. Ich hab es grad mal so probiert. Wollte mein Wissen 
nur erweitern und dachte es gibt noch andere Möglichkeiten.

Danke :)

von Karl H. (kbuchegg)


Lesenswert?

Micha schrieb:
> Hab schon vorhin mal danach gesucht. Bei Wikipedia hab ich gefunden,
> dass der Compiler die volatile Variablen nicht optimieren soll.
> Also macht ihr den Austausch zwischen einer ISR und dem Hauptprogramm
> nur über volatile-Variablen?

Ja.
Eine andere Möglichkeit gibt es letzten Endes nicht. Es läuft immer 
darauf hinaus, dass in der ISR (mglw. über Umwege) eine globale Variable 
auf einen Wert gesetzt wird.

Und da das zu jedem beliebigen Zeitpunkt passieren kann, muss man dem 
Compiler mitteilen, dass er bei Optimierungen keine Annahmen über den 
Zustand dieser Variablen treffen darf.
Genau das macht 'volatile'

von Michael B. (mb_)


Lesenswert?

Karl heinz Buchegger schrieb:
> Micha schrieb:
>> Hab schon vorhin mal danach gesucht. Bei Wikipedia hab ich gefunden,
>> dass der Compiler die volatile Variablen nicht optimieren soll.
>> Also macht ihr den Austausch zwischen einer ISR und dem Hauptprogramm
>> nur über volatile-Variablen?
>
> Ja.
> Eine andere Möglichkeit gibt es letzten Endes nicht.

Das ist so nicht ganz richtig. Wenn man explizize memory-barriers 
verwendet, dann braucht man keine Daten als volatile zu markieren. Das 
hat den Vorteil, dass es den Optimizer wesentlich weniger einschränkt.

Auf AVR kann man den gcc-inline-assembler memory clobber verwenden. Das 
reicht. Die CPU macht ja kein reordering von sich aus.

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.