System-Analyse und System-Spezifikation (Requirements Engineering)

Im deutschen Sprachgebrauch wird dieser Bereich häufig mit Anforderungsmanagement bezeichnet, was nicht ganz richtig ist. Im Englischen wird der Begriff Requirements Engineering verwendet, was schon etwas besser passt.  

System-Analyse und -Spezifikation gehen jedoch noch weit darüber hinaus und beinhalten z.B. auch Risiko-Abschätzungen (Risk Management) oder FMEA (Failure Mode and Effects Analysis). In Embedded Systemen sind dies in sicherheitsrelevanten Bereichen vorgeschriebene Tätigkeiten. Ein Embedded System besteht immer aus Software und Hardware. Damit verbunden gibt es neben dem Software Engineering weitere Fachdomänen wie Elektrotechnik oder Maschinenbau.

Klassisch sollten die ersten Schritte eines Projektes darin bestehen, dass die Anforderungen an das System definiert und analysiert werden. Auf Basis dieser System-Analyse wird dann eine System-Spezifikation erstellt. Diese ist dann die Basis und Zielvorgabe für die Entwicklung, Produktion, Inbetriebnahme, Service und Entsorgung - also den gesamten Lifecycle des Systems. Hier sehen wir schon einige Unterschiede im Bereich der Entwicklung von Embedded Systemen gegenüber der klassischen Informatik und in der Anwendungsprogrammierung. 

In den ersten Phasen der System-Analyse sprechen wir auch von Systems-Engineering. Mit Systems-Engineering ist das domänenübergeordnete Engineering gemeint. In späteren Phasen werden die Anforderungen dann den Fachdomänen zugeordnet (auch als Hand Of bezeichnet).  

Somit beschreibt die System-Spezifikation das gesamte System - unabhängig durch welche Domäne die Anforderungen später einmal entwickelt und produziert werden. Das ist ein nicht unerheblicher Unterschied zum Requirements Engineering im Bereich der klassischen Informatik, da auch die Fachsprachen außerhalb des Software-Engineering angesiedelt werden.  

Systemanalyse und Systemspezifikation beinhaltet folgende Bereiche:

  • Anforderungsspezifikation (Req. Capture)
    Anforderungsspezifikation bezeichnet das Finden, Definieren und Dokumentieren von Anforderungen. Hier gibt es verschiedene hilfreiche Vorgehen und Regeln - z.B. über die Definition von Anforderungen (Eindeutig, Vollständig, Verstehbar ...), die Sprache (natürliche Sprache, UML, MSCs ...) und Vorgehen (Req. Capture, Stakeholder Analyse, Brainstorming ...), die die Qualität und effizientes Vorgehen bei der Anforderungsspezifikation sicherstellen.       
  • Anforderungsanalyse (FMEA, Risk Management ...)
    Die in der Anforderungsspezifikation erarbeiteten Anforderungen sollten nun analysiert werden, z.B. auf Konsistenz (sich widersprechende Anforderungen). Eine der häufigsten Widersprechungen entsteht schon, wenn die grundlegenden Qualitätsattribute (Kosten, Wartbarkeit, Erweiterbarkeit, Änderbarkeit ...) nicht hinreichend definiert wurden. So können sich beispielsweise geringes Gewicht und Stabilität widersprechen. Außerdem müssen bei sicherheitsrelevanten Systemen Risiko-Abschätzungen und Risiko-Eingrenzungen durchgeführt werden.
  • System-Spezifikation
    Mit den Ergebnissen der Anforderungsanalyse wird die System-Spezifikation definiert und bildet damit die Vorgabe für die Entwicklung und Produktion. Fehler in der System-Spezifikation werden meist sehr teuer, wenn sie spät erkannt werden.       
  • Anforderungsmanagement
    Je nach Situation sind die entstehenden Tätigkeiten, Rollen und Dokumente unterschiedlich. Häufig werden Systeme nicht mehr von einem Unternehmen allein entwickelt und produziert. Es gibt dann einen so genannten OEM (Original Equipment Manufacturer), der mit seinem Namen das System am Markt positioniert, zum Beispiel ein Automobilhersteller wie VW. Dieser bezieht jedoch heute den größten Teil der Komponenten von Zulieferern. Oft gibt es also ein komplexes Beziehungsgeflecht zwischen Firmen und deren Produkten, die dann zu einem System zusammengefügt werden müssen.

    Dann müssen die Anforderungen des Gesamtsystems auf die Teilkomponenten heruntergebrochen werden. Es entstehen Auftrag-Geber und Auftrag-Nehmer- Beziehungen, in denen die Anforderungen sehr häufig die Grundlage der Verträge bilden (In Deutschland werden die Anforderungen häufig in Form von Lasten- und Pflichtenheften definiert). Bei heutigen Systemen (zum Beispiel einem PKW) entstehen extrem komplexe Geflechte an Beziehungen zwischen den einzelnen Anforderungen. Das Managen dieser Beziehungen wird auch als Anforderungsmanagement bezeichnet.

    Anforderungsmanagement von komplexen Systemen ist ohne Unterstützung von Datenbanken (Repositorys) nicht mehr effizient und fehlerfrei möglich. Aus diesem Grund werden zunehmend Anforderungsmanagement-Werkzeuge (IBM Rational DOORS, Polarion Requirement, IRQA ...) eingesetzt.

    Vor allem über Linkbeziehungen können mit Hilfe der Werkzeuge die Beziehungen zwischen Anforderungen definiert werden. Auf dieser Basis können dann die Traceability-Analysen durchgeführt werden, z.B. um abzusichern, dass bei Änderungen alle Aspekte im System berücksichtig wurden. Auch das Managen von Anforderungen hinsichtlich Versionen oder Varianten fällt in den Bereich Anforderungsmanagement.  


    Abbildung für Anforderungsmanagement

