Aufgabe: Timer Framework
Übersicht
Einleitung
Was ist zu tun?
Hinweise
Diese Aufgabe dient in erster Linie dazu, sich mit der Entwicklungsumgebung
vertraut zu machen, also die Eigenheiten des Simulators, der GNU Toolchain, des
Debuggers und hardwarenaher Programmierung zu erkunden. Ein sicherer Umgang mit
diesen Werkzeugen erleichtert die Bearbeitung aller Aufgaben.
Inhaltlich geht es in dieser Aufgabe im Wesentlichen um die Abbildung der realen Zeit in einem Echtzeitsystem. Weil in Echtzeitsystemen das Fortschreiten der realen Zeit einen unvermeidbaren Einfluss auf die Bearbeitung von Aufgaben hat, ist es oft unabdingbar, im Echtzeitsystem eine explizite Repräsentation der realen Zeit verfügbar zu haben.
Für die Realisierung dieser Repräsentation werden so gut wie immer sog. Zeitgeber (engl. Timer) verwendet, die man sich einfach als Uhren vorstellen kann: in Intervallen bestimmter Dauer wird ein Zähler hochgezählt, die Dauer der Intervalle ist in vielen Fällen konfigurierbar. Das Fortschreiten des Zählerstandes ist somit ein Maß für das Fortschreiten der realen Zeit.
In dieser Aufgabe geht es nun darum für die Timer-Bausteine des Gameboy-Advance einen Treiber zu schreiben und auf diese Timer sog. Ereigniszähler (engl. Counter) aufzusetzen. Diese Counter dienen ihrerseits als Basis für sog. Alarme. Alarme lassen sich aktivieren und laufen nach einer bestimmen Zeit ab, zum Zeitpunkt des Ablaufens wird dann eine bestimmte Aktion ausgeführt. In EZStubs soll eine Callback-Funktion aufgerufen werden.
In dieser Aufgabe soll ein kleines Timer Framework implementiert
werden. Hierfür sind die folgenden, rot eingerahmten Klassen zu
implementieren:
TM< OFFSET,VECTOR >
Die Klasse TM
ist die direkte Abbildung des 16-bit Timer des
Gameboy Advance und implementiert die durch die Schnittstellenklasse
Interrupt_Timer
vorgegebene Schnittstelle. Sie dient als Basis
für die konkreten Timer TM_0 ... TM_3, der Template-Parameter
OFFSET
bezeichnet den Offset der I/O-Register des jeweilgen
Timers, der Template-Parameter VECTOR
den vom Timer benutzen
Interrupt-Vektor.
User_Counter und Guarded_User_Counter
Ein User_Counter
ist ein Ereigniszähler und kann als Zeitbasis
für Alarme verwendet werden. Die Alarme werden in einer sortierten,
verketteten Liste verwaltet. Wenn ein Alarm abläuft, ruft der
user_Counter
die Methode expire()
des Alarms
auf. Für die Verwaltung des eigentlichen Zählers ist die Klasse
Basic_Counter
zuständig.
Hardware_Counter< INTERRUPT_TIMER >
Ein Hardware_Counter
ist im Wesentlichen ein
User_Counter
, der die Unterbrechungen, die von einem
Interrupt_Timer
generiert werden, zählt. Welcher Timer die
Unterbrechungen erzeugt, wird über den Template-Parameter
INTERRUPT_TIMER
bestimmt.
Alarm und Guarded_Alarm
Ein Alarm
stellt eine Eieruhr dar, die so aufgezogen werden
kann, dass sie entweder einmalig oder periodisch abläuft. Zum Zeitpunkt des
Ablaufs, der durch einen User_Counter
oder einen
Hardware_Counter
bestimmt wird, wird eine Callback-Funktion
ausgeführt.
Alarm_Comparator
Die Klasse Alarm_Comparator
stellt eine statische Methode
compare(Alarm* alarm1,Alarm* alarm2)
zur Verfügung, die es
erlaubt zwei Alarme hinsichtlich ihres nächsten Ablaufzeitpunkts zu
vergleichen. Diese Klasse wird für die Einfügeoperation in die sortierte Liste
von Alarmen, der Alarm_Queue
verwendet.
- Zuerst die Dokumentation für die Timer lesen!
- Der Gameboy Advance besitzt keine Maschinenbefehle um Fließkommazahlen zu verarbeiten, alle benötigten Berechnungen werden daher mit Ganzzahlen durchgeführt.
- Vorsicht bei Ganzzahlarithmetik!
- Empfohlenes Vorgehen:
- Treiber für den Timer implementieren und sicherstellen, dass der Timer Unterbrechungen erzeugt (Breakpoint auf
wrapper_body
setzen)
User_Counter
implementieren
Alarm
implementieren
- Zusammenspiel von
User_Counter
und Alarm
testen
Hardware_Counter
implementieren
- Zusammenspiel von
Hardware_Counter
und Alarm
testen