RTOS für eingebettete Systeme

57

Ich habe viele Artikel gesehen, die mir sagen, dass ich RTOS für die Zeitverwaltung und die Ressourcenverwaltung verwenden sollte. Meine Zeit hat meine eigene Forschung nicht erlaubt, deshalb komme ich zu Chiphacker, um Rat zu bekommen.

Ich benutze ressourcenarme Mikrocontroller (MSP430, PIC) und habe nach RTOS gesucht, die ich verwenden kann.

Auf den Punkt gebracht:

  1. Ressourcenkosten des Systems
  2. Vorteile des Systems
  3. Nachteile des Systems
  4. Implementierungstricks
  5. Situationen, in denen das RTOS nicht verwendet werden sollte.

Ich verwende keine Systeme wie das Arduino, die Projekte, mit denen ich arbeite, können die Kosten eines solchen Systems nicht decken.

Kortuk
quelle
2
Ich bin verwirrt, wofür dies abgelehnt wurde. Wenn der Wähler mir Feedback geben könnte, werde ich versuchen, eine solche Aktion in Zukunft zu vermeiden.
Kortuk
1
dito. Es ist eine gute Frage ...
Jason S
Ich habe eine Frage angenommen, weil ich, obwohl dies offen ist, eine Reihe großartiger Antworten hatte und mindestens einen Schriftsteller für die Mühe belohnen wollte.
Kortuk

Antworten:

29