Softwareentwicklung in C für Mikroprozessoren und Mikrocontroller

Jörg Wiegelmann
*
Softwareentwicklung in C für
Mikroprozessoren und Mikrocontroller
*
6. überarbeitete Auflage 2011 - VDE Verlag GmbH
*
319 Seiten, 39,90 Euro
*
ISBN 978-3-8007-3261-6 

Bei einer 6. Auflage des Buches „Softwareentwicklung in C für Mikroprozessoren und Mikrocontroller“ könnte man denken: Ist C denn überhaupt noch zeitgerecht? Objekt-orientierte Programmierung mit C++, Java oder Modellierung mit UML sind doch derzeit in aller Munde. Ich meine, dieses Buch macht trotzdem Sinn. Vielleicht hätte der Name anders gewählt werden können, denn es ist nicht unbedingt ein Buch, um die Hochsprache C zu lernen.

Jörg Wiegelmann startet zwar mit dem Kapitel „Kurze Einführung in die Sprache C“, und mit rund  30 Seiten werden kurz und knapp die wesentlichen Notationselemente abgehandelt. Wer keine C-Kenntnisse hat, sollte sich jedoch noch ein Buch über ANSI-C dazu nehmen, in dem das eine oder andere noch einmal ausführlicher nachzulesen ist. Die Hauptqualitäten des Buches wird man jedoch nicht unbedingt in diesem Kapitel finden, eher in dem dargebotenen Know-how zur allgemeinen Embedded-spezifischen Programmierung und in Hinweisen zur Anwendung von Werkzeugen. Erfreulich ist, dass der Bereich über Pointer und deren Vor- und Nachteile ausführlicher behandelt wird. Spätestens hier merkt man, dass es weniger ein Grundlagenbuch über die Anwendung von C ist, sondern viel mehr die Stolperfallen in der Anwendung von C thematisiert. Ebenso erfreulich ist die ausführliche Behandlung der #INCLUDE Präprozessoranweisungen in Verbindung mit Header-Files; bilden sie doch die Grundlage für einen modularen Aufbau von Programmen, dem am Anfang der Programmierung häufig zu wenig Bedeutung beigemessen wird. Auch hier wieder reichlich praktische Erfahrungen, was schief gehen kann und wie es verhindert wird - für Einsteiger sicher sehr hilfreich. Und so geht es weiter: Im Kapitel über Compiler werden die verschiedenen Speichermodelle erläutert, die Aufgaben des Linkers, Make und immer wieder werden Stolpersteine behandelt, zum Beispiel wie sich die Compiler-Optimierungen auswirken und beim Debuggen für reichlich Verwirrung sorgen können; oder wann Variablen, die nur extern beschrieben werden vom Compiler weg optimiert werden. Nicht selten haben Entwickler Tage mit Effekten zugebracht, die durch Optimierungen des Compiler verursacht werden.

