Forum: Mikrocontroller und Digitale Elektronik Priorisierung langer Task und Kommunikationstask


von Jan K. (jan_k)


Lesenswert?

Hallo zusammen,

angenommen, ich habe hier einen Mikrocontroller der Cortex M-3 Klasse 
und die freie Wahl des "Betriebssystems" (bare metal, freertos, keil 
rtx, usw).

Die Software liest Sensoren aus (kurze Interrupts, Frequenz etwa 1 kHz, 
nachträgliche Filterung/Bearbeitung in dem entsprechenden Task/Modul) 
und verrechnet diese nach einer Decimation relativ aufwendig (das dauert 
bis zu 20 ms). Das passiert natürlich wieder in einem eigenen Task. 
Momentan ist jeder Task eine Funktion, deren Zustandswechsel durch FSM 
abgebildet werden.

Dann gibt es natürlich noch die Kommunikation mit der Außenwelt über 
CAN.

Ich stelle mir hier die Frage der Priorisierung:
Ich möchte, dass die Kommunikation nicht bis zu 20 ms still steht. 
Gleichzeitig MUSS der Berechnungstask nach 50 ms abgeschlossen sein.
Gestalte ich den Task blockierend, findet natürlich keine Kommunikation 
in der Zeit statt.
Im Moment kann die Berechnung an zwei sinnvollen Punkten unterbrochen 
werden (FSM) und das Programm springt zurück zur Hauptschleife. Das ist 
aber umständlich und wenn ich an weiteren Punkten "Multitasking" haben 
möchte, brauche ich weitere Zustände, die das ganze noch umständlicher 
machen.
Ein RTOS könnte den Task beliebig unterbrechen und ich brauche keine FSM 
mehr. Dafür könnte der Kommunikationstask bei entsprechend häufigem 
Aufrufen bei höherer Priorität als der Berechnungstask ebenjenen 
komplett blockieren. Hat die Kommunikation eine geringere Priorität, 
würde sie die Berechnung niemals unterbrechen und ich bräuchte keinen 
preemptiven Scheduler in diesem Fall.

Wie macht ihr das?

Danke und schöne Grüße,
Jan

von Pandur S. (jetztnicht)


Lesenswert?

> Im Moment kann die Berechnung an zwei sinnvollen Punkten unterbrochen
werden (FSM) und das Programm springt zurück zur Hauptschleife.

Die Berechnung unterteilen, oder noch besser Abkuerzen. Schwer zu 
glauben, dass ihr so viel Rechenleistung sinnvoll verballert.

von Jan K. (jan_k)


Lesenswert?

Sapperlot W. schrieb:
>> Im Moment kann die Berechnung an zwei sinnvollen Punkten unterbrochen
>> werden (FSM) und das Programm springt zurück zur Hauptschleife.
>
> Die Berechnung unterteilen, oder noch besser Abkuerzen. Schwer zu
> glauben, dass ihr so viel Rechenleistung sinnvoll verballert.
Weitere Unterteilungen werden umständlich, ginge aber. Per RTOS is sowas 
nicht lösbar?
Das ist übrigens ein Extended Kalman Filter mit 5 Zuständen und 
Fließkommazahlen. Ja kann man sicherlich optimieren, aber die Lesbarkeit 
und Anpassbarkeit ist gut.

von Georg (Gast)


Lesenswert?

Jan K. schrieb:
> Im Moment kann die Berechnung an zwei sinnvollen Punkten unterbrochen
> werden (FSM)

Warum nicht die Kommunikation in Interrupt-Routinen abwickeln (natürlich 
ohne Warteschleifen!!) und die Berechnung in der Main Loop?

Kommunikation lässt sich normalerweise als State Machine realisieren, so 
dass keine Warteschleifen vorkommen.

Georg

von Pandur S. (jetztnicht)


Lesenswert?

Berechnungen sollten sich auch im Mainloop erledigen lassen.

von Little B. (lil-b)


Lesenswert?

Jan K. schrieb:
> Wie macht ihr das?

Mit einer klassischen Betrachtung der Echtzeitfähigkeit
Welche Tasks werden wie oft aufgerufen und haben welche 
Echtzeitanforderung?
1
Task      Frequenz     Dauer     Timeout
2
----------------------------------------
3
Sensor 1    1kHz         ??         ??
4
Sensor 2    1kHz         ??         ??
5
Filter       ??         20ms       50ms
6
CAN          ??          ??         ??

Das lässt sich dann in ein Diagramm gießen, dass in etwa so wie hier 
aussehen könnte:
http://www.freertos.org/implementation/a00008.html

Daraus ergeben sich dann die Prioritäten.

Jan K. schrieb:
> Das ist übrigens ein Extended Kalman Filter mit 5 Zuständen und
> Fließkommazahlen. Ja kann man sicherlich optimieren, aber die Lesbarkeit
> und Anpassbarkeit ist gut.

Nimm einen M4F, damit sparst du ne menge Zeit, da Fließkomma in Hardware 
berechnet wird.

Desweiteren kannst du die Kommunikation mit den Sensoren über DMA laufen 
lassen, womit du die aktive Rechenzeit auf Mikrosekunden reduzieren 
kannst.

von Jan K. (jan_k)


Lesenswert?

Georg schrieb:
> Jan K. schrieb:
>> Im Moment kann die Berechnung an zwei sinnvollen Punkten unterbrochen
>> werden (FSM)
>
> Warum nicht die Kommunikation in Interrupt-Routinen abwickeln (natürlich
> ohne Warteschleifen!!) und die Berechnung in der Main Loop?
>
> Kommunikation lässt sich normalerweise als State Machine realisieren, so
> dass keine Warteschleifen vorkommen.
>
> Georg

Timing könnte da ein Problem werden. Das Protokoll ist ziemlich 
umfänglich, glaube nicht, dass es ne gute Idee ist, das in die ISR zu 
packen. Das Problem, dass bei dauerhafter "Beschallung" von außen die 
Berechnung blockiert wird bleibt dabei übrigens auch bestehen.

Ich benutze keine Warteschleifen...

