Forum: Mikrocontroller und Digitale Elektronik Wann lohnt ein RTOS (STM32)


von Freddy (Gast)


Lesenswert?

Hallo

Ich wollte mal Allgemein fragen wann sich ein RTOS wirklich lohnt.
Hintergrund ist das ich schon recht lange Mikrokontroller programmiere 
und mir meinen parallelen Betrieb sozusagen selber baue indem ich ein 
Scheduler zeitlich endsprechende Funktionen ablaufen lassen. Also 
ultraeinfach durch zeitliche Interrups oder mitlaufende Handler in der 
main. (Spezialbegriffe hierfür sind mir jetzt nicht so geläufig, hab es 
mir selber über die Jahre beigebracht.

Bücher wie z.B. "Echtzeitbetriebssysteme-Brinkschulte" haben mein 
Interesse geweckt und ich habe hier schon ein paar Beiträge gelesen. 
Sofern Programme im Ablauf geschildert wurden habe ich nicht immer den 
Sinn in einem Rtos gesehen, benötigt schließlich einiges an Flash und 
Ram.

Bitte schildert mir doch mal in ein paar Sätzen wann ihr sagt das man 
ein Softwareproblem nur mit RTOS lösen kann bzw. sollte. Auf letzteres 
lege ich besonderen Wert da es die Erfahrung zeigt, denke ich.

Ich arbeite mit verschiedenen Schnittstellen wie meistens Can, Uarts, 
I2C alles mit Ringpuffer und Protokollen. Flashbedarf ist optimiert ca. 
50K bis 70K (da pendeln sich meine Projekte im Moment ein). FreeRtos 
steht im Raum, da ich mich freuen wurde alles nicht immer auf einander 
abstimmen zu müssen und es danach eben nur statisch läuft. Ebenfalls 
würde mich auch eine Art Dateisystem interessieren wo man Files als 
Programme ausführen kann, bei SD Karten. Natürlich einfachste Basis, 
soll ja mit STM32 laufen.
Dazu bei Interesse mehr.

von JojoS (Gast)


Lesenswert?

Zu dem Thema gibts hier im Forum viele und lange Diskussionen, die Suche 
zb nach FreeRTOS liefert dir Lesestoff für die ganze Nacht.
Ich spiele auch gerade mit FreeRTOS auf einem lpcxpresso (LPC1769) und 
es gefällt mir sehr gut. Vorteile sehe ich in sauberer Aufteilung der 
Apps in mehrere Tasks, verschiedene Prios, fertige Queues, ISR Support. 
Im Org FreeRTOS Download sind auch viele Beispiele für STM32 drin, damit 
kriegt man den Einstieg gut hin.

von JojoS (Gast)


Lesenswert?

Flashbedarf ist bei FreeRTOS zb nicht sehr groß, lässt sich auch noch 
per defines in einer config Datei durch weglassen nicht benötigter 
Features skalieren. RAM Bedarf ist bei OS höher weil jede Task einen 
eigenen Stack bekommt. Da muss man natürlich vermeiden große Datenmengen 
in Stackvariablen zu packen.
Für nachladbare Apps brauchst du einen Proz mit ext Speicherinterface.

von Freddy (Gast)


Lesenswert?

Ich habe vor einen STM32F205 oder 207 zu nehmen, für einen Cortex M3 
haben die wohl die meiste Power. Hae mal einen Vergleich gesehen zum 
ARM9. Außer der MMU hatte der Cortes mehr Power als ein Arm9 bei 250 
Mhz, aber das nur am Rande.
Die haben auch ein Speicherinterface.

von gerhard (Gast)


Lesenswert?

>Ich habe vor einen STM32F205 oder 207 zu nehmen, für einen Cortex M3
>haben die wohl die meiste Power. Hae mal einen Vergleich gesehen zum
>ARM9. Außer der MMU hatte der Cortes mehr Power als ein Arm9 bei 250
>Mhz, aber das nur am Rande.
Da musst du dir aber eine mickrigen arm9 angesehen haben (vermutlich den 
von ST). in der regel hat ein arm9 code und data cache und damit bringt 
der arm9 ca. 200 bis 400 mips. die wirst du mit einem cortex m3/4 nie 
erreichen.

gruss
gerhard

von Freddy (Gast)


Lesenswert?

Ohh, da habe ich aber einen in seiner Ehre verletzt.
Die Daten stammen aber von "ARM" selber. Wer letztlich wievil Mips hat 
sagt ehe nicht so wirklich viel aus und spielt auch für mein Problem 
keine Rolle.

von gerhard (Gast)


Lesenswert?

>Ohh, da habe ich aber einen in seiner Ehre verletzt.
nein, aber du hast eine aussage getroffen die so nicht stimmt.

>Die Daten stammen aber von "ARM" selber.
welche "daten" sollen das sein?
von welchem arm9 (arm926 oder arm966) sprichst du?

gruss
gerhard

von Peter D. (peda)


Lesenswert?

Freddy schrieb:
> Ich arbeite mit verschiedenen Schnittstellen wie meistens Can, Uarts,
> I2C alles mit Ringpuffer und Protokollen.

Das dürfte alles prima mit Interrupts (Datenverkehr) und Mainloop 
(Auswertung) zu lösen sein. Es läuft ja alles schön sequentiell ab. Ein 
RTOS kann da nicht richtig punkten.


Peter

von Super G. (Gast)


Lesenswert?

@Peter

Da will ich mich mal an Freddys Frage anhängen: Wo und wann punktet den 
nun ein RTOS?

von Oliver J. (skriptkiddy)


Lesenswert?

Super Grobi schrieb:
> Da will ich mich mal an Freddys Frage anhängen: Wo und wann punktet den
> nun ein RTOS?
Der übliche Ansatz ist es auf ein RTOS zu verzichten und alles mit einer 
Hauptschleifen, Koroutinen und Interrupts zu erledigen. Das läuft dann 
meist auf so etwas wie ein kooperatives Roundrobin-Scheduling hinaus. 
Jedenfalls für die Koroutinen. Wenn man aber viel zu viele Aufgaben zu 
erledigen hat, die auch noch unterschiedlich priorisiet ablaufen müssen, 
dann läuft das mit dem Ansatz nicht mehr so ohne Weiteres. An dieser 
Stelle ist es dann IMHO sinnvoll ein RTOS einzusetzen.

Gruß Oliver

von Purzel H. (hacky)


Lesenswert?

> Da will ich mich mal an Freddys Frage anhängen: Wo und wann punktet den
> nun ein RTOS?

Das Ganze ist ein gleitender Uebergang.

Man beginnt bei einer Mainloop mit einer odere mehreren 
Zusatndsmaschinen drin. So kann man gut verschiedene Timings von 
verschiedenen unabhaengigen Prozessen abbilden. Irgendwo haben diese 
Prozesse vielleicht eine Abhaengigkeit. Mit zunehmender abhaengigkeit 
dieser Prozesse muessen mehr Daten ausgetauscht werden. Dann wird die 
Zustandsmaschine unuebersichtlich.
Das Wichtigste dabei : Es wird nirgendwo ausser an einem Ort im Main 
gewartet. Keine Delays, nichts dergleichen.

Das naechste ist ein Realtime Kernel. Eine zulinkbare Library, die einen 
Scheduler, Tasks/Prozesse und pro Task/ Prozess unabhaengigen Stack zur 
Verfuegung stellt. Sowie alles was zur Intertask kommunikation noetig 
ist. Das waeren dann Events, Semaphore, Mailboxen, Queues. Es gibt dann 
zwei Ausfuehrungen. Einen kooperativen Scheduler und einen praeemptiven 
Scheduler. Der Erste, schaltet die Tasks/Prozesse um wenn die auf ein 
Wait laufen. Das bedeutet die Tasks muessen so geschrieben sein, dass 
sie hinreichend oft die Rechenzeit abgeben. Ein Task/Prozess laeuft 
solange wie er auf ein Wait laeuft. Der zweite Scheduler, der 
Praeemptive unterbricht zusaetzlich die Task/Prozesse noch zu 
festgelegten Zeitscheiben. Wenn man definierte, harte Antwortzeiten des 
Systems haben muss ist ein praeemptiver Scheduler einfacher. Dafuer muss 
man mit den Variablen besser aufpassen, das die ja zwischendurch 
veraendert werden koennen. Das kann man dem System ueberlassen und sie 
mit Semaphoren schuetzen, was das System langsamer macht. Ein 
kooperatives System ist daher schneller.
Interrupts haben gegenueber allem natuerlich Prioritaet. Ein Interrupt 
loest ueblicherweise (irgendwann) einen Event aus. Man kann zB ein UART 
bei jedem Byte einen Event ausloesen lassen, oder nach empfangener 
Nachricht. Der EmpfangsTask/Prozess, wartet auf diesen Event.
Ein Programm mit einem zugelinkten Realtime Kernel besteht also aus 
mehreren Prozeduren, die jeweils einen eigenen Stack haben. Erst werden 
diese Task oder Prozess genannten Prozeduren initialisiert, und laufen 
dann los. Das gesammte Programm laeuft nie auf ein End-statement, ist 
eine While(Forever) Schleife.
Der Vorteil gegenueber der Zustandsmaschine ist eine erhoehter 
Uebersichtlichkeit Ein Task ist viel leichter lesbar wie eine komplexe 
Zustandsmaschine. Der Preis ist der Realtime Kernel.

Ein RTOS ist ein Realtime Kernel plus Betriebssystem Funktionalitaet. 
Man kann also Programme laden, was ein Realtime Kernel nicht macht.

von (prx) A. K. (prx)


Lesenswert?

Super Grobi schrieb:

> Da will ich mich mal an Freddys Frage anhängen: Wo und wann punktet den
> nun ein RTOS?

Ein normaler Scheduler entspricht im Verhalten grob einem RTOS mit 
cooperative scheduling. Die Latenzen von Code, der nicht direkt in der 
ISR sitzt, sind abhängig von der Laufzeit der vom Scheduler aufgerufenen 
Aktionen, da die im Gänsemarsch ablaufen. Ein RTOS mit preemptive 
scheduling kann jedoch als Reaktion auf einen Interrupt höher 
priorisierte Aktionen sofort anstossen, indem der laufende Code 
zeitweise verdrängt wird. Generell wird Priorisierung von Aktivitäten 
besser abgebildet.

Ein RTOS / Realtime Kernel bietet meist auch Mechanismen für sowas wie 
Queuing von Daten und/oder Messages, für die Kommunikation der 
verschiedenen Abläufe (Threads) untereinander.

Ein weiterer deutlicher Unterschied liegt in der Übersichtlichkeit des 
Ablaufs. In einem RTOS ist ein Ablauf mit diversen Wartepunkten 
zwischendrin ein sequentieller Ablauf im Quellcode. Mit einer 
State-Machine ist das ein im Quellcode unzusammenhängendes Sammelsurium 
von Codestückchen.

von Super G. (Gast)


Lesenswert?

>Ein weiterer deutlicher Unterschied liegt in der Übersichtlichkeit des
>Ablaufs. In einem RTOS ist ein Ablauf mit diversen Wartepunkten
>zwischendrin ein sequentieller Ablauf im Quellcode. Mit einer
>State-Machine ist das ein im Quellcode unzusammenhängendes Sammelsurium
>von Codestückchen.

Das verstehe ich jetzt nicht.

Wenn in meiner main() die einzelnen Funktionen nacheinander aufgerufen 
werden wenn ein Flag in der ISR gesetzt wurde (z.B. Flag.Taste1 oder 
Flag.DatenEmpfangen) habe ich keine Priorisierung weil wie Du schriebst 
alles im Gänsemarsch abläuft, aber die einzelnen Funktionen sind IMHO 
nicht unübersichtlicher als bei einem RTOS mit diversen Tasks die 
jeweils eine eigene "while(1)" enthalten.
Das Problem der Unübersichtlichkeit der gemeinsamen Datenbasis (aka 
Variablen) die von mehreren Funktionen oder Tasks benötigt werden bleibt 
bei beiden Ansätzen gleich, oder irre ich da?

von (prx) A. K. (prx)


Lesenswert?

Super Grobi schrieb:

> Das verstehe ich jetzt nicht.

RTOS Quellcode:
  Startup
  Aktion 1
  while irgendwas
     Aktion 2
  Abschluss

=> Der Ablauf steht direkt im Quellcode.

Scheduler / State Machine Quellcode:
  Init: Status = 1

  wenn Status = 3, dann Funktion 3:
    Aktion 2
    if irgendwas
    then Status = 3
    else Status = 4

  wenn Status = 1, dann Funktion 1:
    Startup
    Status = 2

  wenn Status = 2, dann Funktion 2:
    Aktion 1
    Status = 3

  ...

=> Den realen Ablauf muss man sich aus der Abfolge der Stati mühsam 
zusammenklamüsern. Wenn hinreichend komplex und nicht gut dokumentiert, 
dann sitzt man eine Weile mit Bleistift und Papier da und verbindet 
Kreise.

> Das Problem der Unübersichtlichkeit der gemeinsamen Datenbasis (aka
> Variablen) die von mehreren Funktionen oder Tasks benötigt werden bleibt
> bei beiden Ansätzen gleich, oder irre ich da?

Wenn du dafür globale Variablen verwendest. Im Idealfalls sind Threads 
hinsichtlich der Daten abgeschlossen und korrespondieren über RTOS 
Mechanismen wie Queues, Mailboxes, Monitore, Rendevous etc.

von Super G. (Gast)


Lesenswert?

Vielen Dank.

von Freddy (Gast)


Lesenswert?

Wenn ich das richtig sehe habe ich dann sowas wie ein Rtos längst mit 
eigenen Mitteln gebaut. Gut werschiedene Tasks sind noch etwas anderes, 
aber mit threads ist es wohl vergleichbar.

Meine üblichen Systeme:

Schnittstellen sind Interrupt oder DMA gesteuert und regieren auf jede 
bzw. je nach Hardwarebuffer schnell genug auf ankommende Messages -> 
Echtzeit.
Die Nachrichten werden in einen Software Ringpuffer gelegt der je nach 
Auslastung entsprechende Strukturen in einem Array besitzt.

In der Main(loop) habe ich dann die Protokollverwaltung. Ich nenne sie 
Handler. Die Funktionen werden zwar alle angesprungen aber die erste 
Abfrage nennt sich in der Regel: Wenn Ringpuffer neue Daten hat, 
zuordnen, und Anweisungen starten.
Bei schnellen Befehlen (Auf Frage gibt es eine direkte Antwort) werden 
wiederum Antwort Ringpuffer bedient.
Langsame Befehle (Befehle die zunächst weitere Aktionen erfordern, 
werden vorsortiert (z.B. Anlalogwandlung wird gestartet, aber auf deren 
Ende wird hier nicht gewartet))
Der Sinn liegt im wesendlichen darin, das so nahezu der gesamte 
Ringpuffer abgearbeitet werden kann in einer mainloop. Dieser kann aber 
trotzdem bei ankommenden Nachrichtenwieder aufgefüllt werden. Haben alle 
Schnittstellen Nachrichten kann man aber schonmal ins Schleudern kommen 
wer jetzt wichtiger ist. Wenn ich Pech habe kann eine mainloop schon 
sehr lange dauern, ist in der Regel aber nie zeitlich definierbar.

Dieses Verfahren setze ich so ein und bin in Sachen Multitasking 
eigentlich zufrieden. Allerdinks ist es doch manchmal schwierig die 
Dynamik von diesem System noch in Echtzeit zu beurteilen. Da ja alle 
Schnittstellen befeuert werden (Wir arbeiten immer in 
Multiprozessorkommunikation). Beim Hardwaretrace stellt man eben fest 
das so manche Protokollbehandlung lieber etwas warten könnte, damit 
nichts verloren geht. Aber die Ringpuffer zu erhöhen stößt nicht immer 
auf Gegenliebe.
Daher meine Frage ob man "mein" Verfahren besser Koordinieren kann mit 
einem Rtos. Wenn ein Betriebssystem auch laufende Funktionen oder da 
eben Tasks unterbrechen kann ist das teilweise hilfreich.
Ich hoffe das jetzt einigermaßen verständlich erklärt zu haben, sorry 
für die vielen Worte.

von Purzel H. (hacky)


Lesenswert?

Nein, Du hast eben kein RTOS, auch keinen Realtime Kernel. Du hast eine 
Zustandsmaschine. Und die werden eben etwas unuebersichtlich.

Ein Realtime Kernel saugt auch etwas an Resourcen ab, das sollte man 
nicht vergessen. Resourcen an RAM, an Code und an Rechenzeit.
Wenn's denn so einen Realtime Kernel zum Controller und Compiler passend 
gibt waere das eine Option, die man anschauen sollte. Die 
Einarbeitungszeit kann schon einen Monat betragen. DasDebuggen ist auch 
etwas Anderes, denn man gibt die definierte Reihenfolge, die man sich 
gewohnt ist auf. Die Task laufen wenn sie laufen, manchmal laufen sie 
eben nicht.

Falls du bei der Zustandsmaschine bleiben willst, zumindest kurzfristig: 
Wenn der Mainloop teilweise unueberschaubar lange dauert, muss man die 
Funktionalitaet eben zerscheibeln. Man muss ja nicht ein Longword-to-BCD 
in einem Durchgang rechnen, speziell weil das meist mit Ein-/Ausgabe 
zusammenhaengt, sondern kann das auf eine Ziffer pro Durchgang 
zerhacken. Ein LCD wird auch nicht in einem Durchgang beschrieben, 
sondern nur mit einem Character pro Durchgang.
Dadurch wird die Zustandsmaschine nochmals etwas komplizierter.

von (prx) A. K. (prx)


Lesenswert?

Delta Oschi schrieb:

> Wenn's denn so einen Realtime Kernel zum Controller und Compiler passend
> gibt waere das eine Option, die man anschauen sollte.

Wobei man der Cortex-M Architektur in Form des NVIC ansieht, dass sich 
ARM über das Thema RTOS / Realtime-Kernel Gedanken gemacht hat. Das 
integriert sich recht gut, besser als bei den älteren ARM Architekturen.

Die saubere Prioritätskontrolle erlaubt hohe verzögerungsarme 
Prioritäten für ISRs ohne Nutzung des Kernels, was bei den älteren ARMs 
abgesehen vom FIQ oft problematisch ist. Und es gibt einen eigenen Hook 
für einen Task Switch als Resultat von Aktivitäten in möglicherweise 
verschachtelten ISRs, was den Overhead der ISRs reduziert.

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.