Tips für PICs 11: Multitasking

Ein PIC ist zwar ein leistungsfähiger Microcontroller, aber seinen Aktivitäten sind doch arge Grenzen gesetzt. So fehlt ihm ein Betriebssystem (beim PC könnte dieses 'Windows' oder 'Linux' heißen), das verschiedene anfallende Arbeiten koordiniert.
Eine solche Koordination muß der PIC-Programmierer selber vornehmen. Der PIC besitzt eine Hardware, die eine Unterbrechung des laufenden Programms ('Interrupt') bewirkt. Hiermit kann der Programmierer Programmteile schreiben, die eine solche geforderte Koordinierung ermöglichen.

Wir sind dabei, für das Faller-Car-System eine Infrarot-Fernsteuerung zu bauen. Die Autos sollen dabei durch einen PIC an Bord gesteuert werden, der von außen Befehle über Infrarot-Licht erhält.
Die Aufgabenstellung für diesen PIC lautet:
- empfange Datentelegramme,
- erzeuge Datentelegramme,
- erzeuge eine PWM (pulsweitenmodulierte Spannung) für den Motorantrieb,
- erzeuge eine schnelle Pulsfolge für einen Spannungsvervielfacher,
- erzeuge eine langsame Pulsfolge für einen Blinker.
Diese Aufgaben hat er praktisch gleichzeitig zu bewältigen.
Das Erzeugen der Telegramme und Impulsfolgen geschieht aktiv vom PIC aus (der sich somit die Zeit hierfür in engen Grenzen selber einteilen kann), wobei jedoch das Empfangen eines Telegramms eine sofortige Reaktion verlangt, da ansonsten wichtige Informationen verloren gehen. Das bedeutet aber, daß, egal was gerade an Arbeiten anliegt, der PIC diese sofort unterbrechen muß, um das Empfangen vorzunehmen. Jedoch dürfen hierdurch die anderen Arbeiten keinesfalls in Mitleidenschaft gezogen werden. Im Klartext heißt dies, daß z.B. die Ansteuerung des Motors sich nicht ändern darf, nur weil gerade ein Telegramm empfangen wird.

So etwas wird als 'Multitasking' bezeichnet, also mehrere Dinge quasi-gleichzeitig zu machen, ohne daß diese sich auch nur im Geringsten gegenseitig behindern. Hierfür benötigt ein wie auch immer gearteter Rechner eine Interrupt-Verarbeitung. ('Interrupt' könnte man mit 'Unterbrechungs-Anforderung' übersetzen.) Dies bedeutet, daß der PIC, wenn er einen solchen Interrupt erkennt, sofort jede softwaremäßige Arbeit unterbrechen muß und in einem 'Interrupt-Bearbeitungs-Programm' (IR-Routine) diesen Interrupt bearbeiten muß, und das mit höchster Priorität. Bei kleinen PICs (wie wir sie verwenden) ist der Einbau einer IR-Routine von der Hardware her ermöglicht. Diese Routine selber ist nicht noch einmal durch weitere Interrupts unterbrechbar und muß daher ihre Arbeiten in kürzestmöglicher Zeit abschließen. Evtl. währenddessen auftretende weitere Interrupts gehen nicht verloren. Sie müssen aber warten, bis sie an die Reihe kommen. Es ist natürlich klar, daß für solche Arbeiten Rechenzeit 'abgezwackt' wird, die anderen Aktivitäten nun nicht zur Verfügung steht.

Lösung
Ein Multitasking kann nur funktionieren, wenn:
a) der Rechner relativ viel 'Freizeit' hat und
b) der Programmierer das Programm richtig schreibt.
zu a:
Die Zeit, in der der Rechner Aufgaben bearbeitet, darf nur etwa 1 bis allerhöchstens 10 % der Gesamtzeit sein.
zu b:
Prinzip Schlechte Programmierung kann für das Multitasking tödlich sein. Alle Takte, alle Zeitverzögerungen dürfen niemals über NOP-Schleifen (das sind Programmstellen, in denen der Rechner "no-operation"-Befehle bearbeitet, also durch Nichts-Tun Zeit schindet) bewerkstelligt werden. Vielmehr muß das Hauptprogramm in einer einzigen unbehinderten Schleife laufen können und nur 'gelegentlich' in eine Aufgabe verzweigen. Es darf nur an einer einzigen Stelle eine Warteposition (d.h. eine Warteschleife) haben, in der es, nach getaner Arbeit, auf einen Takt von einem Zeitgeber (der, wenn er abgelaufen ist, einen Interrupt erzeugt) wartet. Alle anderen Zeiten müssen von diesem Takt abgeleitet werden. Jede Art von Rückwärtsschleifen ist verboten. Sprünge sind daher nur vorwärts erlaubt. Die IR-Routine darf nur die wirklich allernötigsten Befehle enthalten, damit nicht zu viel Zeit bei der Abarbeitung verloren geht.
Am sichersten und sinnvollsten ist es, überhaupt keine Wartestellen zu programmieren, sondern, wie im nebenstehenden Bild gezeigt, die Hauptprogrammschleife selber als Warteschleife zu verwenden.
So eine Programmstruktur ermöglicht es, daß der Rechner alle Arbeiten erledigt hat, wenn er auf die Warteschleife stößt. Im Bild, das dieses Prinzip darstellen soll, ist diese Warteschleife in Rot gekennzeichnet. Der PIC rast also in Höchstgeschwindigkeit durch die rote Schleife und fragt nur ab, ob etwas getan werden muß. In der Interrupt-Routine haben sich u.a. irgendwelche Timer gemeldet, da ihre vorgegebene Zeit abgelaufen ist. Dort werden wenige zeitkritische Vorgänge wie das Ende eines auszugebenden Impulses bearbeitet. Meist genügt aber das Setzen einer Kennung, daß diese Zeit abgelaufen ist. Dies ist im Bild oben dargestellt.
Die beiden gezeichneten Programmteile kommunizieren also nur durch Setzen von Kennungen, sind aber ansonsten voneinander unabhängig.

