Modellierung Objektorientierung und modellbasierte Werkzeuge
Über Tools wie Rhapsody kann aus der Modellierung direkt Code generiert werden. – auch für Embedded-Systeme. Dazu sind einige Vorarbeiten nötig, das Abstraktionsniveau steigt für alle Beteiligten. Verbunden mit der Chance, bis zum Produkt eine klar erkennbare Architektur umzusetzen und damit ein gut wartbares Produkt zu erhalten.
Anbieter zum Thema

Die Dr. Fritz Faulhaber GmbH & Co KG entwickelt, fertigt und verkauft Klein- und Micromotoren, die dazu passenden Positionsgeber und Ansteuerungen zum geregelten Betrieb der Motoren. Die Ansteuerungen sind in Ausführungen als reine Drehzahlregler oder auch als Positioniersteuerungen im Programm. Realisiert sind diese als eingebettete Steuerungen auf der Basis von µControllern, in denen alle Stufen der Regelung rein digital abgebildet werden. Betrachtet werden sollen hier die Positioniersysteme.
Die Software einer Motoransteuerung für einen Servoantrieb kann grob in die Teile
- Hardwaretreiber,
- Motorregelung,
- Steuerung und Diagnose,
- Kommunikation und
- Parameterspeicher (Objekt-Verzeichnis oder Management Information Base (MIB))
gegliedert werden.
Erweiterungen und Anpassungen an veränderte Anforderungen, aber auch Beschränkungen des Zielsystems erforderten in den Bestandssystemen den klaren Entwurf zu verlassen. Dies führt zu der klassischen Situation bei eingebetteten Steuergeräten mit deutlich ineinander übergehenden Softwareanteilen.
Trotz dieser Beschränkungen stellt der Motion Controller ein sehr stabiles Gerät dar, Erweiterungen erfordern jedoch einen höheren Aufwand und Entwicklungszeitraum.
Insofern war für eine nächste Ansteuerungs-Generation klar, dass insbesondere die Wartbarkeit und Erweiterbarkeit durch eine klare und modulare Software-Architektur deutlich verbessert werden sollte.
Funktionale Anforderungen waren:
- ein deutlich gesteigerter Umfang an unterstützten Betriebsarten,
- die Unterstützung mindestens eines Ethernet-basierten Feldbus als Option,
- eine wesentlich gesteigerte Flexibilität in der Konfiguration.
Die Anforderungen waren mit der Erwartung verbunden, künftig wieder deutlich schneller auf Kundenwünsche eingehen zu können.
Gleichzeitig sollte der Wechsel auf eine aktuelle und zukunftsträchtige Prozessorfamilie erfolgen, die Software aber so entwickelt werden, dass auch künftige Prozessorwechsel deutlich vereinfacht werden.
Grundentscheidungen
Aufgrund der sehr verwobenen Struktur nach Bild 1 war relativ schnell klar, dass aus dem bestehenden Produkt eigentlich nur die Erfahrungen im Betrieb von elektrischen Kleinantrieben übernommen werden konnten. Alle Teile der Software mussten neu entworfen werden.
Eine Aufgabe war daher die Suche nach einer Prozessorplattform für die speziellen Anforderungen von integrierbaren Kleinantrieben. Die Andere die Suche nach einer geeigneten Entwurfs-Methodik, verbunden mit der Suche nach geeigneten Werkzeugen, die es erlauben würden, die Grundentscheidungen aus dem Entwurf auch in der Implementierung abzusichern.
Abweichend vom bisherigen Vorgehen sollte ein objektorientierter Ansatz verfolgt werden, auch um den Entwurf über die Mechanismen der UML zu strukturieren.
Bereits bisher kamen für die Entwicklung der signalverarbeitenden Softwareteile in der Regelung und Positionsauswertung TargetLink für die Code-Erzeugung aus SIMULINK Modellen zum Einsatz. Dieser Ansatz eignet sich aber nicht, um die eher eventbasierten Softwareteile aus der Treiber-Schicht, dem Parameterhandling, der Kommunikation und auch der Antriebssteuerung zu beschreiben und dann auch zu Implementieren.
Nach einer ersten Evaluation und auf der Basis der Erfahrungen aus früheren Projekten [1] fiel die Entscheidung auf Rhapsody bzw. für die Embedded Version wie sie von der Fa. Willert angeboten wird. Hauptargumente waren:
- Arbeitet nativ im OO Entwurf
- Unterstützung von typischen Embedded Plattformen auch in C bei guter Lesbarkeit
- Ausreichende Durchgängigkeit vom Entwurf bis in die Implementierung
- Guter Einstieg möglich, da wenig Legacy Anteile zu übernehmen
Es war aber von Beginn an klar, dass damit auch eine erhebliche Lernkurve sowohl hinsichtlich der Bediensicherheit des Werkzeugs, als auch in der Entwurfsmethodik anstehen würde. Klar war daher auch, dass wir uns einen erfahrenen Partner für die anstehenden Kernthemen suchen mussten, den wir in der Fa Tieto bzw. Tieto Embedded Systems – heute b1 Engineering Solution fanden.
Architektur & Design
Basierend auf der erarbeiten Spezifikation, den Use-Cases des Systems, und den Erkenntnissen aus dem Bestandssystem entstand zunächst eine Grobarchitektur:
- Aufteilung der Gesamtfunktion in Pakete und z.T. auch schon in Objekte
- Definition der treibenden Aktivitäten des Systems
- Klärung der Datenverwaltung bzgl. des Umgangs mit den Parametern und deren Speicherung
Umsetzung
Angewandte Muster waren die Schichtbildung (Layering) mit insbesondere einer eindeutigen Zuordnung von Verantwortlichkeiten für die Kapselung der µController typischen Peripherieeinheiten im HAL und einer darauf aufsetzenden Middleware Schicht. Die Middleware Schicht stellt deutlich abstrahierte Informationen wie die Motorgeschwindigkeit als Ergebnis unterschiedlichster Sensorsysteme zur Verfügung, oder errechnet Stellgrößen aus allgemeinen Vorgaben, wie z.B. die passende Ansteuerung für den angeschlossenen Motor aus der Sollspannung des Reglers.
Um eine Signalflussrichtung entgegen den definierten Abhängigkeitsbeziehungen zu realisieren, wurde das Publish/Subscribe-Pattern bzw. Beobachter-Muster verwendet. Dazu registrieren Informations-Konsumenten aus höheren Schichten Callback-Funktionen und Instanz-Zeiger bei den Informations-Produzenten in den niedrigeren Schichten. Dieses Pattern wird gleichermaßen für den Übergang zwischen Interrupt-Kontext und Task-Kontext, als auch zwischen Task-Kontexten verwendet. Um die Nebenläufigkeiten zu beherrschen, wird in den Callback-Funktionen daher im Allgemeinen ein Event der Laufzeitumgebung an die adressierte Objekt-Instanz versendet. Es ist vielfach ausreichend, genau einen Subscriber bereits während der Initialisierung zu registrieren.
Die Aktivitäten des Systems können aufgeteilt werden in die streng zeitlich getriebenen Aktivitäten einerseits:
- Der Timerinterrupt für die Motorregelung (100µs, synchron zu PWM)
- Ein Timerinterrupt mit 1ms Zykluszeit für Diagnoseaufgaben
Beide werden über einen Interrupt angestoßen und auch im Interrupts Kontext ausgeführt. Entworfen werden diese signalverarbeitenden Systemteile in SIMULINK und über TargetLink in C-Code mit einer zum Systementwurf passenden Schnittstellengestaltung überführt.
Auf der anderen Seite stehen die eher reaktiven Aktivitäten:
- Externe Ereignisse wie z.B. der Empfang einer kompletten Botschaft aus den Kommunikations-Stacks (die Verarbeitung der einzelnen Zeichen z.B. der RS232 Schnittstelle werden komplett im Schnittstelleninterrupt-Kontext ausgeführt).
- Time-outs über einen niedriger priorisierten Timer
In beiden Fällen wird der Interrupt-Kontext verlassen und ein Event ausgelöst, der typisch über eine Zustandsmaschine bearbeitet wird. Die Modellierung der Interaktion kann hier vorteilhaft über Kommunikationsdiagramme, die Systemreaktion über Zustandsmaschinen entworfen werden.
Anteile der Laufzeitumgebung
Innerhalb des Willert Framework werden Zustandsmaschinen und die nötige Eventbehandlung direkt nativ angeboten, d.h. aus Zustandsdiagrammen und den dazu gehörenden Events kann direkt lauffähiger Code erzeugt werden. Da die Reaktion auf jeden Event am Stück abgearbeitet wird (run to completion), können Zustandsmaschinen auch verwendet werden, um quasi gleichzeitige Ereignisse zu serialisieren, indem die Ereignisse in einer Event-Queue einer Zustandsmaschine eingestellt werden – so z.B. für die Bearbeitung von über die serielle Schnittstelle erhaltener Anfragen in Konkurrenz zu intern erzeugten asynchronen Botschaften.
Umsetzung in Rhapsody
Das Gesamtsystem wurde in eine Reihe von parallelen Rhapsody Projekten zerlegt, die je für eine Komponente die Arbeitsumgebung aus Implementierung und Testpaket beinhalteten. Damit können die Komponenten weitgehend getrennt bearbeitet werden – wichtig für die Arbeit im Team.
Die Komponenten wurden dann entsprechend den Abhängigkeiten und Schichten von Beginn an zu Integrationen zusammen gefügt (Top Down) deren Funktionsumfang dann schrittweise wachsen konnte.
Die Basis bildet ein Projekt, in dem lediglich Typ- und Stereotype-Definitionen beheimatet sind die sich aus der Programmierrichtlinie ergeben. Darauf setzten die Fachpakte auf, die je aus der zu entwickelnden Komponente und optional einem Test-Package bestehen. Über das Test-Package können aus dem Fachpaket ausführbare Testkomponenten erzeugt werden, die je nur den Umfang der betrachteten Fachkomponente nutzen. Auf oberster Ebene werden die Komponenten im Integrationsprojekt referenziert.
Integration von C-Code
Für die Integration und die zu erstellenden Binärfiles stellen die Rhapsody Projekte die Build-Umgebung dar. Der gesamte Code wird über die Projekte in ein Projekt der C-Entwicklungsumgebung (hier Keil µVision) verschoben und dort nur gebildet und debuggt. Die exportierten C-Files unterliegen damit nicht dem Konfigurationsmanagement.
Trotzdem müssen auch in C vorliegende Code-Teile wie z.B. gekaufte Kommunikations-Stacks oder die über TargetLink erzeugten Code-Anteile integriert werden. Aufgaben sind dabei, die vorhandenen Codes jeweils aktuell ins C-Projekt zu kopieren, sowie ggf. die Gestaltung von Schnittstellen, um die externen Code-Anteile im Projekt nutzen zu können.
Der erste Teil der Aufgabe gelingt über make-File Erweiterungen die innerhalb der in Rhapsody erstellten Komponenten angelegt werden können und die Kopieranweisungen aufnehmen.
Für die Integration ins Modell wurden typisch Wrapper Klassen angelegt. So kann z.B. mit TargetLink sehr gut ein Regler erstellt werden. Auch können die Parameter und Variablen in je einer klassenartigen Struktur gesammelt und auch an der Funktionsschnittstelle der eigentlichen Rechenroutine verwendet werden. Das so erzeugte C-Modul kann dann als externer Code im Projekt eingebunden werden. Für den Zugriff auf die einzelnen Parameter der Regler-Struktur werden in TargetLink aber keine zur Integration geeigneten Zugriffsmethoden bereitgestellt. Bliebe der Direktzugriff auf die Member der Struktur, oder eben ein Wrapper, der dafür die Read- und Write-Handler bereitstellt und das Wissen über die C-Struktur kapselt.
Vorteile
Das Projekt ist noch nicht abgeschlossen, eine vorläufige Bewertung lässt als Vorteile erkennen:
- Durch die Strukturierung des Systems über die Mechanismen der OO bleibt der Grundentwurf der Architektur ständig im Blick. Abhängigkeiten werden bewusst gezogen, das Schichtenmodell konsequent eingehalten.
- Bei sauberer Trennung zwischen den Zeit-getriebenen und den Event-getriebenen Aufgaben des Systems können die Mechanismen der in der Laufzeitumgebung hinterlegten Event-Queues voll zur Geltung kommen. Trotz einer Reihe von Nebenläufigkeiten sind die Entwickler nicht mehr mit den zur Synchronisation nötigen Mechanismen wie Semaphoren und Interrupt-Sperren befasst.
- Die Lesbarkeit des erzeugten Codes ist grundsätzlich hoch, es bleibt aber die Aufgabe der Entwickler bzw. des Projektleiters darauf zu achten, dass die Komplexität der Methoden und Klassen beherrschbar bleibt. Das Werkzeug leistet dabei keine Unterstützung.
Herausforderungen und Mühen
Insbesondere aus Sicht des Entwicklers bieten sich in der täglichen Anwendung von Rhapsody einige Hürden, mit denen man zu leben lernen muss. Im Folgenden seine einige Beispiele genannt. Vieles könnte unserer Meinung nach leicht abgestellt werden, wenn der Wille zur Pflege des Produkts noch ausgeprägt wäre.
Der RPY Code- und Modell-Editor
- Das Kopieren/Einfügen/Modifizieren (ein häufig angewandtes Entwicklungsmuster) von Modellelementen geht zwar häufig, aber nicht immer. Probleme treten insbesondere bei den Elementen unterhalb des Standard-Packages „Components“ auf oder aber auch beim Kopieren zwischen verschiedenen Projekten.
- Ein Kopieren aus ReadOnly-Fenstern (z.B. in eine Mail) ist nicht möglich. Auch kann man in ReadOnly-Fenstern nicht scrollen.
- Windows Key-Belegung (Ctrl-Entf, Ctrl-Einfg) funktioniert nicht, nur Ctrl-C und Ctrl-V.
- Autovervollständigung im Code-Editor funktioniert nur unvollständig (nur einmal pro Zeile, nur lokale Elemente, keine Literale, …)
- Generierter Code der einem Package zuzuordnen ist, kann nicht automatisch mit einem Prefix versehen werden.
- Refactoring ist mühsam, da der händisch hinterlegte Code vom Tool nicht mit einbezogen wird.
Properties
Welche Properties bei der Code-Generierung wie, wann wirken ist sehr undurchsichtig. Hier hilft oft nur Probieren.
Beispielsweise ist das Property C_CG::Type::ReturnType nicht wirksam, wenn man sich über das Property C_CG::Attribute::AccessorGenerate automatisch einen Accessor generieren lassen will.
Im genannten Fall sollte anstelle einer Kopie einer Struktur (default), ein Const-Zeiger auf die Struktur zurückgegeben werden.
Versionierung
Die Files in denen Rhapsody seine Informationen hinterlegt, sind leider nicht sehr „Merge“-freundlich gestaltet. Insbesondere werden in Files häufig Zeitstempel und GUIDs geändert, obwohl sie ansonsten keinerlei Änderungen erfahren haben. Um ein gemeinsames Arbeiten zu ermöglichen, haben wir daher häufig vor dem Commit mit den Mitteln des Konfiguration-Managements-Tools manuell kontrolliert, welche Files wirkliche inhaltlich geändert wurden.
Bei tatsächlichen Konflikten war mitunter auch Handarbeit mit dem Merge-Tool notwendig, sofern sich diese Konflikte nicht im Vorfeld durch Absprachen umgehen ließen.
OO in C
Wir arbeiten gerne und häufig mit konstanten, privaten Daten-Tabellen, die dann durch den Code ausgewertet werden. Leider können Statische-Member bei Klassen nicht angelegt werden (wie es in C++ möglich ist). Anwendungsbeispiele wären:
- Tabellen gestützter CRC-Algorithmus
- HW-Konfigurationen
- Tabellen von Callback-Funktionen
Umgehungsmöglichkeiten ergeben sich teilweise durch die Definition von Types, aber z.B. nicht für die Callback-Funktionen, da die Funktionsprototypen im generierten Code erst nach den Types angeordnet werden.
Voraussetzungen
Die Erfahrung zeigt, dass für ein effizientes Arbeiten mit Rhapsody frühzeitig die richtigen Voraussetzungen zu schaffen sind. Aus unserer Sicht sind folgende Punkte besonders wichtig:
- Für die projektspezifischen Einstellungen sollte von Beginn an ein Profil angelegt und durchgängig referenziert werden (Bild 5). Da es am Anfang aufgrund fehlender Erfahrung meist noch unklar ist, welche Property-Einstellungen wie zu setzen ist, lassen sich auf diese Art und Weise ansonsten weitreichende nachträgliche Änderungen relativ einfach einbringen.
- Bestimmte Property-Einstellungen sollten an Stereotypes gebunden werden. Sie sind dann deutlich im Modell erkennbar und können einheitlich gehandhabt werden. Beispiele: SimpleType (für enums, die im Allgemeinen per Value übergeben werden sollen), Volatile (setzt das Property C_CG::Attribute::PreDeclarationModifier zu “volatile” und sollte für volatile Attribute verwendet werden), PackedT (setzt des Property C_CG::Type::PreDeclarationModifier zu “__packed” und sollte für gepackte Strukturen verwendet werden)
- Packages sollten großzügig verwendet werden um die Zusammenarbeit mehrerer Entwickler zu erleichtern. Diese Packages können dann in den jeweiligen Entwickler-Projekten referenziert werden. Packages werden standardmäßig als eigene Unit in einem separaten File gespeichert.
- Es ist vorteilhaft ein „Helper“-Package mit allgemeingültigen Typen und Algorithmen (z.B. CRC) ganz unten im Layering zu definieren, das für alle darüber liegenden Layern wiederverwendbar ist. Das hatten wir – abgesehen von den üblichen Integer-Daten-Typen – nicht gemacht. Dies später nachzuholen, ist nur noch mit viel Aufwand realisierbar.
Unabhängig von der konkreten Entwicklungsmethodik ist ein gutes Grundverständnis der Domänen-spezifischen Probleme immer ein wesentlicher Erfolgsfaktor. In diesem Falle ist es z.B. das Verständnis der treibenden Aktivitäten und die Zuordnung in den zeitgetriebenen Interrupt-Kontext oder den ereignisgetriebenen Task-Kontext.
Durch den abstrakteren, modellhaften Ansatz muss von den beteiligten Entwicklern noch mehr entsprechendes Wissen abverlangt werden. Man darf sich bei der Methodik nicht gleich in die Bits und Bytes flüchten, und im Nachhinein schauen wie man alles zusammenfügt.
Der Vorteil von entsprechenden Modellierungs- und Codier-Richtlinien muss sicherlich nicht extra hervorgehoben werden.
Ergebnisse
Die bisherigen Ergebnisse müssen differenziert betrachtet werden. Aus Sicht des Architekten erlaubt die Modellbasierte Arbeit einen zügigen Übergang von der Architektur bis in die Implementierung. Insbesondere bleiben durch die expliziten Notationen die Grundentscheidungen der Architektur stets im Blick.
Für die Entwickler stellt der Wechsel auf OO und Rhapsody eine erhebliche Umstellung ihrer Arbeitsweise dar. Statt in C-Files und sehr ausgefeilten C-Editoren entsteht der Code im Editor von Rhapsody. Änderungen in den C-Files während des Tests müssen sorgfältig zurück gepflegt werden. Nicht unterschätzt werden darf auch der Paradigmenwechsel von einer Main-Loop auf eine Event-basierte Systemarchitektur.
Aus Sicht des Projektverantwortlichem bestand die größte Herausforderung in der Suche nach geeigneten Partnern. Der Umstieg auf einen OO-Entwurf gelingt nicht aus dem Stand. Rhapsody stellt ein sehr mächtiges Werkzeug dar, mit eher überschaubarer Dokumentation. Trotz eines vorgelagerten Evaluationsprojekts und begleitender Schulungen wäre das Projekt diesen Umfangs und Neuigkeitsgrades ohne die erfahrenen Partner nicht in der ohnehin knappen Vorgabezeit zu bewältigen gewesen.
Kritisch anzumerken bleibt, dass ein erheblicher Teil der Zeit – typisch für Embedded-Systeme – in die Entwicklung von Middleware-Schichten geflossen ist. Diese weisen dadurch zwar ebenso wie die Applikation eine klare Struktur auf, dienen aber nicht zur Produktdifferenzierung. Hilfreich wären hier künftig ggf. stärker standardisierte Middlewarepakete, die aber sicher Branchen- bzw. Anwendungstypisch ausgeführt sein müssten.
:quality(80)/images.vogel.de/vogelonline/bdb/1266600/1266600/original.jpg)
Codegenerierung – was man damit (nicht) machen kann
:quality(80)/images.vogel.de/vogelonline/bdb/1265300/1265342/original.jpg)
Techniken und Tools
Modellbasiert entwickeln im Internet of Things
:quality(80)/images.vogel.de/vogelonline/bdb/1244800/1244826/original.jpg)
Modellgetriebene Entwicklung
Versionierung: Die Herausforderung bei der Modellierung
Literatur- und Quellenverzeichnis
[1] A. Wagener, Ch. Körner, P. Seger, H. Kabza, Anpassung eines Embedded Target für verteilte Steuer- und Regelungsaufgaben an den RTW von Matlab/Simulink, Embedded Intelligence 2001, Nürnberg
[2] U. Lefarth, T. Beck, Qualitäts- und Effizienzsteigerung bei der Entwicklung von Steuergeräte-Software, 3. Stuttgarter Symposium Kraftfahrwesen und Verbrennungsmotoren, 1999, Stuttgart.
[3] Dr. Gary Morgang, AUTOSAR – ein Projekt zur Entwicklung von Steuergeräte-Software, Elektronik automotive 1/2006
* Dr. Andreas Wagener leitet die Entwicklung von Motoransteuerungen bei der Dr. Fritz Faulhaber GmbH in Schönaich.
* Robert Stemplinger arbeitet als Software Entwickler bei der b1 Engineering Solutions GmbH in München.
* Markus Pauls ist als Software Architekt bei der b1 Engineering Solutions GmbH in München tätig.
(ID:44055654)