In Kapitel 9 „C-Programmierung für Embedded Systeme“ geht es ins Eingemachte: Hier wird erläutert, wie Mikrocontroller spezifische Hardware-Komponenten mit Hochsprache angesprochen werden können. Es werden die wichtigsten sogenannten NON ANSI-Erweiterungen der Compiler besprochen, die hierfür notwendig sind, zum Beispiel der Umgang mit Bits anstelle von Bytes, oder der Einsatz von Interrupts. Verständlicherweise geht Jörg Wiegelmann hier nicht in die Tiefe, da dieser Bereich sehr CPU- und Compilerspezifisch ist. Aber die Grundlagen werden angesprochen, so dass die Handbücher der Compiler auf dieser Basis sicher gut verstanden werden. Erfreulich: Auch hier wieder praktische Elemente; zum Beispiel werden nicht - wie häufig üblich - nur die Programmierung von Interrupt-Service-Routinen angesprochen, sondern auch die Kommunikation derselbigen zur Systemebene unter anderem mit der Problematik bei preemptivem Verhalten. Und wieder werden nicht nur die Probleme aufgezeigt, sondern auch probate Mittel, dem zu begegnen, etwa durch die Verwendung von Semaphoren. Leider wird nicht auf asynchrone Kommunikation als eine der elegantesten Möglichkeit eingegangen.

Weiter geht es mit Kapitel 9.7 „Betriebssystem“. Hier werden die Basis-Scheduling-Pattern beschrieben, angefangen bei der einfachen main() Loop bis hin zu preemptivem Multitasking und den damit verbundenen Pattern zur Kommunikation, für den Einstieg sicher gut zu wissen. Alles wird angesprochen, Speicherverwaltung, Anwendung von Interrupt-Routinen in Kombination mit dem Betriebssystem, Hardware Treiber ...

Ein kleiner Wermutstropfen auch an dieser Stelle: Ich vermisse Hinweise auf die sinnvolle Kombination von Scheduling- und Kommunikations-Pattern, beziehungsweise die Problematiken, die bei ungünstigen Kombinationen entstehen, zum Beispiel bei preemptivem Scheduling und synchroner Kommunikation auf Basis von Signalen, was heute sehr häufig anzutreffen ist. Auch interessant für den Einsteiger, das Kapitel 9.11 „Steuerungssoftware“: Hier beschreibt Jörg Wiegelmann eine simple Laufzeit-Architektur auf Basis eines Dispatchers in Verbindung mit Zustandsautomaten. Mit dieser Architektur lassen sich Embedded Systems sehr strukturiert programmieren, wenn sich die Komplexität in Grenzen hält.

Es geht weiter mit dem Kapitel 10 „Quellcode“, in dem auf Struktur, Übersicht und Qualität von Code eingegangen wird. Immer wieder wird der Einsteiger den einen oder anderen Tipp finden, der ihm das Leben erleichtert. Bevor der praktische Teil anfängt, gibt es noch das Kapitel 11 „Tools und Entwicklungsumgebung“. Hier werden außer den Basis-Werkzeugen zum Beispiel auch statische Analyser (Lint) und Sourcecodeverwaltung (RCS, CVS) angesprochen, also auch erste Schritte zur Absicherung von Qualität in Bezug auf Sourcecode an sich und Sourcecode-Management. Ich hoffe, die Leser schenken diesen Kapiteln die notwendige Achtung.