Starker Tobak!
Deshalb wollen wir die vorgeschlagene Vorgehensweise an Beispielen aus unserer Auto-Steuerung verdeutlichen:
Der schnellste benötigte Takt ist der für die Ausgabe eines Telegramms. Alle anderen Takte sind von diesem Takt abgeleitet; man kann auch sagen, sie sind Vielfache dieses Taktes.
Dieser Takt wird von einem Timer (einer Hardware-Uhr im PIC) erzeugt, der die hilfreiche Eigenschaft besitzt, völlig unabhängig von den Software-Aktivitäten zu laufen und daher nicht von ihnen gestört wird; und umgekehrt! Er beträgt in unserem Beispiel 200 µs. Weil wir es gleich noch mit anderen Timern zu tun bekommen werden, wollen wir diesen Vorgang als 'Muttertakt' bezeichnen. Dieser wird (über den Timer) hergeleitet aus dem Takt des Oszillators, der den gesamten PIC in Gang hält.

Ein kleines Detail hierzu:
Wenn ich einen Impuls für ein Telegramm oder die Motorsteuerung ausgeben will, dann schalte ich den entsprechenden Ausgang am PIC ein; darf jetzt aber auf keinen Fall warten, bis der Impuls zuende sein soll; sondern ich muß einen weiteren Timer (wir nennen ihn hier 'Impuls-Timer') mit der geplanten Impulsdauer starten und dann sofort andere Aufgaben erledigen. Erst wenn alles abgearbeitet ist, darf ich an der zentralen Wartestelle 'Däumchen drehen' und auf den Muttertakt (oder andere Ereignisse) warten.
Irgendwann wird der 'Impuls-Timer' abgelaufen sein und sich per Interrupt melden. Hier muß die IR-Routine nichts weiter tun als nur den Impuls-Ausgang wieder abschalten; eine Arbeit, die in wenigen µs erledigt ist. Tricky dicky: in einem solch einfachen Fall lohnt es sich nicht, daß die IR-Routine eine Kennung setzt, damit dann das Hauptprogramm den Impuls abschaltet! Es ist wirklich nur ein einziger Befehl dazu vonnöten; das Setzen einer Kennung dauert länger ...
Ähnliches geschieht auch beim Empfangen eines Telegramms: Die ansteigende Flanke eines Impulses erzeugt einen Interrupt. In der IR-Routine wird wieder ein Timer ('Telegramm-Timer') mit einer Rückmelde-Zeit von genau 100 µs gestartet, mehr muß nicht getan werden. Meldet sich der Telegramm-Timer, wieder per Interrupt, so wird der Telegramm-Eingang abgefragt, ob der Impuls immer noch ansteht. Wenn ja, ist es ein '1'-Impuls; wenn nein, ist eine '0' empfangen worden. Dieser Wert wird vermerkt. Und wieder ist mit sehr wenig Rechenzeit ein Ereignis abgearbeitet worden.
DCC (Zum Verständnis: Unsere Norm für die Übertragung der Infrarot-Befehle besagt, daß die Impulse einen Takt von 200 µs haben. Eine '0' hat eine Impulsdauer von 67 µs, eine '1' eine von 133 µs. Wenn ich den Telegramm-Eingang genau 100 µs nach Impuls-Beginn abfrage, ist ein '0'-Impuls schon lange zuende, aber ein '1'-Impuls dauert noch lange an.)

Das Warten auf den 'Muttertakt' geschieht einfach, indem ich einen Merker auf '1' setze und dann warte, bis die IR-Routine diesen wieder auf '0' gesetzt hat. So startet der 'Rundlauf' des Hauptprogramms immer im selben Takt, egal, was und wieviel zwischendurch erledigt werden mußte.
Mit einer solchen Strategie lassen sich tatsächlich mehrere zeitkritische Vorgänge bearbeiten.
In der nebenstehenden Zeichnung sehen Sie die Aufgaben, die ein PIC in einem unserer Faller-Car-Fahrzeuge erledigen soll. Das meiste funktioniert bereits. Das Prinzip ist richtig.

Für weitere Fragen stehen gern zur Verfügung:
- der MEC; Besichtigung und Fachsimpelei z.B. an unseren "Club-Abenden"
- der Autor: Hans Peter Kastner

erstellt am: 01.01.2015
Copyright © 2015 by Modelleisenbahnclub Castrop-Rauxel 1987 e.V.