Probleme mit Statemachine

Gast #1776263
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
Angehängte Dateien:
Persönliche Seite
> 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.
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.
Gast
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
Gast
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.
Gast
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
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'
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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 16 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.