Nur das Kapitel 12.5 „CASE-Tools“ kann nicht recht überzeugen. Hier kritisiert Jörg Wiegelmann den Einsatz von CASE-Tools, weil es „... ist sehr aufwändig, eine wirkliche komplexe Software vollständig in einem CASE-Tool zu entwickeln. Die einzelnen Softwareteile müssen mit ihren Schnittstellen genau spezifiziert werden. ...“ Das ist aber nicht die Problematik, die entsteht, wenn ein CASE-Tool eingesetzt wird. Das ergibt sich grundsätzlich, egal auf Basis welcher Notationen, Methoden oder Werkzeugen programmiert wird. Im Gegenteil, ein gutes CASE-Tool macht die Definition von Schnittstellen vergleichsweise einfach, zum Beispiel in Form einer „Usage“-Beziehung zwischen zwei Modulen. Die im ersten Teil des Buches aufgeführten Probleme mit Include- und Header-Dateien werden vom CASE-Tool erledigt. Der praktische Nutzen von CASE-Tools ist es gerade, die bei steigender Komplexität anwachsenden Beziehungen zu entflechten und deren Umgang gegenüber der Programmierung in einer Hochsprache zu vereinfachen. Weitere angesprochene mögliche Nachteile von CASE-Tools sind bei guten Werkzeugen nicht relevant. Diese Einstellung scheint Jörg Wiegelmann nicht zu teilen - schade.

Im Kapitel 13 „Fallstudie“ geht es dann um die reale Durchführung eines Beispielprojektes auf Basis des „AVR ATmega88“. Auf einer dem Buch beiliegenden CD-ROM sind Werkzeuge und Quellcode enthalten, um dieses Beispiel selber nachzuvollziehen. Dieser Teil des Buches wurde aus Zeitgründen nicht rezensiert, obwohl er sicher für den Einsteiger noch einmal einen sehr wichtigen und hilfreichen, wenn nicht sogar den wichtigsten Teil darstellt. Streng nach dem Motto: Der Unterschied zwischen Theorie und Praxis ist in der Praxis größer als in der Theorie. Abschließend beurteile ich das Buch für Einsteiger in die Programmierung von Embedded-Applikationen als sehr hilfreich. Abgesehen von ganz wenigen Aussagen ist das Buch reich an praxisrelevanten und kompetenten Tipps und Hinweisen, die einem Einsteiger das Leben erleichtern können.

Manche Stellen musste ich zwei mal lesen um zu begreifen, was Jörg Wiegelmann meint. So könnte man kritisieren, dass das eine oder andere eleganter hätte formuliert werden können. Letztendlich ist der Inhalt kompetent und praxisnah, und das ist der Hauptgrund, warum ich das Buch grundsätzlich jedem Entwickler empfehlen kann, der in die Programmierung von Embedded Systems einsteigen möchte und dort auch mit hardwarenaher Programmierung konfrontiert wird, egal, ob er das in der Notation C, C++ oder auf Modellierungsebene, etwa mit UML tun möchte. Viele in dem Buch beschriebene grundlegende Dinge sind hilfreich zu wissen und beugen langem Suchen nach unerklärlichen Effekten vor. Auch erfahrenen Programmierern, die in das Embedded-SW-Engineering einsteigen möchten. kann das Buch empfohlen werden. Nicht zu empfehlen ist es für Entwickler, die den Einstieg in die Welt der Embedded Systems auf Basis von Betriebssystemen wie Linux, VxWorks oder Windows in Verbindung mit sogenannten BSP‘s (Board Support Packages) machen möchten.

Andreas Willert - www.willert.de

Ansehen

Bereitgestellt von:

zurück


Newsletter abonnieren



Empfehlung an diese E-Mail-Adresse senden:


 

 

 

Ihre eigenen Angaben:

 

 

 

 

Diese Seite empfehlen Sie weiter: