Grundstruktur einer AVR C++ Anwendung mit der UML

Die Grundstruktur einer objektorientierten Anwendung erfordert eine Applikationsklasse oder auch Hauptklasse, welche als erstes gestartet wird. Das ist vergleichbar mit der Hauptfunktion in strukturierten Programmiersprachen. Bei Mikrocontrolleranwendungen repräsentiert die Instanz dieser Hauptklasse letztlich die Firmware des Controllers. Vergegenwärtigen wir uns diesen Sachverhalt nochmals als UML Klassenmodell.

Wir möchten unsere Firmware mit dem PEC-Framework realisieren. Dazu weisen wir der Applikationsklasse Controller alle Merkmale einer Pec-Applikation zu. Dieser Sachverhalt wird in der UML wie folgt abgebildet:

Die Signatur der Operationen hat sich jetzt gegenüber dem einfachen Modell verändert. Hier sehen wir die Operatonsnamen onStart und onWork. Diese sind, wie der Instanzname der Appliklation app im Gegensatz einer Applikation ohne Framework nicht mehr frei wählbar. Das Grundgerüst einer PEC-Applikation „hängt“ sich in das Ereignissystem des Framework hinein. Das Framework ist jetzt verantwortlich für die Verteilung der Rechenzeit und fordert alle aktiven Komponenten über Nachricht auf etwas zu tun. Wir erkennen Nachrichtenbehandlungsfunktionen (event handler) an dem Präfix on. Die festgelegten, nicht mehr frei wählbaren Namen und Attribute dieser Operatioenen (Signaturen) nennt der Fachmann auch Schnittstelle (Interface). Solch eine Schnittstellendefinition stellt sicher, dass die selbst entwickelten Komponenten und das Framework sich Verständigen können. Aus diesem Klassenmodell erzeugt der SiSy-Codegenerator C++ Code der stark vereinfacht wie folgt aufgebaut ist.

// Deklaration der Hauptklasse
class Controller : public PecAppKernel {
   // innere Struktur
   // Attribute und Methoden
   public: void onStart();
   public: void onWork();
} app;  // Anwendungsinstanz

Das Schlüsselwort class ist nötig, um dem Kompiler anzuweisen, eine Klasse zu erstellen. Der Name der Klasse wird vom Programmierer festgelegt. In unserem Fall heißt die Hauptklasse Controller. Das ist die Applikationsklasse. Wenn man cool sein will erzählt man übrigens abends beim Bier, dass man gerade eine Äpp baut. Klassennamen sollten immer mit einem Großbuchstaben beginnen. Daran erkennt der Programmierer später beim Schreiben oder Lesen des Programmcodes jeweils, ob ein Typ oder eine Instanz gemeint ist. Umlaute, Sonderzeichen, Leerzeichen und Zahlen am Wortanfang sind in Klassennamen nicht zulässig. Von der Hauptklasse muss es auch noch eine Instanz geben. Diese wird durch das Objekt mit dem Namen app repräsentiert. Dieser Name kann in unserem Fall nicht frei gewählt werden. Wir verwenden ein vorgefertigtes Framework (Klassenbibliothek), welches zwingend eine Hauptinstanz mit dem Namen app erwartet. Der Controller hat eine „ist ein“-Beziehung zu dem Template PecAppKernel. Folgen wir dem Template und schauen uns an was die Klasse Controller durch die Festlegung „ist ein PecAppKernel“ bereits kann. Dazu eine kurze Übersicht.

Nicht gruseln! Das ist nur ein etwas vereinfachter Ausschnitt aus dem entsprechenden UML Klassenmodell des Portable Embedded Class Framework (PEC). Was wir dort sehen ist, das die Klasse Controller offensichtlich alle Eigenschaften des PecAppKernel realisiert. Das Klassetemplate PecAppKernel stellt wesentliche Basisfunktionalitäten zur Verfügung. Diese finden sich als Operationen, wie zum Beispiel onStart, onWork oder onTimer10ms, in der Klasse Controller wieder. Wir erkennen Funktionen für das Hochfahren und den Betrieb des Controllers. An diese Funktionen werden wir uns sehr bald „ranhängen“, indem wir selber gleichnamige Operationen schreiben. Der Fachmann bezeichnet das als überschreiben der Operationen. Interessant ist auch die Schnittstellenklasse AppModul. Der Controller kennt eine Liste von PecAppModulen und diese verfügen auch über die gleichen Basisfunktionen. Die PecAppModule können ihrerseits Ereignisse an den Controller melden.

Für das Erste reicht es aus die Funktionalität der Framework-Application wie folgt zu verstehen.

