CCBAS2MT.S19
Echtes Multitasking auf dem
C-Control/BASIC-Mikrokontrollersystem
Autor: Dietmar Harlos
Datum: 15. Januar 2005
Für: C-Control-1 Version 1.1
Was ist Multitasking?
Unter Multitasking versteht man die Fähigkeit eines Computersystems,
mehrere Aufgaben (Tasks) quasi-gleichzeitig zu erledigen. Genaugenommen
werden die Begriffe Multitasking und Multithreading unterschieden. Beim
Multitasking laufen zwei Programme weitgehend unabhängig voneinander
ab, als ob sie auf zwei verschiedenen Computern ausgeführt würden.
Dagegen werden beim Multithreading sogenannte Threads ("Fäden") eines
Programms parallel ausgeführt, teilen sich somit einen gemeinsamen
Adreßraum und können über Variablen sehr einfach Daten
austauschen. Der normalerweise sequentielle Programmfluß wird aufteilt
und quasi-parallel ausgeführt. Quasi-parallel bedeutet, daß
der Computer zwar immer nur einen Thread ausführt, zwischen den Threads
wird aber sehr schnell hin- und hergeschaltet. Die Rechenleistung wird
also aufgeteilt.
Wie ist das Multitasking auf der C-Control-1 realisiert?
Der Programmfluß eines CCBASIC-Programms wird in zwei Threads
aufgeteilt, die von einem Multitasking-Interpreter ausgeführt werden.
Es handelt sich bei diesen Threads im Prinzip um zwei getrennte Programme,
die aber die gleichen Variablen und Systemressourcen verwenden und im gleichen
CCBASIC-Sourcecode stehen. Zwischen den Threads wird standardmäßig
einige hundert Mal pro Sekunde hin- und hergeschaltet, wodurch jeder Thread
mit ungefähr der halben Geschwindigkeit abläuft. Falls ein Thread
weniger Leistung benötigt, kann er Rechenleistung freigeben, die dem
anderen Thread zugute kommt.
Jeder Thread besitzt seinen eigenen Programm-Counter, Rechenstack und
GOSUB-Stack, welche vom Multitasking-Interpreter bei jedem Taskwechsel
ausgetauscht werden müssen. Dafür werden 12 Bytes des DCF77-Buffers
verwendet, so daß weder ein DCF77-Empfänger noch eine andere
Signalquelle am DCF/FREQ1-Pin der C-Control angeschlossen werden darf!
BASIC-Interruptroutinen werden vom Multitasking-Interpreter ebenfalls nicht
unterstützt, denn da der DCF77-Buffer bereits belegt ist, läßt
er sich nicht mehr zum Zwischenspeichern des Rechenstacks bei Verwendung
einer Interruptroutine verwenden (siehe ONTIMER.ZIP
auf C-Control-intern).
Wieviel Leistung geht durch das Multitasking verloren?
Obwohl jeder Taskwechsel relativ aufwendig ist, entsteht durch das Multitasking
praktisch kein Leistungsverlust. Laufen beide Threads ungebremst, erreicht
jeder Thread ziemlich genau die halbe Geschwindigkeit im Vergleich zum Ablauf ohne
Multitasking. Ein Thread, der augenblicklich wenig Leistung benötigt,
kann einen Großteil der Rechenzeit freigeben, wodurch der andere
Thread bis auf seine volle Normalgeschwindigkeit kommt. Damit die Vorteile
des Multitaskings voll zum Tragen kommen, ist es sinnvoll, die C-Control
mit einer höheren Taktgeschwindigkeit auszustatten. Der standardmäßige
4-MHz-Quarz kann durch eine 8-, 12-, 16-, oder sogar 24-MHz-Version ausgetauscht
werden. Ab 16 MHz muß allerdings auch das externe I2C-EEPROM (24C65)
durch eine Version ausgetauscht werden, die einen schnelleren I2C-Bus-Takt
unterstützt. Siehe FAQs.
Was ist gegenüber der herkömmlichen Singletask-Programmierung
zu beachten?
Für den normalen CCBASIC-Programmierer ändert sich trotz der
unterschiedlichen Programmausführung nur sehr wenig. Zu beachten ist
in erster Linie, daß einige CCBASIC-Befehle, die den Programmfluß
lahmlegen, mit Vorsicht verwendet werden sollten, da diese auch die Taskumschaltung
hemmen. Vor allen Dingen sind das die beiden Befehle GET und INPUT, die
so lange warten, bis passende Daten von der seriellen Schnittstelle gelesen
werden können. Vor dem Einsatz dieser Befehle sollte deshalb zum Beispiel
mittels RXD geprüft werden, ob überhaupt Daten an der seriellen
Schnittstelle zur Verfügung stehen. Darüberhinaus ist innerhalb
einer mit SYS aufgerufenen Assemblerroutine systembedingt kein Taskwechsel
möglich.
Hat ein Thread seine Aufgaben vorerst erledigt, kann er mittels PAUSE-Befehl
Rechenzeit freigeben. Ein PAUSE-Befehl bewirkt ein vorzeitiges Umschalten
zum anderen Thread. Außerdem kann im PAUSE-Parameter übergeben
werden, wieviele 20-ms-Zeiteinheiten der andere Task anschließend
mindestens ausführen darf, bevor der nächste Taskwechsel stattfindet.
Erlaubte Werte liegen im Bereich von 0 bis 255. Der BEEP-Befehl enthält
übrigens einen versteckten PAUSE-Befehl. Die maximal mögliche
Rechenleistung wird dem verbliebenen Thread zugewiesen, falls sich ein
Thread mittels END beendet.
Falls Systemressourcen (z.B. die Datendatei) von beiden Threads verwendet
werden dürfen, ist es notwendig, mit Hilfe eines Flags zu signalisieren,
das die entsprechende Systemressource augenblicklich belegt ist. Ansonsten
kann es zu sehr unschönen Effekten bis hin zu Datenverlusten kommen.
Ich habe sieben kleine Beispielprogramme erstellt, die zeigen, wie einfach
Multitasking-Programme in CCBASIC erstellt werden können. Die Textausgaben
der Programme werden auf der seriellen Schnittstelle übertragen,
deshalb sollte auf dem PC ein Terminalprogramm benutzt werden. Außerdem
verwenden einige Programme den BEEP-Ausgang. Hier sollte, falls noch nicht
geschehen, ein Piezo-Schallwandler angeschlossen werden.
Kann man noch einen zusätzlichen, dritten Thread ins System
integrieren?
Noch einen weiteren Thread hinzuzufügen, also drei Threads gleichzeitig
zu unterstützen, ist recht schwierig, da noch einmal mindestens 12
Bytes im RAM zum Zwischenspeichern des BASIC-PC, des Rechenstacks und des
GOSUB-Stacks benötigt werden. Bei einer C-Control, die auf einem 68HC705-Mikrokontroller
basiert, wäre das kein Problem, denn dieser Kontrollertyp besitzt
176 zusätzliche RAM-Bytes. Auf der Standard-C-Control könnte
man höchstens einen Teil des Hardwarestacks verwenden. Aber der ist
vorgesehen, um in selbstgeschriebenen Assemblerprogrammen Unterprogrammaufrufe
durchzuführen. Deshalb könnten keine eigenen Assemblermodule
mehr verwendet werden. Aber das ginge in diesem Fall ohnehin nicht, da
das interne EEPROM komplett mit dem Multitasking-Interpreter belegt sein
würde. Auch hier böte sich wieder der 68HC705 an, denn der besitzt
ein 16 kB großes EPROM zur Aufnahme des Betriebssystems und für
zusätzliche Assemblerprogramme wie den Multitasking-Interpreter. Siehe
CC1-OS-Project.
Viel Spaß beim C-Controllern!
Dietmar Harlos
http://ccintern.dharlos.de