Sapperlot W. schrieb:
> Berechnungen sollten sich auch im Mainloop erledigen lassen.

Werden sie ja im Moment.

Little B. schrieb:
> Jan K. schrieb:
>> Wie macht ihr das?
>
> Mit einer klassischen Betrachtung der Echtzeitfähigkeit
> Welche Tasks werden wie oft aufgerufen und haben welche
> Echtzeitanforderung?
> Task      Frequenz     Dauer     Timeout
> ----------------------------------------
> Sensor 1    1kHz         ??         ??
> Sensor 2    1kHz         ??         ??
> Filter       ??         20ms       50ms
> CAN          ??          ??         ??
>
> Das lässt sich dann in ein Diagramm gießen, dass in etwa so wie hier
> aussehen könnte:
> http://www.freertos.org/implementation/a00008.html
>
> Daraus ergeben sich dann die Prioritäten.
Ok, mal malen ;)
> Jan K. schrieb:
>> Das ist übrigens ein Extended Kalman Filter mit 5 Zuständen und
>> Fließkommazahlen. Ja kann man sicherlich optimieren, aber die Lesbarkeit
>> und Anpassbarkeit ist gut.
>
> Nimm einen M4F, damit sparst du ne menge Zeit, da Fließkomma in Hardware
> berechnet wird.
>
Wäre natürlich ne Möglichkeit. Aber eigentlich ist der Prozessor 
ausreichend schnell, es ist ja eher ein Timing Problem und eine Frage 
der Architektur. Das Problem kann ja auch verallgemeinert werden auf 
einen Task, der z.B. ne Minute braucht ;)

> Desweiteren kannst du die Kommunikation mit den Sensoren über DMA laufen
> lassen, womit du die aktive Rechenzeit auf Mikrosekunden reduzieren
> kannst.
Mach ich natürlich. Werden per DMA in nen Puffer gefüllt, aber hinterher 
muss noch etwas rumgerechnet werden (Skalierung, Temperaturkompensation, 
Digitale Filter usw).


Vielleicht lautet die allgemeinere Frage: Wie schafft ihr es, bei "Spam" 
über eine Kommunikationsschnittstelle noch handlungsfähig zu bleiben? 
Einführung einer minimal möglichen Zeit zwischen zwei 
Kommunikationsevents? Oder vielleicht eine Art dynamische Priorisierung?

Danke & schöne Grüße

von Georg (Gast)


Lesenswert?

Jan K. schrieb:
> Wie schafft ihr es, bei "Spam"
> über eine Kommunikationsschnittstelle noch handlungsfähig zu bleiben?

Ich glaube nicht, dass es mit CAN überhaupt möglich ist, den Prozessor 
auszulasten.

Jan K. schrieb:
> Das Protokoll ist ziemlich
> umfänglich, glaube nicht, dass es ne gute Idee ist, das in die ISR zu
> packen

Ich glaube auch nicht, dass man so ein Protokoll nicht per State Machine 
in kleinste Häppchen aufteilen kann - z.B. ist auf ein ankommendes 
Zeichen nur eine einfache Reaktion nötig und ein neuer Zustand, und 
selbst eine CRC-Berechnung ist überschaubar. Wir reden hier ja nicht von 
einem 8085.

Aber das müsste man natürlich konkret durchführen. Wenn du dir das nicht 
zutraust, ist ein fertiges Realtime OS schon sicherer.

Georg

von A. S. (Gast)


Lesenswert?

> Die Software liest Sensoren aus (kurze Interrupts, Frequenz etwa 1 kHz,
> nachträgliche Filterung/Bearbeitung in dem entsprechenden Task/Modul)

OK. jede MS ein oder zwei Interrupts mit etwa 10...100µs.

> Dann gibt es natürlich noch die Kommunikation mit der Außenwelt über CAN.

OK. Jede 10ms ein Telegramm mit 10 Byte, per (Timer-)Interrupt 
geringerer Priorität. (?)

> Ich möchte, dass die Kommunikation nicht bis zu 20 ms still steht.
Tut sie ja nicht. per Timer-Interrupt.

> Gleichzeitig MUSS der Berechnungstask nach 50 ms abgeschlossen sein.
Berechnungs-Task = Main-Loop. Ggf. mit CAN-Interrupt-Sperrungen falls 
notwendig.

> Gestalte ich den Task blockierend, findet natürlich keine Kommunikation
> in der Zeit statt.
OK, also CAN-Kommunikation in eigener Task. Auch OK. Aber dann CAN mit 
höherer Priorität und die Berechnung nicht blockierend.

> Im Moment kann die Berechnung an zwei sinnvollen Punkten unterbrochen
> werden (FSM) und das Programm springt zurück zur Hauptschleife.
???? Task oder SPS-Loop?

> Dafür könnte der Kommunikationstask bei entsprechend häufigem
> Aufrufen bei höherer Priorität als der Berechnungstask ebenjenen
> komplett blockieren.

Nein, wieso? Sie kann sich doch beliebig lange Schlafen legen, wenn sie 
z.B. 50% der letzten 50ms verbraucht hat. Oder sich mit der Berechnung 
Synchronisieren. Der genaue Ablauf hängt davon ab, wann genau die 
Berechnung starten muss und wie lange sie dann brauchen darf. Z.B. 
im 50ms-Takt starten und innerhalb der nächsten 50ms fertig? Oder 
maximal 50ms zwischen 2 Ergebnissen (das ist ein Unterschied (!sic)).

von A. S. (Gast)


Lesenswert?

Jan K. schrieb:
> Wie schafft ihr es, bei "Spam"
> über eine Kommunikationsschnittstelle noch handlungsfähig zu bleiben?

a) Kommunikationstask schlafen legen für x ms (Telegramme ignorieren)
b) verwerfen auf Auswerteebene wenn korrekte Anfragen aber zu schnell 
nacheinander
c) Zusammenfassen (falls Fifo): von 10Mal LED an/aus oder Anfrage des 
Wertes Y gewinnt nur der letzte
d) Handshake (gerne auch als Acknowledge!)
e) Den Sender (Spammer) kontrollieren
f) entsprechende Adressfilter auf oberster Ebene (für Telegramme, die 
nicht für mich sind)
g) bei Kommunikationsfehlern relativ lange Pausen (halbes Telegramm oder 
mehr)
h) Fehlermeldung

Die beste Waffe aber sind separate logische Kanäle. verschiedene 
Aufgaben bekommen verschiedene Kanäle, die alle parallel verarbeitet 
werden. Es werden alle Kanäle nacheinander abgearbeitet. Wenn ein Kanal 
spammt, gehen in diesem ggf. Telegrammer verloren, alle anderen 
reagieren noch in Echtzeit. Jeder Kanal hat seinen eigenen 
1-Telegramm-Fifo, je nach Anwendung auch x-Elemente, wichtig nur, dass 
sie wirklich parallel/unabhängig sind, nicht z.B. per Prio hirarchisch.

von ui (Gast)


Lesenswert?

Die Angaben sind doch etwas verwirrend, wie an den Reaktionen hier auch 
ablesbar ist.

Die Frage hängt ja von deinem Anwendungsfall ab, und da hast du noch zu 
wenig geschildert:
1) Die Berechnung muss nach 50ms abgeschlossen sein. Harte 
Echtzeitbedinung? Was machst du mit dem Ergebnis? Rausschreiben? Und 
startet unmittelbar dannach die nächste Berechnungsrunde? Wie wird die 
Berechnung getriggert, wenn sie nicht dauerhaft läuft?

2) Was heißt "soll nicht 20ms nichts tun" bzgl. der Kommunikation? Sind 
die Daten, die du versenden/empfangen willst, für die Berechnung 
wichtig? Oder sind das "ganz" andere Daten (Heartbeat etc.). Warum ist 
es wichtig, dass die Kommunikation nicht einfach 20ms schläft? Was hast 
du davon für einen Vorteil, wenn sie z.B. nach 5ms sendet, dafür aber 
nur einen Teil ihrer Nachrichten?

Und dann solltest du dir auch noch über andere Dinge Gedanken machen, 
die durchaus vorkommen:
- Was soll passieren wenn die Berechnung länger als 20ms oder noch 
schlimmer länger als 50ms dauert? Wenn du einen Programmierfehler drin 
hast, der auf einmal aus irgendeinem Grund verzögert? Was passiert dann?

Erklär erst mal genau was du willst und was du brauchst. Auch mit 
Prioritäten. Oftmals sind einfache Lösungen die besten, weil schwierige 
Lösungen oft (eigentlich nicht benötigte) Komplexität mit reinbringt.

von ui (Gast)


Lesenswert?

Ach ja zum RTOS:
Es gibt ja auch noch einen EDF Scheduler. Da könntest du (wenn du weißt 
wie lange was dauert und wie oft z.B. der Kommunikationstask drankommen 
soll) entsprechend verfahren.

von A. S. (Gast)


Lesenswert?

Achim S. schrieb:
> die alle parallel verarbeitet
> werden. Es werden alle Kanäle nacheinander abgearbeitet

gemeint ist: Es gibt z.B. 8 Eingangs-Kanäle. Jedes einkommende Telegramm 
wird untersucht, für welchen Kanal es ist und dort abgelegt 
(überschreibt ggf. das bisherige dort oder wird verworfen wenn voll). 
Die Eingangs-Telegrammspeicher liegen also "parallel" wie 8 Briefkästen 
nebeneinander.

Abgearbeitet werden sie nacheinander.
Zuerst Kanal-1: Ist ein Telegramm da, dann verarbeiten.
Danach Kanal-2: "
...
Dann wieder von neuem Kanal-1:

Wenn es wie hier darum geht, dass die Kommunikation zuviel Rechenzeit 
raubt, dann wird "von neuem" frühestens 50ms nach dem letzten Lauf oder 
30ms nach Kanal-8 gestartet.

von Peter (Gast)


Lesenswert?

Hallo Jan,
falls dein gewähltes RTOS Time Sliceing beherscht (wie z.B. FreeRTOS) 
kannst du beiden Task(Kommunikation und KF) die selbe Priorität 
zuteilen. Dann sollte dein Rechentask mindestens 50% der Rechenzeit 
abbekommen. Ob das jetzt schönes Design ist kann ich nicht sagen.
Wahrscheinlich wäre ein Buffern der Information via DMA und ein 
garantiertes zügiges abarbeiten oder falls dies nicht möglich ist das 
Auslösen eines Fehlerzustands die bessere Lösung. Weil bei hoher 
Kommunikationslast bleibt ja je nach dem trotzdem nicht genug Zeit um 
alle Nachrichten zu beantworten. Sprich du verlagerst das Problem zur 
Kommunikationsseite.
Gruß
Peter

von Peter D. (peda)


Lesenswert?

Jan K. schrieb:
> Wie schafft ihr es, bei "Spam"
> über eine Kommunikationsschnittstelle noch handlungsfähig zu bleiben?

Ich mache das immer nach dem Ping-Pong Prinzip. Master sendet Kommando, 
Slave antwortet.
Außerdem habe ich eine FIFO, d.h. der Master kann 8 Pakete 
hintereinander senden. Ist die FIFO voll, werden weitere Pakete 
verworfen und ein Fehlerbit gesetzt.

Den CAN betreibe ich mit 500kBit, d.h. die Nutzdatenrate ist maximal 
250kBit, das schafft selbst der AT90CAN128 bei 16MHz locker.

Die Auswertung erfolgt im Main. Ist das Main durch andere Tasks lange 
beschäftigt, könnte man dafür auch einen Softwareinterrupt niedriger 
Priorität verwenden.

An ein RTOS habe ich mich bisher nicht getraut. Dadurch, daß dann die 
Tasks in nicht vorhersehbaren Zeitscheiben und nicht vorhersehbarer 
Reihenfolge ausgeführt werden, ist die Datenkonsistenz sehr schwierig zu 
garantieren.
Ich mag lieber die volle Kontrolle über den Ablauf, sowie die 
Unmöglichkeit von Deadlocks.

von A. S. (Gast)


Lesenswert?

