Forum: Mikrocontroller und Digitale Elektronik eine Variable für zwei Tasks --> volatile setzen?


von brechbunkt (Gast)


Lesenswert?

Hallo,

ich verwende freeRTOS und habe einen Task, der mir einen (double)Wert 
setzt und einen anderen Task, der diesen Wert gelegentlich lesen muss.

Nun habe ich gelegentlich (aber ganz selten) das Problem, dass der 
zweite Task glaubt einen (sehr großen) Wert in der Variable zu lesen, 
der jedoch gar nicht möglich sein kann.

In der Suche konnte ich nicht findig werden, aber kann es sein, dass man 
Variablen in Verbindung mit verschiedenen Task als
1
volatile
 deklarieren muss? Also genauso, als wären es interrupts?

von (prx) A. K. (prx)


Lesenswert?

brechbunkt schrieb:
> Also genauso, als wären es interrupts?

Korrekt.

Ein Taskwechsel ergibt sich oft als Folge eines Interrupts, indem der 
Interrupt-Handler nicht in die ursprüngliche Task zurückkehrt, sondern 
in eine andere. Präemptives Multitasking wirkt folglich in diesem 
Zusammenhang analog zu Interrupts.

Dein Problem löst dies allerdings noch nicht.

von Peter D. (peda)


Lesenswert?

brechbunkt schrieb:
> Nun habe ich gelegentlich (aber ganz selten) das Problem, dass der
> zweite Task glaubt einen (sehr großen) Wert in der Variable zu lesen,
> der jedoch gar nicht möglich sein kann.

Vermutlich braucht double mehrere Befehle, dann müssen die Zugriffe 
atomar erfolgen (in beiden Tasks).

von Stefan W. (dl6dx)


Lesenswert?

A. K. schrieb:
> Präemptives Multitasting wirkt folglich in diesem
> Zusammenhang analog zu Interrupts.

Nur zur Ergänzung: Alle Zugriffe auf "shared memory" (was anderes ist 
diese Variable ja nicht) müssen aus dem gleichen Grund atomar erfolgen.

Güße

Stefan

Edit: Peter war etwas schneller...

von (prx) A. K. (prx)


Lesenswert?

Stefan Wagner schrieb:
> Edit: Peter war etwas schneller...

Ja, er war auch etwas schneller als mein Edit. ;-)

von (prx) A. K. (prx)


Lesenswert?

FreeRTOS enthält Methoden, mit denen man sich diesem Problem widmen 
kann. Nämlich in erster Linie Mutexe (siehe Semaphoren), und in 
Härtefallen taskENTER_CRITICAL/taskEXIT_CRITICAL.

von Alex (Gast)


Lesenswert?

Wenn ich dein Problem richtig verstanden habe, kannst du deine Variable 
mit Hilfe von Queue an den zweiten Task schicken.
http://www.freertos.org/Embedded-RTOS-Queues.html

von Peter D. (peda)


Lesenswert?

Alex schrieb:
> http://www.freertos.org/Embedded-RTOS-Queues.html

Hübscher Link, er zeigt sehr schön, wie kompliziert das ganze RTOS 
Gedöns ist. Da raucht einem schnell der Schädel beim Lesen.

Also Queues sind schonmal nicht. Sie funktionieren nur dann, wenn exakt 
gleichviel gesendet und empfangen wird. Ansonsten gibt es nen Über- bzw. 
Unterlauf. Und sie sind auch deutlich aufwendiger als "atomar".

Mutexe und Semaphoren aber auch nicht, denn jeder muß jederzeit drauf 
zugreifen können.

Weiß jemand, wie "atomar" in RTOS-Sprech heißt?

von Fabian O. (xfr)


Lesenswert?

Peter Dannegger schrieb:
> Mutexe und Semaphoren aber auch nicht, denn jeder muß jederzeit drauf
> zugreifen können.
>
> Weiß jemand, wie "atomar" in RTOS-Sprech heißt?

Wenn ein Zugriff atomar geschehen soll, darf doch eben nicht jeder 
jederzeit drauf zugreifen, sondern schön der Reihe nach. Das geht mit 
einem Semaphor bzw. Mutex.

Ohne die korrekte Syntax zu kennen, also etwa so:
1
mutex->lock();
2
Wert lesen / schreiben
3
mutex->unlock();

von Siegfried W. (swausd)


Lesenswert?

Hallo zusammen,

eine von mehreren Tasks gemeinsam genutzte Variable ist eine "shared 
ressource" und der Zugriff kann unter FreeRtos mit einer Mutex 
geschützt werden. Siehe hier:

http://www.freertos.org/Real-time-embedded-RTOS-mutexes.html

Das funktioniert wunderbar. Die Synchronisation verursacht natürlich 
einen gewissen overhead ...