Ich habe nicht viel persönliche Erfahrung mit RTOSs außer QNX gemacht (was im Großen und Ganzen großartig ist, aber nicht billig, und ich habe wirklich schlechte Erfahrungen mit einem bestimmten Board-Anbieter gemacht und QNXs Einstellung, dass wir uns nicht um andere Systeme kümmern ist zu groß für PICs und MSP430s.

Wo Sie von einem RTOS profitieren, ist in Bereichen wie

  • Thread Management / Scheduling
  • Inter-Thread-Kommunikation + Synchronisation
  • E / A auf Systemen mit stdin / stdout / stderr oder seriellen Ports oder Ethernet-Unterstützung oder einem Dateisystem (größtenteils kein MSP430 oder PIC, außer den seriellen Ports)

Für Peripheriegeräte eines PIC oder MSP430: Für serielle Ports würde ich einen Ringpuffer + Interrupts verwenden ... etwas, das ich einmal pro System schreibe und einfach wiederverwende; andere Peripheriegeräte Ich glaube nicht, dass Sie viel Unterstützung von einem RTOS finden würden, da sie so herstellerspezifisch sind.

Wenn Sie ein Timing benötigen, das absolut auf die Mikrosekunde genau ist, wird ein RTOS wahrscheinlich nicht helfen - RTOSs haben ein begrenztes Timing, haben aber in der Regel Timing-Jitter aufgrund von Verzögerungen beim Kontextwechsel ... QNX, das auf einem PXA270 läuft, hatte Jitter in den typischen zehn Mikrosekunden, maximal 100-200us, also würde ich es nicht für Dinge verwenden, die schneller als ungefähr 100Hz laufen müssen oder die ein viel genaueres Timing als ungefähr 500us benötigen. Für solche Dinge müssen Sie wahrscheinlich Ihre eigene Interrupt-Behandlung implementieren. Einige RTOSs werden gut damit spielen und andere werden es zu einem königlichen Schmerz machen: Ihr Timing und ihr Timing können möglicherweise nicht gut koexistieren.

Wenn das Timing / Scheduling nicht zu komplex ist, ist es möglicherweise besser, eine gut konzipierte Zustandsmaschine zu verwenden. Ich würde das Lesen von Praktischen Zustandsdiagrammen in C / C ++ wärmstens empfehlen, wenn Sie dies noch nicht getan haben. Wir haben diesen Ansatz in einigen unserer Projekte verwendet, in denen ich arbeite, und er hat einige echte Vorteile gegenüber herkömmlichen Zustandsautomaten für die Verwaltung der Komplexität. Dies ist wirklich der einzige Grund, warum Sie ein RTOS benötigen.

Jason S
quelle
Ich arbeite in einem Startup-Unternehmen, in dem die erfahrensten Embedded-Systems-Leute gerade das College verlassen haben (dh ich selbst und der andere, der seit ungefähr 2 Jahren mit mir zusammenarbeitet). Ich verbringe einen sehr großen Teil meiner Zeit damit, mich während meiner Arbeitswoche über Industriepraxis zu unterrichten. Wie ich gelesen habe, wurde ich über alles informiert, außer über unser kostengünstigstes System. Ein RTOS wäre eine große Verbesserung.
Kortuk
Es scheint ein ressourcenschwaches RTOS-System für PICs und MSP430s zu geben, das dazu beitragen kann, ein deterministisches System aus einem sehr komplizierten System zu erstellen, und das unsere Verwaltung der getrennten Module erheblich aufräumt. Ich war Teil eines Zwei-Mann-Teams, das effektiv ein System zur Datenerfassung und -weiterleitung vor Ort aufgebaut hat. Jetzt, wo ich mir RTOS anschaue, sehe ich, dass es perfekt für das ist, was wir entworfen haben.
Kortuk
Es tut uns leid, dass Sie drei Post-Slots verwenden. Ihre Antwort ist sehr hilfreich. Ich suche nach einer Lösung mit sehr geringen Ressourcen. Diese Informationen sind jedoch hilfreich. Vielen Dank für die Hilfe.
Kortuk
Sorgen Sie sich nicht um die Anzahl der Kommentare (IMHO fehlt dem StackExchange-Framework die Unterstützung für Diskussionen ... das Q / A-Format deckt die meisten Dinge ab, aber nicht einige) du schaust nach. Ich habe mir das von Steve erwähnte FreeRTOS nicht angesehen, aber wenn es auf Low-End-Mikrocontroller portiert wurde, wird es möglicherweise das Scheduling-Management übernehmen, das Sie benötigen.
Jason S
Es scheint den Status jedes Threads im Stack zu speichern (etwa 50 Push / Pull-Anweisungen) und kann zeitgesteuerte Interrupts verarbeiten. Normalerweise verwendet mein System einen Port-Interrupt zum Wechseln des Threads, aber die Aufgabe scheint erledigt zu sein. Ich wünsche mir, dass diese Art der Diskussion in einem besseren Format behandelt wird.
Kortuk
26

Haben Sie FreeRTOS ausprobiert ? Es ist kostenlos (vorbehaltlich der Nutzungsbedingungen) und wurde sowohl auf den MSP430 als auch auf verschiedene PIC-Versionen portiert.

Es ist klein im Vergleich zu einigen anderen, aber das macht es auch einfach zu erlernen, besonders wenn Sie zuvor noch kein RTOS verwendet haben.

Eine (nicht kostenlose) kommerzielle Lizenz sowie eine IEC 61508 / SIL 3-Version sind verfügbar.

Steve Melnikoff
quelle
Vielen Dank, ich werde mich in der Woche darum kümmern, ich werde die Frage für andere Antworten offen lassen, aber Sie sind eine große Hilfe!
Kortuk
12

Ich habe gerade von NuttX RTOS erfahren , das sogar auf einem 8052 (8-Bit) -System funktionieren kann. Es hat nicht viele Ports, aber es sieht interessant aus. Das POSIX kann ein Plus sein, da es einen Teil Ihres Codes ein wenig portabler machen kann, wenn Sie auf einen leistungsstärkeren Prozessor umsteigen und Linux oder QNX in Echtzeit ausführen möchten.

Ich habe selbst keine Erfahrung mit kommerziellen RTOSs, aber ich habe jahrelang hausgemachte verwendet! Sie unterstützen Sie dabei, Ihre Codeentwicklung auf viele Programmierer aufzuteilen, da sie im Grunde genommen jeweils eine "Aufgabe" oder einen "Thread" für ihre Arbeit erhalten können. Sie müssen noch koordinieren und jemand muss das gesamte Projekt beaufsichtigen, um sicherzustellen, dass jede Aufgabe ihre Frist einhält.

Ich empfehle Ihnen auch, die Rate Monotonic Analysis oder RMA zu untersuchen, wenn Sie ein RTOS verwenden. Auf diese Weise können Sie sicherstellen, dass Ihre kritischen Aufgaben ihre Fristen einhalten.

Ich würde mir auch das ereignisgesteuerte QP-nano -Programmierframework von Miro Samek ansehen , das mit oder ohne RTOS arbeiten kann und Ihnen dennoch Echtzeitfähigkeit bietet. Damit teilen Sie Ihr Design in hierarchische Zustandsautomaten anstatt in herkömmliche Aufgaben. Jason S erwähnte Miros Buch in seinem Beitrag. Eine ausgezeichnete Lektüre!

Jay Atkinson
quelle
9

Eine Sache, die ich auf einer Reihe von Maschinen als nützlich empfunden habe, ist ein einfacher Stapelumschalter. Ich habe noch keinen für den PIC geschrieben, aber ich würde erwarten, dass der Ansatz auf dem PIC18 gut funktioniert, wenn beide / alle Threads insgesamt 31 oder weniger Stapelebenen verwenden. Auf dem 8051 ist die Hauptroutine:

_taskswitch:
  xch a, SP
  xch a, _altSP
  xch a, SP
  ret

Auf dem PIC vergesse ich den Namen des Stapelzeigers, aber die Routine würde ungefähr so ​​aussehen:

_taskswitch:
  movlb _altSP >> 8
  movf _altSP, w, b
  movff _STKPTR, altSP 
  movwf _STKPTR, c
  Rückkehr

Rufen Sie zu Beginn Ihres Programms eine task2 () - Routine auf, die altSP mit der Adresse des alternativen Stacks lädt (16 würde wahrscheinlich für einen PIC18Fxx gut funktionieren) und die task2-Schleife ausführt. Diese Routine darf niemals zurückkehren, sonst sterben die Dinge einen schmerzhaften Tod. Stattdessen sollte _taskswitch aufgerufen werden, wann immer die Kontrolle über die primäre Task erlangt werden soll. Die primäre Task sollte dann _taskswitch aufrufen, wann immer sie der sekundären Task nachgeben möchte. Oft hat man niedliche kleine Routinen wie:

void delay_t1 (vorzeichenloser kurzer Wert)
{
  machen
    Taskschalter ();
  while ((vorzeichenloser Kurzschluss) (millisecond_clock - val)> 0xFF00);  
}

Beachten Sie, dass der Task-Switcher keine Möglichkeit hat, auf eine Bedingung zu warten. Alles, was es unterstützt, ist ein Spinwait. Auf der anderen Seite ist der Taskwechsel so schnell, dass ein Versuch, einen Taskswitch () auszuführen, während der andere Task auf das Ablaufen eines Timers wartet, zum anderen Task wechselt, den Timer überprüft und schneller zurückschaltet als ein typischer Task-Switcher würde feststellen, dass es keinen Taskswitch braucht.

Beachten Sie, dass kooperatives Multitasking einige Einschränkungen hat, aber die Notwendigkeit für viele Sperren und anderen mutexbezogenen Code in Fällen, in denen vorübergehend gestörte Invarianten schnell wiederhergestellt werden können, entfällt.

(Bearbeiten): Ein paar Vorsichtsmaßnahmen in Bezug auf automatische Variablen und solche:

  1. Wenn eine Routine, die Task-Switching verwendet, von beiden Threads aufgerufen wird, müssen im Allgemeinen zwei Kopien der Routine kompiliert werden (möglicherweise durch zweimaliges Einschließen derselben Quelldatei mit unterschiedlichen #define-Anweisungen). Jede Quelldatei enthält entweder Code für nur einen Thread oder Code, der zweimal kompiliert wird - einmal für jeden Thread -, sodass ich Makros wie "#define delay (x) delay_t1 (x)" oder "#define delay" verwenden kann #define delay (x) delay_tx (x) "abhängig davon, welchen Thread ich verwende.
  2. Ich glaube, dass PIC-Compiler, die eine aufgerufene Funktion nicht "sehen" können, davon ausgehen, dass eine solche Funktion alle CPU-Register verwerfen kann, so dass keine Register in der Task-Switch-Routine gespeichert werden müssen [ein netter Vorteil gegenüber präventives Multitasking]. Jeder, der einen ähnlichen Task-Switcher für eine andere CPU in Betracht zieht, muss die verwendeten Registerkonventionen kennen. Das Schieben von Registern vor einem Taskwechsel und das Anzeigen von Registern nach einem Taskwechsel ist eine einfache Möglichkeit, die Dinge zu erledigen, vorausgesetzt, es ist ausreichend Stapelspeicher vorhanden.

Mit kooperativem Multitasking kann man Sperrproblemen und dergleichen nicht vollständig entkommen, aber es vereinfacht die Dinge wirklich erheblich. In einem vorbeugenden RTOS mit einem komprimierenden Garbage Collector ist es beispielsweise erforderlich, das Anheften von Objekten zu ermöglichen. Wenn Sie einen kooperativen Switcher verwenden, ist dies nicht erforderlich, vorausgesetzt, der Code geht davon aus, dass sich GC-Objekte bei jedem Aufruf von taskswitch () bewegen können. Ein Verdichtungssammler, der sich nicht um festgesteckte Objekte kümmern muss, kann viel einfacher sein als einer, der dies tut.

Superkatze
quelle
1
Geniale Antwort. Ich denke, es wäre interessant, Links zu Ressourcen zu erhalten, wenn ich mich an mein eigenes RTOS wende. Mein Fokus lag hier wirklich darauf, ein qualitativ hochwertiges RTOS von einem Anbieter zu erhalten, der die Arbeit geleistet hat, harte Echtzeit sicherzustellen, aber dies könnte ein lustiges Hobby-Projekt für mich sein.
Kortuk
1
Cool, nie gedacht, Aufgaben wie nur die SP wechseln ...
NickHalden
1
@JGord: Ich habe auf dem 8x51 und einem TI DSP winzige Task-Switcher gemacht. Der oben gezeigte 8051 ist für genau zwei Aufgaben ausgelegt. Der DSP eins wird mit vier benutzt und es ist etwas komplizierter. Ich hatte nur eine verrückte Idee: Mit drei Taskswitchern konnte man vier Aufgaben bewältigen. Jedes Mal, wenn einer der ersten beiden Tasks einen Taskwechsel durchführen möchte, sollte er TaskSwitch1 und TaskSwitch2 aufrufen. Wenn einer der beiden zweiten Tasks einen Taskwechsel durchführen möchte, sollte er Taskswitch1 und Taskswitch3 aufrufen. Angenommen, der Code beginnt in stack0, und jeder Task-Switcher wird mit seiner entsprechenden Stack-Nummer festgelegt.
Supercat
@JGord: Hmm ... das funktioniert nicht ganz; es scheint ein 3-Wege-Round-Robin zu ergeben und ignoriert den dritten Switcher. Nun, experimentieren Sie und ich denke, Sie werden wahrscheinlich eine gute Formel finden.
Supercat
7

Ich habe Salvo auf dem MSP430 verwendet. Dies war sehr ressourcenschonend und unter der Voraussetzung, dass Sie die Implementierungsregeln einhalten, sehr benutzerfreundlich und zuverlässig. Dies ist ein kooperatives Betriebssystem und erfordert, dass Taskwechsel auf der äußeren Funktionsaufrufebene der Taskfunktionen durchgeführt werden. Diese Einschränkung ermöglicht es dem Betriebssystem, in sehr kleinen Speichergeräten zu arbeiten, ohne große Mengen an Stapelspeicher zu benötigen, um Aufgabenkontexte aufrechtzuerhalten.

Auf dem AVR32 verwende ich FreeRTOS. Bis jetzt wieder sehr zuverlässig, aber ich hatte einige Konfigurations- / Versionsdiskrepanzen zwischen der Version, die FreeRTOS veröffentlicht, und der mit dem Atmel-Framework gelieferten Version. Dies hat jedoch den Vorteil, dass es kostenlos ist!

uɐɪ
quelle
5

Die Dezember-Ausgabe von Everyday Practical Electronics enthält Teil 3 einer Reihe von Echtzeit-Betriebssystemen für PICs (in der Spalte PIC n 'Mix) und enthält Einzelheiten zum Einrichten von FreeRTOS mit MPLAB und einem PICKit 2. Die beiden vorherigen Artikel (die ich offenbar die Vorzüge verschiedener RTOS diskutiert und sich für FreeRTOS entschieden haben. Sobald der aktuelle Artikel die Entwicklungsumgebung eingerichtet hat, beginnt der Entwurf einer binären Digitaluhr. Es scheint, dass es zu diesem Thema noch mindestens einen weiteren Teil gibt.

Ich bin nicht sicher, wie verfügbar EPE in den USA ist, aber es scheint einen US-Store zu geben, der von ihrer Website verlinkt ist, und möglicherweise sind elektronische Kopien verfügbar.

Amos
quelle
4

Der CCS-Compiler für den PIC wird mit einem einfachen RTOS ausgeliefert. Ich habe es nicht ausprobiert, aber wenn Sie diesen Compiler haben, wäre es einfach, damit zu experimentieren.

Jeanne Pindar
quelle
1
Ich habe es tatsächlich als erstes versucht. Es ist kein RTOS im eigentlichen Sinne des Wortes. Es ist in keiner Weise präventiv. Es erfordert die regelmäßige Verwendung von yield-Befehlen, damit das RTOS entscheiden kann, wer als Nächstes ausgeführt wird. Sie müssen diese Befehle absichtlich permanent eingeben, falls ein anderes Programm die Aufgabe übernehmen muss.
Kortuk
2
Ich denke, dass es immer noch ein RTOS heißt. Es klingt nur so, als hätte es einen kooperativen Scheduler anstelle eines vollständig präemptiven Schedulers.
Jay Atkinson
Ja, es ist technisch immer noch ein RTOS, aber ich hatte und habe sehr wenig Wert dafür. Ich weiß, dass es eine persönliche Sache ist, aber für mich muss es präventiv sein, um wertvoll zu sein. Ich habe immer noch +1, da es eine gute Antwort und von Wert war.
Kortuk
3

Eng verwandte Frage: https://stackoverflow.com/questions/1624237/multithreading-using-c-on-pic18

Davidcary
quelle
Vielen Dank! Es sieht so aus, als hätten die meisten Leute die Frage nicht bekommen, aber es ist immer noch interessant.
Kortuk 10.06.10
Ich habe auf SO eine Frage gestellt, in der ich den Benutzer einlade, zu E & R zu kommen, um Hilfe zu erhalten.
Kortuk
Ich denke, wir haben die Frage zu SO "verstanden". Sie stellte etwas anderes, bezog sich aber auf diese Frage. Wie für Ihren Kommentar dort über die Zertifizierung; Das hängt von vielen Dingen ab. Wenn ich die Antworten hier betrachte, mag ich die Antwort von DoxaLogos, die sich auf QP-nano bezieht. Aufgrund meiner Erfahrung bevorzuge ich ereignisgesteuerten Code gegenüber Threads und impliziten Kontextwechseln von Threads.
9.
2

Sie haben nicht viel zu Ihrer Bewerbung gesagt. Ob Sie ein RTOS verwenden, hängt stark davon ab, was Sie im PIC tun müssen. Wenn Sie nicht mehrere verschiedene asynchrone Vorgänge ausführen, die strenge Zeitbeschränkungen erfordern oder in denen mehrere Threads ausgeführt werden, ist ein RTOS möglicherweise überlastet.

Es gibt viele Möglichkeiten, die Zeit auf einem Mikrocontroller zu organisieren, je nachdem, was am wichtigsten ist:

  1. Konstante Bildrate: Für einen PIC, auf dem ein Servocontroller ausgeführt wird, der beispielsweise mit 1000 Hz betrieben werden muss. Wenn die Ausführung des PID-Algorithmus weniger als 1 ms dauert, können Sie den Rest der Millisekunde verwenden, um andere Aufgaben auszuführen, z. B. den CAN-Bus zu überprüfen, Sensoren auszulesen usw.

  2. Alle Interrupts: Alles, was im PIC passiert, wird durch einen Interrupt ausgelöst. Die Interrupts können entsprechend der Wichtigkeit des Ereignisses priorisiert werden.

  3. Stecke es in eine Schleife und mache alles so schnell du kannst. Sie werden vielleicht feststellen, dass dies geeignete Zeitgrenzen bietet.

Raketenmagnet
quelle
Ich verstehe andere Methoden, möchte aber auf ein RTOS erweitern. Ich werde mehrere Aufgaben ausführen und ein hartes Echtzeitsystem haben, aber ich bin bereit, ohne die Anforderungen der harten Echtzeit zu starten. Vielen Dank, dass Sie sich die Zeit genommen haben, um zu antworten, aber ich möchte ein RTOS lernen, damit ich es in einer Situation mit hoher Nachfrage verwenden kann.
Kortuk