Peter D. schrieb:
> Den CAN betreibe ich mit 500kBit
Wenn möglich, ist das wirklich die beste Maßnahme gegen Spam: Die 
Baudrate so klein, dass selbst Back-To-Back-Telegramme genügend 
Rechenzeit für den Rest lassen. Nur ggf. darauf achten, dass die 
Fehlerbehandlung eines Zeichens oder eines Telegramms nicht länger 
dauert als die Normale Behandlung. Also z.b. Pause einlegen und auf 
sauberen Neustart achten.

von Guest (Gast)


Lesenswert?

Hallo Jan,

für welches RTOS hast du dich denn entschieden? Wir haben ähnliche 
Anforderungen und arbeiten mit SEGGER embOS. Der Vorteil ist das die 
Jungs sich mit solchen Sachen extrem gut auskennen und das quasi mit zum 
Service gehört einem bei so etwas zu beraten. Vielleicht einfach mal bei 
denen melden? Hat bei mir super geklappt. Vor allem kann man sich das 
dann alles mit SystemView grafisch anzeigen lassen und einfach 
überprüfen, ob alles so läuft, wie man es sich vorgestellt hat:
https://www.segger.com/systemview.html
Ich hatte da auch zuerst falsche Vorstellungen und musste lernen das ein 
RTOS nicht dafür sorgen kann die CPU zu mehr als 100% auszulasten. Aber 
es hilft einem unwahrscheinlich die Arbeit in mehrere Tasks aufzuteilen 
und alle Timings einzuhalten. Den Ansatz mit der klassischen Betrachtung 
der Echtzeitfähigkeit in einer Tabelle ist schon der richtige. Man muss 
sich halt entscheiden was für einen die höchste Echtzeitanforderung 
haben soll.

von Jan K. (jan_k)


Lesenswert?

Wow, das sind ja viele Beiträge, danke!

Ich versuche mal auf alle einzugehen.

Georg schrieb:
> Jan K. schrieb:
>> Das Protokoll ist ziemlich
>> umfänglich, glaube nicht, dass es ne gute Idee ist, das in die ISR zu
>> packen
>
> Ich glaube auch nicht, dass man so ein Protokoll nicht per State Machine
> in kleinste Häppchen aufteilen kann - z.B. ist auf ein ankommendes
> Zeichen nur eine einfache Reaktion nötig und ein neuer Zustand, und
> selbst eine CRC-Berechnung ist überschaubar. Wir reden hier ja nicht von
> einem 8085.
>
> Aber das müsste man natürlich konkret durchführen. Wenn du dir das nicht
> zutraust, ist ein fertiges Realtime OS schon sicherer.
Es ist eher eine Frage der Übersichtlichkeit und der Zeit. Das 
eigentliche Parsen der reintröpfelnden Daten könnte man aber wirklich 
auch als FSM machen, werde ich angehen.

Achim S. schrieb:
>> Die Software liest Sensoren aus (kurze Interrupts, Frequenz etwa
> 1 kHz,
>> nachträgliche Filterung/Bearbeitung in dem entsprechenden Task/Modul)
>
> OK. jede MS ein oder zwei Interrupts mit etwa 10...100µs.
>
>> Dann gibt es natürlich noch die Kommunikation mit der Außenwelt über CAN.
>
> OK. Jede 10ms ein Telegramm mit 10 Byte, per (Timer-)Interrupt
> geringerer Priorität. (?)
Jain - es gibt zwei Modi, einmal werden Daten mit 10 ms Zykluszeit 
broadcastet (Timer Interrupt), der mit einem Befehle deaktiviert werden 
kann. Dazwischen können natürlich trotzdem Telegramme eintreffen, auf 
die auch reagiert wird. In meinem Fall geht es um letzteren 
Betriebsmodus, ich möchte möglichst schnelle und kontinuierliche interne 
Größen auslesen.
Allerdings könnte es sein, dass die Gegenstelle eben nicht wartet, bis 
eine Antwort kam. Ist natürlich eine Fehlkonstruktion, aber dieser 
Fehlerfall sollte abgefangen werden.
>> Ich möchte, dass die Kommunikation nicht bis zu 20 ms still steht.
> Tut sie ja nicht. per Timer-Interrupt.
Aber eben nur die broadcast Nachricht.
>
>> Gleichzeitig MUSS der Berechnungstask nach 50 ms abgeschlossen sein.
> Berechnungs-Task = Main-Loop. Ggf. mit CAN-Interrupt-Sperrungen falls
> notwendig.
>
So ist es im Moment, allerdings wird der CAN nicht gesperrt.
>> Gestalte ich den Task blockierend, findet natürlich keine Kommunikation
>> in der Zeit statt.
> OK, also CAN-Kommunikation in eigener Task. Auch OK. Aber dann CAN mit
> höherer Priorität und die Berechnung nicht blockierend.
Sorry, das war nur eine Überlegung. Momentan gibt es noch keine "echten" 
preemptive Tasks. Die Kommunikation findet (ausgenommen der 10 ms 
Broadcast) ebenfalls im Main Loop statt.
>> Im Moment kann die Berechnung an zwei sinnvollen Punkten unterbrochen
>> werden (FSM) und das Programm springt zurück zur Hauptschleife.
> ???? Task oder SPS-Loop?
siehe oben :) Ich habe in Gedanken dann angefangen, ein Rtos 
einzusetzen...
>> Dafür könnte der Kommunikationstask bei entsprechend häufigem
>> Aufrufen bei höherer Priorität als der Berechnungstask ebenjenen
>> komplett blockieren.
>
> Nein, wieso? Sie kann sich doch beliebig lange Schlafen legen, wenn sie
> z.B. 50% der letzten 50ms verbraucht hat. Oder sich mit der Berechnung
> Synchronisieren. Der genaue Ablauf hängt davon ab, wann genau die
> Berechnung starten muss und wie lange sie dann brauchen darf. Z.B.
> im 50ms-Takt starten und innerhalb der nächsten 50ms fertig? Oder
> maximal 50ms zwischen 2 Ergebnissen (das ist ein Unterschied (!sic)).
Die Berechnung und die Ausgabe müssen nicht synchronisiert werden.
Die Berechnung startet, sobald die dafür benötigten Sensorwerte 
gefiltert und dezimiert wurden (alle 100 ms, somit ist theoretisch für 
alle Berechnungen mehr als genug Zeit). Es ist keine harte Echtzeit 
gefordert, insofern muss ich das "MUSS nach 50 ms fertig sein" etwas 
revidieren, sorry. Aber es darf sich halt nicht aufschaukeln, sodass die 
Latenz immer größer wird. Und es wäre schön, wenn die Deadline 
eingehalten würde.

