Es gibt zwei Haupttypen von Multitasking-Betriebssystemen: präventive und kooperative. Mit beiden können mehrere Aufgaben im System definiert werden. Der Unterschied besteht darin, wie die Aufgabenumschaltung funktioniert. Natürlich läuft mit einem einzigen Core-Prozessor immer nur eine Task gleichzeitig.
Für beide Arten von Multitasking-Betriebssystemen ist für jede Aufgabe ein separater Stack erforderlich. Dies impliziert also zwei Dinge: Erstens, dass der Prozessor das Platzieren von Stacks an einer beliebigen Stelle im RAM zulässt und daher Anweisungen zum Bewegen des Stack-Zeigers (SP) enthält - dh, es gibt keinen speziellen Hardware-Stack wie am unteren Ende PIC's. Dadurch entfallen die PIC10, 12 und 16-Serien.
Sie können ein Betriebssystem fast vollständig in C schreiben, aber der Task-Switcher, in dem sich der SP bewegt, muss sich in der Assembly befinden. Zu verschiedenen Zeiten habe ich Task-Switches für PIC24, PIC32, 8051 und 80x86 geschrieben. Die Eingeweide sind je nach Architektur des Prozessors sehr unterschiedlich.
Die zweite Anforderung besteht darin, dass genügend RAM vorhanden ist, um mehrere Stapel bereitzustellen. Normalerweise möchte man mindestens ein paar hundert Bytes für einen Stapel; Aber selbst bei nur 128 Bytes pro Task benötigen acht Stapel 1 KB RAM - Sie müssen jedoch nicht für jeden Task die gleiche Stapelgröße zuweisen. Denken Sie daran, dass Sie genügend Stack benötigen, um die aktuelle Task und alle Aufrufe der verschachtelten Subroutinen zu verarbeiten, aber auch Speicherplatz für einen Interrupt-Aufruf, da Sie nie wissen, wann einer auftreten wird.
Es gibt ziemlich einfache Methoden, um zu bestimmen, wie viel Stapel Sie für jede Aufgabe verwenden. Sie können beispielsweise alle Stapel auf einen bestimmten Wert initialisieren, z. B. 0x55, und das System für eine Weile ausführen und dann den Speicher stoppen und untersuchen.
Sie sagen nicht, welche Art von PICs Sie verwenden möchten. Die meisten PIC24- und PIC32-Geräte bieten ausreichend Platz für die Ausführung eines Multitasking-Betriebssystems. Der PIC18 (der einzige 8-Bit-PIC mit Stapeln im RAM) hat eine maximale RAM-Größe von 4 KB. Also das ist ziemlich zweifelhaft.
Bei kooperativem Multitasking (das einfachere von beiden) wird die Taskumschaltung nur durchgeführt, wenn die Task ihre Kontrolle an das Betriebssystem "zurückgibt". Dies geschieht immer dann, wenn die Task eine OS-Routine aufrufen muss, um eine Funktion auszuführen, auf die sie warten wird, z. B. eine E / A-Anforderung oder einen Timer-Aufruf. Dies erleichtert dem Betriebssystem das Wechseln von Stapeln, da nicht alle Register und Statusinformationen gespeichert werden müssen. Der SP kann einfach auf eine andere Task umgeschaltet werden (wenn keine anderen Tasks ausgeführt werden können, handelt es sich um einen inaktiven Stack gegebene Kontrolle). Wenn die aktuelle Task keinen OS-Aufruf tätigen muss, aber schon eine Weile ausgeführt wurde, muss sie die Kontrolle freiwillig aufgeben, um das System reaktionsfähig zu halten.
Das Problem mit kooperativem Multitasking besteht darin, dass es das System überlasten kann, wenn die Aufgabe niemals die Kontrolle verliert. Nur es und alle Interrupt-Routinen, die zufällig gesteuert werden, können ausgeführt werden, sodass das Betriebssystem anscheinend abstürzt. Dies ist der "kooperative" Aspekt dieser Systeme. Wenn ein Watchdog-Timer implementiert ist, der nur zurückgesetzt wird, wenn ein Taskwechsel ausgeführt wird, können diese fehlerhaften Tasks abgefangen werden.
Windows 3.1 und frühere Versionen waren kooperative Betriebssysteme, weshalb ihre Leistung teilweise nicht so hoch war.
Präventives Multitasking ist schwieriger zu implementieren. Hier müssen Aufgaben nicht manuell die Steuerung aufgeben, sondern jeder Aufgabe kann eine maximale Ausführungszeit (z. B. 10 ms) zugewiesen werden, und dann wird zur nächsten ausführbaren Aufgabe gewechselt, falls eine vorhanden ist. Dazu muss eine Task willkürlich angehalten, alle Statusinformationen gespeichert und der SP auf eine andere Task umgeschaltet und gestartet werden. Dies macht den Task-Switcher komplizierter, erfordert mehr Stack und verlangsamt das System ein wenig.
Sowohl beim kooperativen als auch beim präemptiven Multitasking können zu jeder Zeit Interrupts auftreten, die die ausgeführte Task vorübergehend präemptieren.
Wie Supercat in einem Kommentar hervorhebt, besteht ein Vorteil von kooperativem Multitasking darin, dass es einfacher ist, Ressourcen gemeinsam zu nutzen (z. B. Hardware wie ein Mehrkanal-ADC oder Software wie das Ändern einer verknüpften Liste). Manchmal möchten zwei Aufgaben gleichzeitig auf dieselbe Ressource zugreifen. Bei der vorbeugenden Zeitplanung könnte das Betriebssystem mithilfe einer Ressource Aufgaben in der Mitte einer Aufgabe wechseln. Daher sind Sperren erforderlich, um zu verhindern, dass eine andere Task hereinkommt und auf dieselbe Ressource zugreift. Bei kooperativem Multitasking ist dies nicht erforderlich, da die Task steuert, wann sie sich selbst an das Betriebssystem zurückgibt.