Nach dem Spannung an das System angelegt bzw. ein RESET ausgelöst wurde sendet der AppKernel die Nachricht onStart an unsere Controlleranwendung. In der entsprechenden Nachrichtenbahandlungsfunktion (event handler) der Operation onStart können wir unseren Teil der Initialisierungssequenz programmieren. Danach geben wir die Steuerung an den AppKernel zurück. Die Mainloop läuft im AppKernel. Wir selber haben keine Kontrolle über die Mainloop, werden aber vom AppKernel mit der Nachricht onWork aufgefordert unseren Teil der Verarbeitungslogik die im Polling erfolgen soll abzuarbeiten. In die Operation onWork bauen wir später alles rein was nicht zeitkritisch ist. Wir dürfen das System jedoch nicht durch bestimmte Steuerflusskonstrukte anhalten. Besonders kontraproduktiv wäre es eine eigene Mainloop aufzubauen. Selbst die Anwendung der Wartefunktionen waitMs und waitUs sind eigentlich alles andere als sexy. Wir müssen uns immer vergegenwärtigen das der AppKernel für die Verteilung der Rechenzeit verantwortlich ist (Scheduling) und wir in jeder Klasse und in jeder Nachrichtenbehandlungsfunktion uns nur so viel Rechenzeit greifen wie unbedingt notwendig ist. Timing realisieren wir später auf einem höheren Niveau als das dumpfe Anziehen der Handbremse mit waitMs.

Die erste eigen PEC Application erstellen

Falls Sie SiSy und das Tutorial-Projekt nicht vorleigen haben starten Sie SiSy und legen Sie ein neues Projekt mit dem Namen „Tutorial“ an. Wählen Sie das AVR-Profil. Für alle die noch nicht oder nicht mehr wissen wie ein SiSy-Projekt angelegt wird hier zur Wiederholung ein ScreenCast dazu ;-)

Es sind als nächstes folgende Arbeitsschritte auszuführen:

  1. ein neues Klassendiagramm anlegen und öffnen
  2. die Grundstruktur einer PEC-Application aus dem LibStore laden
  3. das Controllerspezifische Treiberpaket zuweisen
  4. Die Firmware aus dem Klassendiagramm erstellen und auf den Controller übertragen
  5. das Beispiel studieren

Das neue Klassendiagramm legen wir in der obersten Ebene unseres Projektes an indem wir ein Objekt vom Typ Klassemndiagramm per Drag & Drop in das Diagrammfenster ziehen.

Geben Sie dem Klassendiagramm den Namen „Beispiel_GG“. Achten Sie darauf, dass die Zielsprache und die Zielhardware korrekt eingestellt ist. Öffnen Sie das Diagramm indem Sie es selektieren und im Kontextmenü (rechte Maustaste) den Menüpunkt „nach unten (öffnen)“ wählen. Laden Sie aus dem Libstore die Vorlage

Sie erhalten nach dem herunterladen aus dem SiSy LoibStore folgendes Klassenmodell.

Dieses Grundgerüst einer PEC-Applikation ist vollständig portabel. Es enthält keine controllerspezifischen Daten oder Befehle. Sie verwenden dieses Grundgerüst genau so auch auf anderen Zielplattformen wie zum Beispiel dem STM32 oder dem XMC. Als nächstes müssen Sie dem Diagramm die Zielplattfporm zuweisen indem Sie das entsprechende Treiberpaket für den verwendetetn Controller einfügen. Wir benötigen das Treiberpaket für AVR Mikrocontroller der Mega-Familie (MCU_ATmega_xxx). Das Paket finden Sie zum Beispiel über den Navigator mit dem Filter UML-Pakete oder den Explorer mit dem Suchbegriff MCU. Ziehen Sie das Paket per Drag & Drop in das Klassendiagramm.

Jetzt ist das Grundgerüst plattformspezifisch. Es stehen die Low-Level-Driver des Herstellers und spezielle Klassen und Templates aus dem MCU-Paket zur Verfügung.

Obwohl das Programm noch gar nichts tut wollen wir erst einmal sehen, ob die Programmierung des Controllers funktioniert. Dazu lösen wir über das Aktionsmenü (Erstellen, Brennen und Ausführen) nacheinander folgende Aktionen aus:

  • Generieren, aus dem UML-Modell werden die benötigten Quelltextdateien (*.cc) generiert
  • Komilieren, die Quelltextdatei (*.cc) werden in Objekt-Dateien (*.o) übersetzt
  • Linken, die Objekt-Dateien (*.o) werden mit der Bibliothek (*.a) zum lauffähigen Programm (*.elf) verbunden
  • Brennen, Das lauffähige Programm (*.elf) wird über den Programmer oder den Bootloader in den Programmspeicher (FLASH) des Controllers übertragen

Wir können aus dem Klassendiagramm allso den kompletten Quellcode generieren, diesen übersetzen und auf den Controller übertragen. Das erfolgt, wie bereits erwähnt, über das Aktionsmenü in der Objektbibliothek. Wählen sie dort den Menüpunkt Erstellen, Brennen & Ausführen.

Glückwunsch! Sie haben Ihre erste eigene PEC-Application auf den Controller geflasht.

Videozusammenfassung

Und hier diesen Abschnitt als kurze Videozusammenfassung.

Nächstes Thema

  • grundstruktur_mit_uml.txt
  • Zuletzt geändert: 2021/10/14 09:53
  • von huwi