Vielen Dank noch für deine 2. Antwort Achim, da stehen ein paar gute 
Ideen drin, die ich mir zu Gemüte führen werde.

ui schrieb:
> Die Angaben sind doch etwas verwirrend, wie an den Reaktionen hier auch
> ablesbar ist.
>
Ja, merke ich auch. Tut mir Leid.
> Die Frage hängt ja von deinem Anwendungsfall ab, und da hast du noch zu
> wenig geschildert:
> 1) Die Berechnung muss nach 50ms abgeschlossen sein. Harte
> Echtzeitbedinung? Was machst du mit dem Ergebnis? Rausschreiben? Und
> startet unmittelbar dannach die nächste Berechnungsrunde? Wie wird die
> Berechnung getriggert, wenn sie nicht dauerhaft läuft?
>
Sie wird nach Beendigung der Sensordaten-Verarbeitung getriggert. Das 
Ergebnis wird rausgeschrieben. Es ist keine harte Echtzeit, die 
Verzögerungen dürfen sich aber nicht akkumulieren.
> 2) Was heißt "soll nicht 20ms nichts tun" bzgl. der Kommunikation? Sind
> die Daten, die du versenden/empfangen willst, für die Berechnung
> wichtig? Oder sind das "ganz" andere Daten (Heartbeat etc.). Warum ist
> es wichtig, dass die Kommunikation nicht einfach 20ms schläft? Was hast
> du davon für einen Vorteil, wenn sie z.B. nach 5ms sendet, dafür aber
> nur einen Teil ihrer Nachrichten?
Nein, die sind nicht für die Berechnung wichtig. Es handelt sich um 
interne Daten zu Debug/Visualisierungszwecke, die am PC dargestellt 
werden.
>
> Und dann solltest du dir auch noch über andere Dinge Gedanken machen,
> die durchaus vorkommen:
> - Was soll passieren wenn die Berechnung länger als 20ms oder noch
> schlimmer länger als 50ms dauert? Wenn du einen Programmierfehler drin
> hast, der auf einmal aus irgendeinem Grund verzögert? Was passiert dann?
Es sollte geloggt werden und auch kommuniziert. Dafür gibt es bereits 
ein Status Byte. Aber ich habe mir noch gar nicht überlegt, wie ich ein 
eventuelles Verpassen überhaupt detektiere. Der Cyclecounter ist da 
sinnvoll, oder?
> Erklär erst mal genau was du willst und was du brauchst. Auch mit
> Prioritäten. Oftmals sind einfache Lösungen die besten, weil schwierige
> Lösungen oft (eigentlich nicht benötigte) Komplexität mit reinbringt.
Ich merke gerade selber, dass das eigentliche Problem woanders liegt. Es 
ist im Grunde nicht die lange Berechnung, sondern der Fakt, dass ich die 
Kommunikation robuster gestalten muss.

Peter schrieb:
> Hallo Jan,
> falls dein gewähltes RTOS Time Sliceing beherscht (wie z.B. FreeRTOS)
> kannst du beiden Task(Kommunikation und KF) die selbe Priorität
> zuteilen. Dann sollte dein Rechentask mindestens 50% der Rechenzeit
> abbekommen. Ob das jetzt schönes Design ist kann ich nicht sagen.
> Wahrscheinlich wäre ein Buffern der Information via DMA und ein
> garantiertes zügiges abarbeiten oder falls dies nicht möglich ist das
> Auslösen eines Fehlerzustands die bessere Lösung. Weil bei hoher
> Kommunikationslast bleibt ja je nach dem trotzdem nicht genug Zeit um
> alle Nachrichten zu beantworten. Sprich du verlagerst das Problem zur
> Kommunikationsseite.
> Gruß
> Peter

Hi Peter,
ja tut es. Heißt da Round-Robin Scheduling und teilt zur Ausführung 
bereite Tasks in gleiche "slices" ein. Wenn nicht alle Nachrichten 
beantwortet werden können ist das weniger schlimm als eine verpasste 
Berechnung.

Ist das unschönes Design?

Achim S. schrieb:
> Peter D. schrieb:
>> Den CAN betreibe ich mit 500kBit
> Wenn möglich, ist das wirklich die beste Maßnahme gegen Spam: Die
> Baudrate so klein, dass selbst Back-To-Back-Telegramme genügend
> Rechenzeit für den Rest lassen. Nur ggf. darauf achten, dass die
> Fehlerbehandlung eines Zeichens oder eines Telegramms nicht länger
> dauert als die Normale Behandlung. Also z.b. Pause einlegen und auf
> sauberen Neustart achten.

Da muss ich  mal rechnen, wie viel Zeit im schlimmsten Fall übrig 
bleibt.

Peter D. schrieb:
> Jan K. schrieb:
>> Wie schafft ihr es, bei "Spam"
>> über eine Kommunikationsschnittstelle noch handlungsfähig zu bleiben?
>
> Ich mache das immer nach dem Ping-Pong Prinzip. Master sendet Kommando,
> Slave antwortet.
> Außerdem habe ich eine FIFO, d.h. der Master kann 8 Pakete
> hintereinander senden. Ist die FIFO voll, werden weitere Pakete
> verworfen und ein Fehlerbit gesetzt.
>
Es gibt hier auch einen Ausgangs-FIFO. Ist allerdings etwas kleiner als 
bei dir. Ping Pong machen wir ja.
> Den CAN betreibe ich mit 500kBit, d.h. die Nutzdatenrate ist maximal
> 250kBit, das schafft selbst der AT90CAN128 bei 16MHz locker.
>
Ok..
> Die Auswertung erfolgt im Main. Ist das Main durch andere Tasks lange
> beschäftigt, könnte man dafür auch einen Softwareinterrupt niedriger
> Priorität verwenden.
>
Software Interrupt ist auch eine interessante Idee, z.B. der SVC Handler 
oder so?

