RTOS für eingebettete Systeme

Ich habe viele Artikel gesehen, die mir sagen, dass ich RTOS für Zeitmanagement und Ressourcenmanagement verwenden sollte. Meine Zeit hat meine eigene Recherche nicht zugelassen, also wende ich mich an Chiphacker, um mich beraten zu lassen.

Ich verwende ressourcenarme Mikrocontroller (MSP430, PIC) und suchte nach RTOSs, die ich verwenden kann.

Auf den Punkt:

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

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

Ich bin verwirrt darüber, wofür dies eine Ablehnung erhalten hat. Wenn der Wähler mir Feedback geben könnte, werde ich versuchen, eine solche Aktion in Zukunft zu vermeiden.
dito. Es ist eine große Frage....
Ich habe eine Frage akzeptiert, weil ich, obwohl ich dachte, dass dies offen ist, eine Reihe großartiger Antworten erhalten habe und mindestens einen Autor für seine Mühe belohnen wollte.

Antworten (9)

Ich habe nicht viele persönliche Erfahrungen mit anderen Echtzeitbetriebssystemen als QNX gemacht (was im Großen und Ganzen großartig, aber nicht billig ist, und ich habe eine wirklich schlechte Erfahrung mit einem bestimmten Board-Anbieter und der Uns-egal-Einstellung von QNX für andere Systeme gemacht als ihre gebräuchlichsten), was zu groß für PICs und MSP430 ist.

Wo Sie von einem RTOS profitieren, liegt in Bereichen wie z

  • 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, mit Ausnahme der 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 von einem RTOS viel Unterstützung finden würden, da sie so herstellerspezifisch sind.

Wenn Sie ein mikrosekundengenaues Timing benötigen, wird ein RTOS wahrscheinlich nicht helfen - RTOS haben ein begrenztes Timing, haben aber normalerweise Timing-Jitter in ihrer Planung aufgrund von Verzögerungen beim Kontextwechsel ... QNX, das auf einem PXA270 ausgeführt wird, hatte Jitter in den typischen zehn Mikrosekunden, maximal 100-200us, also würde ich es nicht für Dinge verwenden, die schneller als etwa 100Hz laufen müssen oder die ein viel genaueres Timing als etwa 500us benötigen. Für solche Dinge müssen Sie wahrscheinlich Ihr eigenes Interrupt-Handling implementieren. Einige RTOSs werden damit gut spielen, 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 gestaltete Zustandsmaschine zu verwenden. Ich würde dringend empfehlen, Praktische Zustandsdiagramme in C/C++ zu lesen , falls Sie dies noch nicht getan haben. Wir haben diesen Ansatz in einigen unserer Projekte, in denen ich arbeite, verwendet, und er hat einige echte Vorteile gegenüber herkömmlichen Zustandsmaschinen für die Verwaltung von Komplexität .... das ist wirklich der einzige Grund, warum Sie ein Echtzeitbetriebssystem benötigen.

Ich arbeite in einem Startup-Unternehmen, in dem die erfahrensten Embedded-System-Leute gerade das College verlassen haben (dh ich selbst und der andere Typ, der seit etwa 2 Jahren mit mir zusammenarbeitet). Ich verbringe einen sehr großen Teil meiner Zeit damit, mir während meiner Arbeitswoche etwas über die Branchenpraxis beizubringen. Während ich gelesen habe, wurde ich darüber informiert, dass ein RTOS für alle außer unserem kostengünstigsten System eine große Verbesserung wäre.
Es scheint sehr ressourcenarme RTOS-Systeme für Dinge wie PICs und MSP430s zu geben, die dabei helfen können, ein deterministisches System aus einem sehr komplizierten System zu erstellen, und auch unser Management der Trennung von Modulen erheblich aufräumen. Ich war Teil eines Zwei-Mann-Teams, das effektiv ein Felddatenerfassungs- und Routingsystem aufgebaut hat. Wenn ich mir jetzt RTOS anschaue, sehe ich, dass es perfekt für das ist, was wir entworfen haben.
Entschuldigung für die Verwendung von drei Post-Slots, Ihre Antwort ist sehr hilfreich, ich suche nach einer Lösung mit sehr geringen Ressourcen, aber diese Informationen sind wertvoll, danke für die Hilfe.
Machen Sie sich keine Sorgen über die Anzahl der Kommentare (IMHO eine Sache, die dem StackExchange-Framework fehlt, ist die Unterstützung für Diskussionen ... das Q / A-Format deckt die meisten Dinge ab, aber nicht einige) ... hört sich so an, als hätten Sie ziemlich gut im Griff, was 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 vielleicht die Planungsverwaltung übernehmen, die Sie benötigen.
Es scheint den Status jedes Threads durch den Stapel zu speichern (etwa 50 Push/Pull-Anweisungen) und kann zeitgesteuerte Interrupts verarbeiten. Mein System würde normalerweise einen Port-Interrupt für die Thread-Umschaltung verwenden, aber die Aufgabe sieht machbar aus. Ich wünsche mir, dass dieser Site-Typ Diskussionen in einem besseren Format behandelt.

Hast du FreeRTOS ausprobiert ? Es ist kostenlos (vorbehaltlich der AGB) und wurde sowohl auf den MSP430 als auch auf verschiedene PIC-Varianten portiert.

Es ist klein im Vergleich zu einigen anderen, aber das macht es auch leicht zu erlernen, besonders wenn Sie noch nie ein RTOS verwendet haben.

Eine (nicht kostenlose) kommerzielle Lizenz ist verfügbar, ebenso wie eine IEC 61508/SIL 3-Version.

Vielen Dank, ich werde mich innerhalb der Woche darum kümmern, ich werde die Frage für andere Antworten offen lassen, aber Sie sind eine große Hilfe!
@Kortuk, hast du am Ende FreeRTOS oder ThreadX gelernt?

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. POSIX kann ein Plus sein, da es einen Teil Ihres Codes etwas portabler macht, wenn Sie auf einen stärkeren Prozessor umsteigen und Echtzeit-Linux oder QNX ausführen möchten.

Ich habe selbst keine Erfahrung mit kommerziellen RTOS's, aber ich benutze seit Jahren selbstgebaute! Sie sind großartig darin, Ihnen dabei zu helfen, Ihre Codeentwicklung auf viele Programmierer aufzuteilen, da sie im Wesentlichen jeder eine "Aufgabe" oder einen "Thread" bekommen können, um an seiner Seite zu arbeiten. Sie müssen immer noch koordinieren und jemand muss das gesamte Projekt beaufsichtigen, um sicherzustellen, dass jede Aufgabe ihren Termin einhalten kann.

Ich empfehle Ihnen auch, sich bei der Verwendung eines RTOS mit Rate Monotonic Analysis oder RMA zu befassen. Auf diese Weise können Sie sicherstellen, dass Ihre kritischen Aufgaben ihre Fristen einhalten.

Ich würde mir auch das ereignisgesteuerte Programmierframework QP-nano von Miro Samek ansehen , das mit oder ohne RTOS arbeiten kann und Ihnen trotzdem Echtzeitfähigkeit bietet. Damit unterteilen Sie Ihr Design in hierarchische Zustandsmaschinen statt in traditionelle Aufgaben. Jason S erwähnte Miros Buch in seinem Beitrag. Eine hervorragende Lektüre!

Eine Sache, die ich auf einer Reihe von Maschinen als nützlich empfunden habe, ist ein einfacher Stack-Switcher. Ich habe eigentlich keinen für den PIC geschrieben, aber ich würde erwarten, dass der Ansatz auf dem PIC18 gut funktionieren würde, 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 gut für einen PIC18Fxx funktionieren) und die task2-Schleife ausführt; diese Routine darf nie wiederkehren, sonst sterben die Dinge einen qualvollen Tod. Stattdessen sollte es _taskswitch immer dann aufrufen, wenn es die Kontrolle an die primäre Aufgabe abgeben möchte; 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 (unsigned short val)
{
  tun
    Taskswitch();
  while((unsigned short)(millisecond_clock - val) > 0xFF00);  
}

