3 Modularität, Basissystem, Systemaufbau

Die Beschränkung auf den Programm-Speicherbereich von 8 Kb Flash RAM, die Tatsache, dass Assemblerprogrammierung eine maximale Optimierung ermöglicht und der Versuch, eine Methode zur effizienten Umsetzung größerer Projekte mittels Assembler zu erarbeiten, haben dazu geführt, dass die gesamte Software in ATMEL Assembler umgesetzt wurde.

Um nun Software in dieser relativ komplexen Anforderung effizient umsetzten zu können, ist es notwendig, die Programmstruktur modular zu halten und gewisse Abstraktionsschichten einzuführen, um, einerseits die Entwicklung Problemkreis bezogen durchführen zu können und andererseits möglichst ,,einfache'' und überschaubare Programmmodule zur Verfügung zu haben. Damit ist zusätzlich auch ein gewisses Maß an Portabilität zu erreichen, falls eine ähnliche Anforderung mit einer anderen Hardware umgesetzt werden soll.

Abb. 7.2 zeigt, dass das Basissystem - wie auch bei Betriebssystemen üblich - in einzelne Schichten unterteilt wurde [7] S. 175. Die Grundidee, die dahinter steckt, ist, dass eine Schicht bestimmte ,,Services'' liefert, die von der darüber liegenden Schicht ohne Berücksichtigung der darunter liegenden Mechanismen verwendet können.

Figure 7.2: Applikationsaufbau
\includegraphics[%
width=6cm]{graphics/Basissystem.eps}

Hinweis:
Diese Gliederung darf nicht mit dem ISO-OSI Schichten-Modell verwechselt werden, das vorwiegend für den Kommunikationsbereich definiert wurde, sondern die Schichten wurden hier ausschließlich nach definierten, aus den Gegebenheiten für sinnvoll erachteten Grenzen festgelegt.
Zusätzlich wurde durch extensive Nutzung von ,,symbolischen'' Konstanten und durch die Verwendung vom Assembler-Makros versucht, die Lesbarkeit des Source-Codes zu verbessern um damit einen wesentlichen Nachteil gegenüber einer Hochsprachenumsetzung wieder Wett zu machen.

  1. Im vorliegenden Fall besteht die Applikationsschicht aus dem Benutzerinterface (GUI) und der Menüsteuerung der obersten Menüebene. Diese besteht aus einem Menüauswahl Event-Loop, um eine der Top-Level Funktionen und damit den Funktionsmodus festzulegen (siehe dazu auch 7.6.1). Wie im folgenden Punkt ersichtlich, wurde diese Schicht vorwiegend aus software-organisatorischen Überlegungen eingeführt, sie beinhaltet keine funktionellen Komponenten, die in Schicht 2 ausgeführt werden, eine Änderung der Benutzeroberfläche (wie z.B. die Implementierung von Zeit- und Datumsanzeigen) würde in diesen Bereich fallen.
  2. Die Programmsteuerung ist in der Art implementiert, dass für jeden Betriebsmodus entweder die notwendigen Untermenüpunkte oder die entsprechenden Programmfunktionen als Aufruf eines Unterprogramms umgesetzt werden. Diese Schicht verwendet ebenfalls die Mechanismen, wie sie in Schicht 1 beschrieben sind und setzen auf die Basisroutinen der darunterliegenden Schicht auf. Die Trennung in Applikationsschicht und Basissoftware wurde vorwiegend auf Grund der in Absch. 7.5 vorgegebenen Code-Organisation eingeführt. Für jeden Hauptmenüpunkt (Modus) existiert genau eine Sourcedatei, die die einzelnen Funktionen umsetzt.
  3. An Basisfunktionen stehen Funktionen zur Ein- und Ausgabe von Menü-Interaktionen, LCD-Texten, das Lesen und Schreiben von gespeicherten Werten, die Anzeige von Stati sowie spezielle Ausgabeobjekte wie ,,Speedcursor'' oder ,,Menüselection'' (siehe dazu auch 7.6.2) zur Verfügung. Diese Schicht zeichnet sich dadurch aus, dass die zugeordneten Routinen nicht direkt auf die Hardware zugreifen, sondern Routinen ansprechen, die quasi als ,,High-Level'' Routinen zur Verfügung gestellt werden. In dieser Ebene sind auch die Software-Timer angesiedelt, die nur mittels Schleifen Zeitverzögerungen bewirken oder die Pseudo-Scheduler Schnittstelle (siehe 7.7.3.3), die Interrupt gesteuerte Ereignisse (wie z.B. die Aktualisierung der Anzeige in Schleifen) verwaltet.
  4. Die High-Level Hardwareebene greift auf die Ressourcen der halvedDISC zu, verwendet jedoch die darunter liegende Low-Level Abstraktionsschicht, die dann endgültig die Ports ansprechen, Timings berücksichtigen, etc. In dieser Schicht sind Routinen zur Ausgabe typspezifischer Werte (Zahlen im Dezimal-, BCD-, Binär- oder Hexadezimalformat, Winkelanzeige, Hex-Byte, Hex-Word Ausgaben, ASCII-Text) oder die Tastaturbearbeitung angesiedelt. Diese benötigen dazu die Low-Level Routinen, wie z.B. Byte weises Lesen und Schreiben von $I^{2}C$-Komponenten oder Port-I/O Funktionen.
  5. Die Low-Level Schicht stellt die direkte Verbindung zur Hardware her. Routinen zur Ansteuerung von $I^{2}C$-Komponenten, wie dem PCF8591, Einlesen oder Schreiben eines Temperatur-, Zeit- oder Datumswertes werden in dieser Ebene umgesetzt. Diese Softwareebene ist bis zur Adressierung des $I^{2}C$-Busses Hardware spezifisch, und muss in fast jedem Fall bei einer Änderung von Hardwarekomponenten mitgeändert werden. Da die Low-Level Routinen in jedem Mikrocontroller-Projekt vorhanden sein müssen, wurde in diesem Bereich großteils auf bestehenden Code (z.B. die IIC-Lib oder LCD-Lib von Heiko Polster, ACMC oder die Timing-Routinen Harald Knapp, www.comlogic.at) zurückgegriffen.

gerhard.reithofer@tech-edv.co.at