Guest schrieb:
> Hallo Jan,
>
> für welches RTOS hast du dich denn entschieden? Wir haben ähnliche
> Anforderungen und arbeiten mit SEGGER embOS. Der Vorteil ist das die
> Jungs sich mit solchen Sachen extrem gut auskennen und das quasi mit zum
> Service gehört einem bei so etwas zu beraten. Vielleicht einfach mal bei
> denen melden? Hat bei mir super geklappt. Vor allem kann man sich das
> dann alles mit SystemView grafisch anzeigen lassen und einfach
> überprüfen, ob alles so läuft, wie man es sich vorgestellt hat:
> https://www.segger.com/systemview.html
> Ich hatte da auch zuerst falsche Vorstellungen und musste lernen das ein
> RTOS nicht dafür sorgen kann die CPU zu mehr als 100% auszulasten. Aber
> es hilft einem unwahrscheinlich die Arbeit in mehrere Tasks aufzuteilen
> und alle Timings einzuhalten. Den Ansatz mit der klassischen Betrachtung
> der Echtzeitfähigkeit in einer Tabelle ist schon der richtige. Man muss
> sich halt entscheiden was für einen die höchste Echtzeitanforderung
> haben soll.

Heho,
für noch gar keines. Eine Überlegung ist, CMSIS-RTOS oder CMSIS-RTOS++ 
einzusetzen, um unabhängiger von der konkreten Implementation zu werden, 
aber zurzeit wird noch keines eingesetzt.
Dass ein RTOS nicht zaubern kann und mehr als 100 % rauskitzeln kann ist 
mir komplett klar. Es ist ja eher eine Timing Geschichte.

Danke für eure Antworten! Ich muss nochmal über einiges nachdenken und 
melde mich dann nochmal :)

Schöne Grüße,
Jan

von Guest (Gast)


Lesenswert?

CMSIS-RTOS ist kein RTOS sondern nur ein Abstraktionslayer. Tu dir das 
aber bitte nicht an. Das Ding ist reiner Marketingkram von ARM und 
technisch total sinnfrei. Wenn man wöchentlich sein RTOS wechselt macht 
man eh was falsch ;-).

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

Peter D. schrieb:
>
> An ein RTOS habe ich mich bisher nicht getraut. Dadurch, daß dann die
> Tasks in nicht vorhersehbaren Zeitscheiben und nicht vorhersehbarer
> Reihenfolge ausgeführt werden, ist die Datenkonsistenz sehr schwierig zu
> garantieren.
> Ich mag lieber die volle Kontrolle über den Ablauf, sowie die
> Unmöglichkeit von Deadlocks.

Ich kann die Position verstehen, aber die Vorteile dauern nur eine 
gewisse Zeit. Solange die Aufgabenstellung relativ klein und 
übersichtlich ist, reicht eine Message Pump in main() als 
"handgestricktes OS" (mehr oder weniger als das ist es eigentlich nicht) 
aus, aber sobald neue features oder Anforderungen dazu kommen, wird das 
Ganze schnell zu einem unleserlichen und unwartbaren Moloch.

Du kannst fast Alle RTOS auch als nicht preemptiv konfigurieren, dann 
gibt es keine Zeitscheiben, aber trotzdem Prioritätssteuerung (d.h. 
tasks höhrerer Priorität leeren tasks niedrigerer Priorität, aber tasks 
gleicher Priorität müssen sich explizit die CPU abgeben).

Ich schildere den Umstieg auf ein RTOS beispielhaft in Kapitel 3 von 
(jaja, schon gut).

Bei einem meiner Kunden (Zk Bereich) war die main message pump für einen 
Leser, der "nichts Anderes" machen muss als Karten zu lesen, die Werte 
zum Zk Terminal zu kommunizieren und im Gegenzug LEDs leuchten zu 
lassen, schon nach der ersten Anforderung komplett überfordert. Bei der 
nächsten Version haben wir dann ein RTOS benutzt (Konfiguration: 256 k 
internes Flash und 32 K internes RAM and that's it), und es funktioniert 
prima.

von ui (Gast)


Lesenswert?

Peter D. schrieb:
> Ich mag lieber die volle Kontrolle über den Ablauf, sowie die
> Unmöglichkeit von Deadlocks.

Gibt es nicht. Das würde implizieren du
- machst keine Programmierfehler
- hast nie auch nur irgendeinen Designfehler (absichtlich/unabsichtlich)

Und jeder weiß, dass beides (oder auch nur eines davon) nicht 
funktioniert, zumindest nicht in Projekten/Programmen die über UART 
rein, rechne A+B, UART raus hinausgehen.

von Mehmet K. (mkmk)


Lesenswert?

Guest schrieb:
> CMSIS-RTOS ist kein RTOS sondern nur ein Abstraktionslayer. Tu dir das
> aber bitte nicht an. Das Ding ist reiner Marketingkram von ARM und
> technisch total sinnfrei. Wenn man wöchentlich sein RTOS wechselt macht
> man eh was falsch ;-).

Ich arbeite seit Jahren mit CMSIS-RTOS. Und bin sehr zufrieden damit.
Für einfache Sachen, wo es nur darum geht, ein paar Sensoren 
einzuselesen und Berechnungen durchzuführen, setze ich ganz gerne 
Protothreads ein.
http://dunkels.com/adam/pt
Die Anforderungen des TO waeren aus meiner Sicht für Protothreads 
geeignet.

von Michael A. (micha54)


Lesenswert?

Peter D. schrieb:
> Ich mag lieber die volle Kontrolle über den Ablauf, sowie die
> Unmöglichkeit von Deadlocks.


Hallo,