Gruß

swausd

von Peter D. (peda)


Lesenswert?

Siegfried W. schrieb:
> Die Synchronisation verursacht natürlich
> einen gewissen overhead ...

Ja, das wird um Größenordnungen teurer sein, als ein simples 
CLI,Zugriff,SEI.

von Siegfried W. (swausd)


Lesenswert?

Peter Dannegger schrieb:
> Siegfried W. schrieb:
>> Die Synchronisation verursacht natürlich
>> einen gewissen overhead ...
>
> Ja, das wird um Größenordnungen teurer sein, als ein simples
> CLI,Zugriff,SEI.

über die Synchronisation zweier Prozesse/Tasks sollte man sich schon ein 
paar Gedanken machen. Einen oft geänderten Schleifenzähler sollte man 
nicht mit Mutex teilen müssen. Alle Interrupts des Systems sollte man 
dann allerdings auch nicht ausschließen ...

Gruß

swausd

von Daniel V. (danvet)


Lesenswert?

Peter Dannegger schrieb:
> Alex schrieb:
>> http://www.freertos.org/Embedded-RTOS-Queues.html
>
> Hübscher Link, er zeigt sehr schön, wie kompliziert das ganze RTOS
> Gedöns ist. Da raucht einem schnell der Schädel beim Lesen.
>
> Also Queues sind schonmal nicht. Sie funktionieren nur dann, wenn exakt
> gleichviel gesendet und empfangen wird. Ansonsten gibt es nen Über- bzw.
> Unterlauf. Und sie sind auch deutlich aufwendiger als "atomar".
>
> Mutexe und Semaphoren aber auch nicht, denn jeder muß jederzeit drauf
> zugreifen können.
>
> Weiß jemand, wie "atomar" in RTOS-Sprech heißt?

Ich kann mich dunkel erinnern, dass ich auf Windows-Rechnern für 
"atomaren" Zugriff auch das Mutex-Object verwendet habe (lange ists 
her):
http://msdn.microsoft.com/en-us/library/windows/desktop/ms684266(v=vs.85).aspx
Man kann glaube ich auch einfach checken, ob das Object grad belegt ist, 
ohne auf die Freigabe zu warten.
Wie das jetzt aber bei den RTOS für uC ist, weiss ich ehrlich gesagt 
nicht.

Edit: zu langsam

von Kein Name (Gast)


Lesenswert?

Für diesen Fall ginge auch eine sehr einfache Strategie. Den Wert 
mehrmals lesen.

do {
  tmp1 = volatileVar;
  tmp2 = volatileVar;
} while (tmp1 != tmp2);

von (prx) A. K. (prx)


Lesenswert?

Peter Dannegger schrieb:
> Ja, das wird um Größenordnungen teurer sein, als ein simples
> CLI,Zugriff,SEI.

Ist es. Es ist eine Abwägung des Aufwands. Wenn nur wenige Befehle zu 
schützen sind, dann ist die oben ebenfalls angeführte critical section 
billiger.

Je nach Prozessor und RTOS ist eine critical section entweder identisch 
mit einer simplen Interrupt-Sperre, oder setzt den Interrupt-Level so, 
dass nur noch Interrupts durchkommen, die keine RTOS-APIs nutzen und 
daher nicht preempten können. Beim NVIC der Cortex-M Cores lässt sich 
das effektiv nutzen um die Latenzzeit kritischer Interrupts nicht zu 
gefährden.

von (prx) A. K. (prx)


Lesenswert?

Kein Name schrieb:
> Für diesen Fall ginge auch eine sehr einfache Strategie. Den Wert
> mehrmals lesen.

Dummerweise verbessert das die Situation nur statistisch, nicht aber 
absolut. Ist also nur sinnvoll, wenn ein extrem seltener Fehlwert 
toleriert werden kann.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> Siegfried W. schrieb:
>> Die Synchronisation verursacht natürlich
>> einen gewissen overhead ...
>
> Ja, das wird um Größenordnungen teurer sein, als ein simples
> CLI,Zugriff,SEI.

Das funktioniert z.B. nicht bei echter Parallelität.  Oder willst du 
alle anderen Cores anhalten?

von (prx) A. K. (prx)


Lesenswert?

Johann L. schrieb:
> Das funktioniert z.B. nicht bei echter Parallelität.  Oder willst du
> alle anderen Cores anhalten?

Yep, aber das ist dann meistens ausserhalb des hier üblichen Kontextes 
"Mikrocontroller". Da kann man sich dann auch schon mal mit dem Gedanken 
an Spinlocks anfreunden, garniert mit resourcensparenden Delays um sich 
bei SMT nicht gegenseitig zu bremsen. Oder kann mit transactional memory 
gleich noch eine Stufe weiter gehen.

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.