Beachten Sie, dass der Task-Umschalter keine Möglichkeit hat, eine 'Warten auf Bedingung' auszuführen; alles, was es unterstützt, ist ein Spinwait. Andererseits ist der Aufgabenwechsel so schnell, dass ein Versuch eines taskswitch(), während die andere Aufgabe auf das Ablaufen eines Timers wartet, zu der anderen Aufgabe wechselt, den Timer überprüft und schneller zurückwechselt als ein typischer Aufgabenwechsler würde feststellen, dass es keinen Taskswitch braucht.

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

(Bearbeiten): Ein paar Vorbehalte in Bezug auf automatische Variablen und dergleichen:

  1. Wenn eine Routine, die Task-Switching verwendet, von beiden Threads aufgerufen wird, ist es im Allgemeinen erforderlich, zwei Kopien der Routine zu kompilieren (möglicherweise durch zweimaliges #Einschließen derselben Quelldatei mit unterschiedlichen #define-Anweisungen). Jede angegebene 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)" verwenden kann oder #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 löschen kann, wodurch die Notwendigkeit vermieden wird, Register in der Task-Switch-Routine zu speichern [ein netter Vorteil im Vergleich zu präventives Multitasking]. Jeder, der einen ähnlichen Task-Umschalter für eine andere CPU in Betracht zieht, muss sich der verwendeten Registerkonventionen bewusst sein. Das Pushen von Registern vor einem Taskwechsel und das anschließende Popping ist eine einfache Möglichkeit, sich um die Dinge zu kümmern, vorausgesetzt, es ist ausreichend Stack-Speicherplatz vorhanden.

Kooperatives Multitasking erlaubt es einem nicht, Probleme mit Sperren und dergleichen vollständig zu vermeiden, aber es vereinfacht die Dinge wirklich erheblich. In einem präemptiven RTOS mit einem kompakten Garbage Collector ist es beispielsweise notwendig, das Fixieren von Objekten zuzulassen. Bei Verwendung eines kooperativen Umschalters ist dies nicht erforderlich, vorausgesetzt, der Code geht davon aus, dass sich GC-Objekte jederzeit bewegen können, wenn taskswitch() aufgerufen wird. Ein kompaktierender Kollektor, der sich nicht um gepinnte Objekte kümmern muss, kann viel einfacher sein als einer, der dies tut.

Tolle Antwort. Ich denke, es wäre interessant, ein paar Links zu Ressourcen zu bekommen, wie ich mich meinem eigenen RTOS nähern kann. Mein Fokus lag hier wirklich darauf, ein qualitativ hochwertiges RTOS von einem Anbieter zu bekommen, der die Arbeit geleistet hat, harte Echtzeit zu gewährleisten, aber dies könnte ein lustiges Hobbyprojekt für mich sein.
Cool, ich habe nie an Aufgaben gedacht, bei denen es darum geht, einfach den SP zu wechseln ...
@JGord: Ich habe kleine Task-Switcher auf dem 8x51 und auf einem TI DSP gemacht. Der oben gezeigte 8051 ist für genau zwei Aufgaben ausgelegt. Der DSP wird mit vier verwendet und ist etwas komplizierter. Ich hatte aber gerade eine verrückte Idee: Man könnte vier Tasks bewältigen, indem man einfach drei Taskswitcher verwendet. 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 Taskswitch 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.
@JGord: Hmm ... das funktioniert nicht ganz; es scheint ein 3-Wege-Round-Robin zu ergeben und ignoriert den dritten Umschalter. Nun, experimentieren Sie und ich denke, Sie werden wahrscheinlich eine gute Formel finden.

Ich habe Salvo auf dem MSP430 verwendet. Dies war sehr ressourcenschonend und, vorausgesetzt, Sie befolgen die Implementierungsregeln, sehr einfach zu verwenden und zuverlässig. Dies ist ein kooperatives OS und erfordert, dass Aufgabenumschaltungen auf der äußeren Funktionsaufrufebene der Aufgabenfunktionen durchgeführt werden. Diese Einschränkung ermöglicht es dem Betriebssystem, in sehr kleinen Speichergeräten zu arbeiten, ohne große Mengen an Stapelplatz zu verwenden, um Aufgabenkontexte aufrechtzuerhalten.

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

Die Dezember-Ausgabe von Everyday Practical Electronics enthält Teil 3 einer Serie über Echtzeit-Betriebssysteme für PICs (in der PIC n' Mix-Kolumne) und enthält Einzelheiten zum Einrichten von FreeRTOS mit MPLAB und einem PICKit 2. Die beiden vorherigen Artikel (die I noch nicht gesehen) scheinen die Vorzüge verschiedener Echtzeitbetriebssysteme diskutiert und sich für FreeRTOS entschieden zu haben. Sobald der aktuelle Artikel die Entwicklungsumgebung eingerichtet hat, beginnen sie mit dem Entwurf einer binären Digitaluhr. Es scheint, dass es noch mindestens einen weiteren Teil zu diesem Thema geben wird.

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

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

Ich habe das tatsächlich als erstes ausprobiert. 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 läuft. Sie müssen sie absichtlich ständig einfügen, falls ein anderes Programm übernehmen muss.
Ich denke, dass es immer noch als RTOS bezeichnet wird. Es hört sich einfach so an, als hätte es einen kooperativen Scheduler anstelle eines vollständig präemptiven Schedulers.
Ja, es ist technisch immer noch ein RTOS, aber ich hatte und habe immer noch sehr wenig Wert darauf. Ich weiß, es ist eine persönliche Sache, aber für mich muss es präventiv sein, um wertvoll zu sein. Ich gebe immer noch +1, da es eine gute Antwort und von Wert war.
Danke! Es sieht so aus, als hätten die meisten Leute die Frage nicht verstanden, aber es ist trotzdem interessant.
Ich habe auf die Frage zu SO gepostet und den Benutzer eingeladen, zu E & R zu kommen, um Hilfe zu erhalten!
Ich denke, wir haben die Frage zu SO "verstanden", es wurde etwas anderes gestellt, aber mit dieser Frage verwandt. Was Ihren Kommentar dort zur Zertifizierung betrifft; das hängt von vielem ab. Wenn ich mir die Antworten hier ansehe, mag ich die Antwort von DoxaLogos, die sich auf QP-nano bezieht; Meine Erfahrung führt dazu, dass ich ereignisgesteuerten Code Threads und implizitem Kontextwechsel von Threads vorziehe.

Sie haben nicht viel über Ihre 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 Dinge tun, die strenge Zeitgrenzen erfordern, oder mehrere Threads ausführen, ist ein RTOS möglicherweise übertrieben.

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 läuft, der beispielsweise mit 1000 Hz laufen muss. Wenn die Ausführung des PID-Algorithmus weniger als 1 ms dauert, können Sie den Rest der Millisekunde für andere Aufgaben verwenden, z. B. den CAN-Bus überprüfen, Sensoren lesen usw.

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

  3. Stecke es in eine Schleife und mache alles so schnell du kannst. Möglicherweise stellen Sie fest, dass dies geeignete Zeitgrenzen bietet.

Ich verstehe andere Methoden, möchte aber auf ein RTOS erweitern. Ich werde mehrere Tasks ausführen und ein hartes Echtzeitsystem haben, bin aber bereit, ohne die Anforderungen von harter Echtzeit zu beginnen. 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.