also Deadlocks entstehen, wenn 2 Prozesse gegenseitig Ressourcen 
blockieren. Das setzt voraus, dass diese dynamisch angefordert werden.
Das macht man in diesem Fall aber nicht, man fordert sie stattdessen 
statisch beim Programmstart (Speicher) an bzw. sie sind implizit fest 
zugeordnet (Ports oder andere Hardware).

Blockaden durch Warten auf Ereignisse die nie eintreten sind keine 
Deadlocks und können auch ohne RTOS entstehen. Ich erinnere mich da an 
meinen UART per Interrupt, bei dem unter gewissen Umständen der 
Interrupt ausblieb. So was ist ein einfacher BUG (edit: obwohl es nicht 
einfach zu debuggen war).

Was die Übersichtlichkeit anbelangt ist eine RTOS-Implementierung meist 
enger am Problem programmiert und damit besser zu Warten.

Gruß,
Michael

von Peter D. (peda)


Lesenswert?

Michael A. schrieb:
> also Deadlocks entstehen, wenn 2 Prozesse gegenseitig Ressourcen
> blockieren. Das setzt voraus, dass diese dynamisch angefordert werden.

Nö, dynamisch ist da nichts.
Ich programmiere vorwiegend Steuerungen, wo viele Tasks untereinander 
kommunizieren müssen. Dazu habe ich einen globalen Datensatz. Als 
Main-Loop kein Problem, jede Task liest Daten, verarbeitet sie und 
schreibt die Änderungen zurück.
Beim RTOS müßte aber jede Task die Daten für alle anderen sperren, damit 
ihr nicht die Daten unterm Hintern weggeändert werden oder halb neue, 
halb alte Daten drin stehen. Da ist ein Deadlock quasi unvermeidlich.
Für die Steuerung ist es wichtig, daß alle Daten in einer definierten 
Reihenfolge und immer vollständig abgearbeitet werden. Z.B. wäre es 
blöd, wenn erst die Ausgabetask die Daten ausgibt, dann die 
Verarbeitungstask rankommt und dann die Eingabetask. Damit würde ich 
unnötig Zeit verlieren bzw. schlimmer noch, die Regelung hätte kein 
definiertes Zeitverhalten.

Ein RTOS ist dann schön, wenn die Tasks weitgehend unabhängig 
voneinander ihr Ding machen können.

P.S.:
Es kann natürlich sein, daß es bessere Konzepte für eine Steuerung gibt, 
als ich es verwende. Nur kenne ich (noch) keins.

von Tom (Gast)


Lesenswert?

Peter D. schrieb:
> Ein RTOS ist dann schön, wenn die Tasks weitgehend unabhängig
> voneinander ihr Ding machen können.

Jain, ich denke deine Steuerungen sind ein Sonderfall in dem es ohne 
RTOS einfacher funktioniert aber in deinem Beispiel ist es kein Problem 
mit Semaphoren den gegenseitigen Zugriff zu verhindern. Vernünftige RTOS 
haben dann auch Methoden implementiert um solche Deadlocks zu vermeiden 
(Priority inheritance, Priority ceiling protocol).
Ich hatte mir das mal bei verschiedenen RTOS angeschaut und es scheint 
das embOS bis jetzt das einzige RTOS ist das Priority inheritance 
komplett implementiert hat (bei allen anderen gibt es tatsächlich Fälle, 
in denen es zu Problemen kommen kann). Demnach sollte man natürlich 
schon schauen welches RTOS man benutzt.

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

Peter D. schrieb:
> Beim RTOS müßte aber jede Task die Daten für alle anderen sperren, damit
> ihr nicht die Daten unterm Hintern weggeändert werden oder halb neue,
> halb alte Daten drin stehen. Da ist ein Deadlock quasi unvermeidlich.
>

Naja, so stimmt es natürlich nicht. Ein deadlock setzt immer ein 
zirkuläres Warten mindestens zweier tasks auf mindestens zwei 
Synchronisationsressourcen voraus. In deinem Fall würde eine 
Mutexvariable zum "globalen" Sperren des kritischen Datensatzes 
ausreichen, und bei einem Mutex kann es keinen deadlock geben.

Aber deine Argumentation ist natüclich nicht ganz falsch; man hat nichts 
von einem RTOS, wenn am Ende des Tages der gesamte Kontrollfluß doch 
wieder durchserialisiert wird, dann hat man im Gegenteil noch die 
penalty durch den Kontext Switch Overhead.

> Ein RTOS ist dann schön, wenn die Tasks weitgehend unabhängig
> voneinander ihr Ding machen können.
>

Auch das stimmt, aber bei genauer Analyse gibt es wenig Fälle, in denen 
der Kontrollfluss streng serialisiert sein muss; meistens ist die 
Abfolge im Kopf strikter als sie sein muss, und man erkennt beim drüber 
nachdenken Dinge, die auch nebenläufig sein können.

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

Tom schrieb:
> Peter D. schrieb:
>> Ein RTOS ist dann schön, wenn die Tasks weitgehend unabhängig
>> voneinander ihr Ding machen können.
>
> Jain, ich denke deine Steuerungen sind ein Sonderfall in dem es ohne
> RTOS einfacher funktioniert aber in deinem Beispiel ist es kein Problem
> mit Semaphoren den gegenseitigen Zugriff zu verhindern. Vernünftige RTOS
> haben dann auch Methoden implementiert um solche Deadlocks zu vermeiden
> (Priority inheritance, Priority ceiling protocol).
> Ich hatte mir das mal bei verschiedenen RTOS angeschaut und es scheint
> das embOS bis jetzt das einzige RTOS ist das Priority inheritance
> komplett implementiert hat (bei allen anderen gibt es tatsächlich Fälle,
> in denen es zu Problemen kommen kann). Demnach sollte man natürlich
> schon schauen welches RTOS man benutzt.



Nein, FreeRTOS macht bei Mutexen auch priority inheritance, aber kein 
PCP.

Es ist übrigens ein sehr gängiger Fehler, Mutexe und Semaphoren 
durcheinanderzumischen. Das sind zwei sehr verschiedene Konzepte, und in 
90% der Fälle, wo Jemand Semaphore sagt/schreibt sind eigentlich Mutexe 
gemeint.

von Tom (Gast)


