In vielen Aufgabenstellungen kommt es vor, dass gewisse Dinge in bestimmten
Abständen periodisch ausgeführt werden müssen. Eine Gruppe
solcher Aufgabenstellungen sind z.B. Regelungsprobleme. Mit Sensoren werden
regelmäßig eine oder mehrere Größen (z.B. Druck,
Temparatur,...) eines Systems gemessen, abhängig von der Abweichung von
ihren Sollwerten wird über einen oder mehrere Aktoren versucht, diese
Größen wieder auf ihre Sollwerte einzustellen.
Ein sehr bekanntes Beispiel für ein Regelungsproblem im Bereich der
Echtzeitsysteme ist das sog. Inverse Pendel:
Auf einem Wagen ist ein bewegliches Pendel montiert. Ziel ist es, das
Pendel in aufrechter Position zu halten. Dazu ist es notwendig, den Wagen in
Abhängigkeit der Abweichung des Pendels von der Senkrechten nach rechts
oder links zu beschleunigen. Diese Regelung geschieht, indem in
regelmäßigen Abständen der Winkel gemessen wird, den das
Pendel mit der Senkrechten einschließt, und anschließend ein
Signal an einen Aktor (z.B. ein Motor) gesendet wird, der den Wagen
entsprechend beschleunigt.
Für die Abbildung solcher regelmäßig stattfindenden
Vorgänge auf ein mikrocontroller-gesteuertes System sind
sog. ScheduleTables gut geeignet. Eine ScheduleTable ist nichts
anderes als eine Tabelle, die auflistet, zu welcher Zeit bestimmte
Aktivitäten ausgeführt werden sollen. Diese Tabelle wird vom
Scheduler mit einer bestimmten Periode zyklisch abgearbeitet. Das folgende
Beispiel zeigt eine solche Tabelle. Sie enthält insgesamt vier
Einträge, die mit einer Periode von 8 ms zyklisch ausgeführt
wird. Die Startzeiten der einzelnen Threads beziehen sich dabei auf den Beginn
der Tabelle. Die Grafik veranschaulicht die Abfolge der verschiedenen Threads,
wie sie zur Laufzeit entsteht.
In dieser Aufgabe soll ein ScheduleTable-Scheduler implementiert
werden. Hierfür sind die folgenden, rot eingerahmten Klassen zu
implementieren:
Schedule_Table_Entry
Diese Klasse ist einfach das C++-äquivalent zum Tupel aus Thread und
Startzeitpunkt.
Schedule_Table< SIZE > und Abstract_Schedule_Table
Die beiden Klassen Schedule_Table< SIZE > und
Abstract_Schedule_Table entsprechen Tabellen, die die
Startzeitpunkte der einzelnen Threads enthalten. Die Klasse
Schedule_Table< SIZE > wird als C++-Template implementiert,
weil es möglich sein soll, Tabellen verschiedener Größe zu
erzeugen - ohne dynamische Speicherverwaltung ist dies nur über
C++-Templates möglich. Die Template-Implementierung macht aber eine
gesonderte abstrakte Schnittstelle notwendig, über die der Scheduler auf
die Tabelle zugreifen kann. Diese Schnittstelle stellt die Klasse
Abstract_Schedule_Table zur Verfügung.
Schedule_Table_Scheduler und Guarded_Schedule_Table_Scheduler
Die Klasse Schedule_Table_Scheduler stellt die eigentlich
Implementierung des Schedulers dar, der den Timer ansteuert und die Tabelle
der zu startenden Threads abarbeitet. Die Klasse
Guarded_Schedule_Table_Scheduler stellt eine gegen
Unterbrechungen geschützte Schnittstelle für den eigentlichen
Scheduler zur Verfügung.
Thread
Eine scheduler-spezifische Implementierung eines Threads.
Eine genauere Beschreibung der jeweiligen Klassen und der zu implementierenden
Schnittstellen, findet man in der Doxygen-Dokumentation von EZ-Stubs.
Im Laufe dieser Übungen werden verschiedene Varianten von EZStubs
entwickelt, die weder vom Quelltext noch von der Semantik her kompatibel
zueinander sind. Im Rahmen eines
Versionsverwaltungssystems im allgemeinen und SVN im Speziellen gibt es nun
verschiedene Möglichkeiten mit diesen Inkompatibilitäten umzugehen:
Man ignoriert diese Inkompatibilität und überschreibt die
existierenden Implementierung mit der neuen Implementierung, alte, nicht
mehr benötigte Quelltextdateien müssen evtl. entfernt werden
(svn remove).
Man merkt sich den gegenwärtigen Stand der Entwicklung mit einem Tag
(svn copy) und verfährt ansonsten wie oben.
Man legt einen Branch an und arbeitet auf diesem Branch weiter (svn
copy + svn switch), dieser Branch kann das gesamte
Repository oder nur betroffene Module enthalten, in unserem Fall wäre
z.B. nur das Unterverzeichnis thread betroffen.
Um auch später noch auf die verschiedenen Varianten zugreifen zu können,
verwenden wir in diesen Übungen die letzte angebotetene Variante, konkret
heißt das:
cd ezstubs
Einen Branch anlegen: svn copy
. https://www4.informatik.uni-erlangen.de:8088/i4ezs/<gruppe>/branches/time_triggered. Bevor
ihr den Branch anlegt, solltet ihr darauf achten, dass eure aktuelle
Arbeitskopie sauber ist, d.h. alle Dateien sollten aktuell sein und es
sollten sich keine modifizierten Dateien mehr in eurer Arbeitskopie
befinden.
auf den neu angelegten Branch wechseln: svn switch
https://www4.informatik.uni-erlangen.de:8088/i4ezs/<gruppe>/branches/time_triggered
die Vorgabe in das Arbeitsverzeichnis entpacken und die neuen Dateien zum
Repository hinzufügen (svn add)
die Änderungen an das Repository senden (svn commit)