Verwenden Sie keine Threads, verwenden Sie eine Ereignisschleife.
Der PIC18 ist ein kleiner Prozessor und ein auf Event-Loop basierender Stil bedeutet, dass Sie nicht viele tiefe Stapel herumhängen müssen. Sie müssen Ihren Code in Bezug auf die Ereignisschleife schreiben, aber das ist wahrscheinlich sinnvoll.
Wenn Sie einige lange laufende Aufgaben haben, verwenden Sie Timer mit unterschiedlichen Interrupt-Prioritätsstufen, um Ereignisschleifen mit höherer Priorität zu ermöglichen, Ereignisschleifen mit niedrigerer Priorität vorzuenthalten und entsprechende Arbeitstypen in die entsprechende Ereigniswarteschlange einzufügen.
Sie können Cooperative Multitasking ausprobieren.
Für Arten von Problemen, die PICs lösen, würden Sie wahrscheinlich besser sein, wenn Sie ein anderes Design ausprobieren, das Interrupts oder Polling statt mehrerer Threads verwendet.
Sie können dort ein RTOS setzen (es gibt einen inoffiziellen ucOS-Port ), oder Sie könnten nachsehen out FreeRTOS PIC18-Port ).
Andernfalls könnten Sie versuchen, Korotinen in C zu implementieren, indem Sie setjmp
und longjmp
verwenden.
Wenn überhaupt kein Betriebssystem vorhanden ist, müssen Sie (offensichtlich) die erforderliche Funktionalität selbst erstellen.
Der einfachste Weg zu folgen wäre wahrscheinlich, einen Timer-Interrupt zu installieren, der auf einer geeigneten Frequenz läuft (hängt wahrscheinlich von Ihrer tatsächlichen Taktrate ab, aber vielleicht im Bereich von 100-1000 Hz). Im Interrupt-Handler müssen Sie den Status des aktuellen Threads überprüfen und entscheiden, ob ein Wechsel stattfinden soll.
Der Trick besteht darin, den Schalter bei Bedarf zu aktivieren und vom Interrupt-Handler in einen anderen Thread zurückzugeben.
Natürlich ist es nicht unbedingt einfach, dies zu erreichen, wenn die Threads selbst Interrupts verwenden.
Sie könnten auch nach der Installation eines Kernels suchen, vielleicht Contiki .
Hier ist ein Beispiel für "protothreads" für den PIC18 , sieht wie eine angemessene Menge an Code aus. Nicht sicher über die Semantik, though.
Update : Dies wird wahrscheinlich erfordern Sie einige der niedrigsten Code in Assembler (Ich bin mir nicht sicher, habe nicht in C auf dem PIC, so dass ich nicht genau weiß wie viel Kontrolle du bekommst). Sie müssen die Kontrolle über die Register den Programmzähler, und das sind nicht C-Konzepte.
Beachten Sie, dass einige "Threads" auf Mikrocontrollern auch nur von einem bestimmten Interrupt-Handler verarbeitet werden können und daher "parallel" zu Ihrer Hauptereignisschleife laufen.
z. Wenn ein externes Ereignis eine ADC-Konvertierung auslöst, kann Ihr ADC-conversion-done-Handler diesen Wert annehmen, einige Berechnungen durchführen und dann einige Ausgabebits setzen, um die Steuerausgabe gemäß dem ADC-Wert anzupassen. All das kann im Interrupt-Handler passieren und damit parallel zu allem anderen.
Abhängig von den Dingen, die Sie parallel tun müssen, können Sie eine Kombination aus mehreren Techniken wählen, um Dinge wie vorgesehen parallel arbeiten zu lassen.
Vielleicht möchten Sie diesen Artikel aus der Embedded-System-Programmierung lesen: Baue einen Super Simple Tasker
Der CCS-Compiler enthält ein RTOS. Ich habe es nicht verwendet, aber aus dem Compilerhandbuch :
Das CCS-Echtzeitbetriebssystem (RTOS) ermöglicht einen PIC-Mikrocontroller um regelmäßig geplante Aufgaben auszuführen ohne die Notwendigkeit von Unterbrechungen. Dies wird durch eine Funktion erreicht (RTOS_RUN ()), die als a fungiert Dispatcher. Wann ist eine Aufgabe geplant? zu laufen, gibt die Dispatch-Funktion Steuerung des Prozessors für diese Aufgabe. Wenn die Aufgabe ausgeführt wurde oder benötigt den Prozessor nicht mehr, Kontrolle über den Prozessor wird zurückgegeben zur Versandfunktion welche dann wird die Kontrolle über den Prozessor geben die nächste Aufgabe, die geplant ist zur passenden Zeit ausführen. Dies Prozess heißt kooperativ Multitasking.
Nur ein Wort der Warnung - überprüfen Sie ihre Foren für Informationen über die spezifischen Funktionen, die Sie suchen. Anscheinend hat CCS die Angewohnheit, neue Funktionen zu veröffentlichen, bevor sie vollständig getestet werden. Das ist einer der Gründe, warum ich immer noch die ältere Version verwende (v3.249).
Beim 8051 habe ich Dual-Tasking mit einem einfachen Stack-Switcher gemacht. Ich würde erwarten, dass das gleiche auf dem PIC getan werden könnte, vorausgesetzt, dass jede Aufgabe nur 16 Stapelebenen verwendet. Der Code wäre in etwa so (geht davon aus, dass _altSP in der gemeinsamen Bank ist)
%Vor%Die Hauptaufgabe sollte _InitTask2 aufrufen, um die zweite Aufgabe zu starten. Die zweite Task wird ausgeführt, bis sie _TaskSwitch aufruft, woraufhin die Haupttask die Ausführung nach der Anweisung, die _InitTask2 aufgerufen hat, wieder aufnimmt. Von da an wird die andere Task die Ausführung jedes Mal, wenn eine Task _TaskSwitch aufruft, von der letzten Stelle, an der sie _TaskSwitch aufgerufen hat, wieder aufnehmen.
Wenn Sie diesen Ansatz verwenden, muss Ihr Compiler informiert werden, dass alle Register durch Aufrufe von _InitTask2 oder _TaskSwitch verworfen werden können. Es muss auch gesagt werden, dass _Task2Start und Funktionen, die es aufruft, von der Hauptaufgabe separaten Variablenraum zugewiesen werden müssen.
Ich bin nicht sicher, was Sie dem Compiler sagen müssen, um es glücklich zu machen, aber ich werde sagen, dass kooperatives Dual-Tasking einige Dinge wirklich gut funktionieren lassen kann.
Ich möchte meinen kleinen Kernel in der Programmiersprache C teilen, um Aufgaben auf einem Mikrocontroller zu verwalten. Sie können eine Aufgabe mit einem Zeitraum erstellen, einen Aufgabenzeitraum jederzeit unterbrechen, fortsetzen und ändern. Dieser Kernel kann alle Aufgaben löschen, um einen anderen Sequenzer zu erstellen. Eine TickGet-Funktion wird vom Kernel bereitgestellt, um alle Timer wie gewünscht zu verwalten. Sie müssen nur eine Interrupt-Funktion erstellen und die Funktion Timer () ersetzen, um Ihren winzigen Kernel für Ihre eigene Anwendung zu erhalten. Um fortzufahren, basiert dieser Kernel auf einer zirkulär verknüpften Liste, um Task für Task zu wechseln. Es wird bereitwillig in einer allgemeinen Weise geschrieben, um Leuten zu helfen, für ihre eigenen Anwendungen besonders anzufertigen. Es gibt keine Priorität zwischen Aufgaben wie eine Round-Robin-Aufgabenplanung. Und ich habe diesen Quellcode in Bezug auf die MISRA-Richtlinien (Automotive Norm) geschrieben Sie können es herunterladen hier
Ich hoffe, den Leuten zu helfen, Aufgaben auf dem Mikrocontroller zu verwalten.
Ich stimme mit ndim überein - Sie können sich jeden Interrupt-Handler als etwas wie einen "Thread" vorstellen. Manchmal können alle Aufgaben, die Sie erledigen müssen, von Interrupt-Handlern verarbeitet werden, die durch externe und interne Ereignisse ausgelöst werden - die "Hauptschleife" ist eine Leerlaufschleife, die nichts tut.
Ich weiß nicht, wo einige Kommentatoren die Idee haben, dass es für das PIC18 "kein Betriebssystem" gibt. Es gibt einige PIC-spezifische Multithreading-Bibliotheken und "Multitasking-Betriebssystemkernel" für den PIC18, von denen viele frei und Open Source sind. Siehe PICList: "PIC Microcontroller-spezifische Multitasking-Methoden" .
Ich mache es (im engeren Sinne kooperatives Multitasking bei fester Aufruf-Stack-Tiefe).
Es funktioniert, aber der Hitec-c-Compiler funktioniert gegen mich - er verwendet Speicherplätze für temporäre Variablen aus Funktionen, von denen er denkt, dass sie nie gleichzeitig ausgeführt werden. Grundsätzlich korrumpieren sich Threads gegenseitig. Wenn ich einen Weg finde, werde ich diese Antwort mit Beispielcode aktualisieren.
Tags und Links c multithreading embedded pic pic18