Lesenswert?

Ruediger A. schrieb:
> Nein, FreeRTOS macht bei Mutexen auch priority inheritance, aber kein
> PCP.

Ja, aber nicht vollständig. Das Problem taucht dann auf wenn man mehrere 
Tasks hat mit mehreren Mutexen. Zwei Tasks und eine Mutex funktioniert 
bei den meisten noch problemlos aber man kann sich auch komplizierte 
Fälle ausdenken und da funktioniert es z.B. bei FreeRTOS nicht mehr. Bei 
embOS ist das Konzept stark erweitert worden. Es geht letztlich um die 
Problematik zu wissen welche Priorität man man wann von wem erbt.

> Es ist übrigens ein sehr gängiger Fehler, Mutexe und Semaphoren
> durcheinanderzumischen. Das sind zwei sehr verschiedene Konzepte, und in
> 90% der Fälle, wo Jemand Semaphore sagt/schreibt sind eigentlich Mutexe
> gemeint.

Jep, ich gehöre zu den 90% ;-), an der Stelle ist natürlich Mutex 
gemeint.

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

Tom schrieb:
>
> Ja, aber nicht vollständig. Das Problem taucht dann auf wenn man mehrere
> Tasks hat mit mehreren Mutexen. Zwei Tasks und eine Mutex funktioniert
> bei den meisten noch problemlos aber man kann sich auch komplizierte
> Fälle ausdenken und da funktioniert es z.B. bei FreeRTOS nicht mehr. Bei
> embOS ist das Konzept stark erweitert worden. Es geht letztlich um die
> Problematik zu wissen welche Priorität man man wann von wem erbt.
>

als ich das zuerst gelesen habe, klang es so wie "Mein Vetter 3. Grades 
hat einen Klassenkameraden, dessen Schwiegermutter gelesen hat..." mAW 
etwas inkonkret.

Da mich das Thema aber interessiert, habe ich etwas gespielt und 
rumcodiert und tatsächlich etwas gefunden, was in die Richtung geht:

http://ruediger-asche.de/Blog

Ist es das? Wenn ja, wie löst embOS das Problem?

Danke!

von Tom (Gast)


Lesenswert?

Ruediger A. schrieb:
> als ich das zuerst gelesen habe, klang es so wie "Mein Vetter 3. Grades
> hat einen Klassenkameraden, dessen Schwiegermutter gelesen hat..." mAW
> etwas inkonkret.

lach ehrlich gesagt bin ich näher dran als du denkst ;-).

Ruediger A. schrieb:
> Ist es das? Wenn ja, wie löst embOS das Problem?

Ich habe den Blog nicht gelesen aber embOS löst das Problem indem man 
sich Gedanken darum macht welche Priorität man wann von wem erbt. 
Details kann ich hier nicht nennen da Segger bestimmt nicht den 
Wettbewerb schlau machen möchte ;-).

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

Tom schrieb:
> Ruediger A. schrieb:
>> als ich das zuerst gelesen habe, klang es so wie "Mein Vetter 3. Grades
>> hat einen Klassenkameraden, dessen Schwiegermutter gelesen hat..." mAW
>> etwas inkonkret.
>
> lach ehrlich gesagt bin ich näher dran als du denkst ;-).
>
> Ruediger A. schrieb:
>> Ist es das? Wenn ja, wie löst embOS das Problem?
>
> Ich habe den Blog nicht gelesen...

Solltest Du aber, Du bist in dem blog entry dankend erwähnt ;-)

Ich habe das Problem mal mit Richard Barry (Papa von FreeRTOS) 
diskutiert (der ist sehr offen für technische Diskussionen von allen 
Seiten und antwortet auch in der Regel sehr schnell und selbst).

Bei FreeRTOS wird einfach weniger Information vorgehalten. Wenn eine 
Task X eine von Task Y besetzte Mutex versucht zu kriegen, ist mit der 
Mutex eine Rückwärtsreferenz auf Y verknüpft, was es FreeRTOS erlaubt, 
die Priorität von Y temporär entsprechend anzupassen, und zwar in 
Abhängigkeit von der Priorität von X (das ist "1st level priority 
inheritance").

Soweit so gut, aber spannend wird es, wenn X selber nun später das 
Objekt von Priority Inheritance wird. D.h. eine Task Z würde über 
denselben Mechanismus die Priorität von X umsetzen - in dem Moment weiss 
FreeRTOS zwar die momentane Priorität von X, aber es fehlt die 
Rückwärtsverkettung zu Y, mit der umgekehrt Y nun die Priorität von Z 
erben könnte ("2nd level priority inheritance"). Da zwar eine Mutex 
unter FreeRTOS mit ihrem momentanen Halter assoziiert ist, aber 
umgekehrt eine Task keine Informationen darüber vorhält, welche Mutexes 
sie gerade hält, fehlt die Information, die wir brauchen würden, um PI 
durchgehend implementieren zu können.

Eine saubere Lösung würde erfordern, dass eben eine solche 
Rückwärtsverfolgungskette aufgebaut würde. Das wäre vermutlich auch der 
Schlüssel zu einer Deadlockerkennung (die dann aber ja wieder nur aus 
Mutexbenutzung resultierende deadlocks erkennen könnte und wie weiter 
oben beschrieben auch sonst nur beschränkten Wert hätte).

So eine Rückwärtsverkettung ist bereits mehrmals an Richard 
herangetragen worden, aber aus verschiedenen Gründen bislang nicht 
realisiert. Ich vermute aber auch, dass so eine mehrstufige PI Potential 
für Nachfolgeprobleme beinhaltet, z.B. würde bei einer zweistufigen 
Anhebung der Priorität von Y die erste Stufe komplett verloren gehen, 
d.h. die Priorität Y wird grundsätzlich niemals auf die (zwischendurch 
gültige) Priorität von X zurückfallen, sondern immer auf ihre 
Basispriorität, was in manchen Szenarien zu unerwartetem Verhalten 
führen könnte (darüber muss ich nochmal nachdenken und das in den Blog 
nachtragen).

In jedem Fall Danke nochmal für den Input!

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.