Zeitdruck versus Anforderungen = Risiko

Embedded-Entwicklung: Wenn sich Anforderungen ändern

7. Dezember 2010, 10:49 Uhr | Jon D. Pearson

Bei den meisten kommerziellen Projekten ist die Zeit ein wichtiger Faktor, sei es, um saisonalen Absatzzyklen oder Messeterminen Rechnung zu tragen, um einem Konkurrenten um eine Nasenlänge voraus zu sein oder schlicht um den gesetzten Zeitplan nicht zu sprengen. Der Zeitdruck geht zu Lasten der Anforderungen, die deshalb im Lauf des Projekts modifiziert oder weiterentwickelt werden.

Diesen Artikel anhören

Fordert man Entwickler von Embedded-Systemen auf, in knapper Form den Ablauf eines Projekts zu skizzieren, erhält man meist eine Aussage wie: »Man nennt uns die Anforderungen, wir de-signen das System, schreiben den Code und verifizieren das Ganze dann.« Möglicherweise nimmt die befragte Person noch am selben Tag an der Planung des nächsten Projekts teil. Sobald bekannt ist, um was es bei dem Projekt geht, wird zumindest im Kopf mit dem Schreiben des Programms begonnen, was gleichzeitig die Architektur festlegt.

Vielleicht nur einen Tag oder eine Woche später kann man nicht selten miterleben, wie sich derselbe Programmierer in einem ähnlichen Meeting darüber beklagt, die Anforderungen für das Design reichten nicht aus und man könne erst weitermachen, wenn sich die Vorgaben nicht mehr veränderten. Marketingabteilungen neigen dazu, Projekte vor Festlegung der Anforderungen beginnen zu wollen.

Sie bringen ihre Kenntnisse darüber ein, was möglich ist, was der Kunde wünscht (dies lässt sich allerdings bestenfalls vage vorhersagen) und welche Wettbewerbssituation herrscht (wichtig besonders bei neuen Technologien). Allerdings wachsen die Ingenieure mit ihren Aufgaben und stürzen sich deshalb nicht selten kopfüber in ein neues Vorhaben.

Die eigentliche Herausforderung besteht somit darin, ein Projekt erfolgreich zu starten und so schnell zu beenden, dass es maximale Einnahmen bringt - wohl wissend, dass sich bis zur Markteinführung praktisch jede Anforderung ändern kann. Ist das Produkt erfolgreich, wird es außerdem in noch schnellerer Folge Nachfolgeprodukte und Varianten geben.

Nichts ist so beständig wie der Wandel

Es empfiehlt sich, von vornherein auf eine Strategie zu setzen, die auf Änderungen vorbereitet ist. Von Beginn an ist davon auszugehen, dass sich alles ändern kann. Die verschiedenen Aspekte des Designs werden daraufhin untergliedert und hinter leistungsfähigen Schnittstellen gruppiert, die dafür sorgen, dass die hinter ihnen stattfindenden Veränderungen keine Auswirkungen auf das übrige Design haben.

Übrigens ist diese Programmierweise sehr willkürlich gewählt und passiert keineswegs in einem Umfeld, in dem der Code entsprechend den Anforderungen gleichsam am Fließband erzeugt wird. Die Anforderungen sind wichtig - daran besteht kein Zweifel.

Man kann jedoch die kritischen, strukturbezogenen Vorgaben von den Features trennen und mit dem anschließend beschriebenen Designkonzept schneller vorankommen und sich rasch den Gegebenheiten anpassen. Die Vorgehensweise ist wie folgt

  • Schritt 1: Festlegung der Struktur;
  • Schritt 2: Einrichten der Kommunikation;
  • Schritt 3: Definition des Timings;
  • Schritt 4: Schaffung der Voraussetzungen für austauschbare Features.

passend zum Thema

Wenn die Diskussionen zu einem neuen Projekt beginnen, einigt man sich in der Regel zunächst auf die wichtigen strukturellen Elemente und klärt Fragen zum Wesen des beabsichtigten Produkts: Handelt es sich um einen Toaster, einen Blade-Server, ein Handheld-Navigationssystem oder ein Mobiltelefon?

Aus dieser Produktdefinition entsteht eine Systemdefinition, in der bereits die wichtigsten Features ausgearbeitet werden und mit der durch Zerlegen des Produkts in kleinere Teilsysteme die eigentliche Entwicklung einsetzt. An dieser Stelle definieren die Entwickler das strukturelle Design der Subsysteme und schreiben es fest.

Die Produktfeatures auf der höheren Ebene beeinflussen die Vermarktbarkeit eines Produkts zwar ebenso wie die detaillierten Eigenschaften, diese Systemdefinition und die Aufteilung in Subsysteme haben jedoch keinen großen Einfluss darauf, wie der Kunde das spätere Produkt wahrnimmt. Dementsprechend unwahrscheinlich ist es, dass diese Partitionierung noch einmal grundlegend geändert wird. Was soll nun Teil der Strukturdefinition sein?

Hier sind auf jeden Fall die Host- und Peripheriebausteine auszuwählen, zumindest soll eine Entscheidung über die Bausteinklasse fallen. Mit dieser Festlegung der übergeordneten Hardwareanforderungen findet auch eine erste Aufteilung auf Hardware und Software statt. Anschließend gilt es, die Strukturen der einzelnen Subsysteme zu definieren und auszuarbeiten.

Während diese Struktur das Gerüst für die gesamte Applikation bildet, bleiben die Features selbst in diesem Stadium noch offen. Sie werden aber später in dieses Gerüst eingefügt. Als Praxisbeispiel soll ein moderner Heißluftofen dienen.

Bild 1: Heißluftofen des Typs »Aroma ABT-419DNS«
© Cypress Semiconductor

Bild 1 zeigt ein Standgerät mit digitalen Bedienelementen und LED-Display. Die übergeordnete Struktur dieses Produkts verlangt nach einem Heizsystem (elektrische Heizelemente samt Bedienelementen), einem Lüftersystem (zum Umwälzen der Heißluft), einem Netzteil und einer Benutzeroberfläche mit Berührungstasten und LED-Display.

Das Embedded System gliedert sich in das Stromversorgungssystem (für die Sicherheit und möglicherweise das Registrieren von Stromausfällen), das eigentliche Ofensystem mit Subsystemen zum Steuern der Heizelemente und des Lüfters aufgrund der Ist-Temperatur sowie die Benutzeroberfläche für Eingaben des Anwenders und das Display (zusätzlich möglicherweise mit gespeicherten Menüs bzw. Rezepten und Voreinstellungen).

Diese Strukturdefinition kann als recht stabil angesehen werden. Änderungen sind hier eher unwahrscheinlich. Groß ist die Wahrscheinlichkeit für Änderungen an dieser Stelle dagegen bei anderen Fragen. Wird beispielsweise ein Super-Mikrocontroller für alle Aufgaben mit der gesamten möglichen Hardware im Gerät verwendet (was eine Fantasievorstellung ist) oder besteht das Design aus mehreren MCUs und Standard-Peripheriebausteinen (dies ist wahrscheinlicher und »änderbarer«)?

Die Struktur muss über die Wahl der spezifischen Hardwareelemente hinausgehen und sich stattdessen auf die Applikation konzentrieren. Unabhängig davon, ob einer oder mehrere Mikrocontroller zum Einsatz kommen, wird es stets eine Haupt-MCU geben, der das Hauptaugenmerk beim Festlegen der Struktur gilt. Schließlich ist die Strukturdefinition auf die Endanwendung fokussiert.

Bild 2: Blockschaltbild des kompletten Ofens
© Cypress Semiconductor

In Bild 2 sind links die blauen Blöcke des Eingabeteils dargestellt: Temperaturwerte, Anwenderinteraktion und gespeicherte Rezepte.

Rechts befinden sich die roten Blöcke des Ausgabeteils: Heizelement, Lüfter und Anwenderdisplay. Verknüpft werden alle Elemente mit der in der Mitte dargestellten Steuerungslogik, die als zentrale Entscheidungsinstanz fungiert.

Dieses abstrakte Design muss noch den verschiedenen Subsystemen und Bausteinen zugewiesen werden, sodass es an dieser Stelle nicht erforderlich ist, über die Implementierung der in der Grafik dargestellten Pfeile Bescheid zu wissen oder zu entscheiden. Dies muss erst im Anschluss an Schritt 4 geschehen, doch selbst wenn es schon an diesem Punkt bekannt und festgeschrieben ist, wird es in den Schritten 2 bis 4 nicht verändert.

Einrichten der Kommunikation

Bild 3: Steuerungslogik mit Interfaces
© Cypress Semiconductor

Im jetzigen Stadium kann jeder der in Bild 3 dargestellten Blöcke als eigenständiges Subsystem betrachtet werden.

Die Kommunikation zwischen diesen Subsystemen ist die Interface-Definition. Dieses Festschreiben der Schnittstellen ist entscheidend dafür, die Essenz beziehungsweise die Struktur des Produkts zu erfassen und dafür zu sorgen, dass die Anforderungen für die einzelnen Subsysteme unabhängig voneinander weiterentwickelt werden können.

Damit bleiben die Rückwirkungen auf das Projekt (nämlich auf den Zeitplan und andere Aspekte) begrenzt. Im Brennpunkt dieses Schritts liegt die Steuerungslogik, also der grüne Block, der das Herzstück des Produkts bildet. Unter »Kommunikation« ist hier der Informationsfluss von und nach dem Steuerungslogik-Block zu verstehen. Es kann sich dabei um das von einem Echtzeitbetriebssystem (RTOS) unterstützte Messaging, eine physische Kommunikationsschnittstelle wie I2C oder SPI oder um schlichte Funktionsaufrufe handeln.

An dieser Stelle muss man die Details noch nicht alle kennen. Ziel ist es vielmehr, das Interface so einzurichten, dass die Steuerungslogik diese Einzelheiten tatsächlich niemals kennen muss. Damit ist sichergestellt, dass die im Steuerungslogik-Block implementierte zentrale Applikation unbeeinflusst von Fluktuationen in den übrigen Abschnitten weiterentwickelt werden kann.

Zum Einrichten der Kommunikation ist aus dem Blickwinkel der Steuerungslogik festzulegen, was von den einzelnen Ein- und Ausgabeblöcken nötig ist. Als Beispiel soll der Block »Temperaturerfassung« dienen, von dem die Steuerungslogik die aktuelle Ist-Temperatur erhalten muss (unter der beispielhaften Annahme, der Ofen habe nur eine Temperaturzone). Das Format der Temperaturinformation ist ein wichtiger Aspekt der Schnittstelle, da Änderungen an diesem Format gravierende Auswirkungen auf die Implementierung der Steuerungslogik haben.

Deshalb muss hier das Format ebenso festgelegt werden wie die Funktion, welche die Steuerungslogik verwendet. Dies kann eine in C formulierte Funktion sein, die im Prototyp »int getTemperature(void)« heißt. Der Temperaturwert ist folglich ein vorzeichenbehafteter Festkomma-Integerwert, der die Temperatur multipliziert mit dem Faktor 10 angibt (+353,7 °C würden als 3537 ausgegeben). Auch die Einheit ist wichtig. Sie kann als Bestandteil der Interfacebeschreibung »getTemperature« festgelegt sein, oder man verwendet zwei verschiedene Funktionen für Celsius- und Fahrenheitgrade (»getTemperatureF()« und »getTemperatureC()«).

Im Anschluss findet die Definition der Schnittstellen für die übrigen Blöcke statt, die in Bild 3 als blaue oder rote »IF«-Blöcke im grünen Steuerungslogik-Teil dargestellt sind.

Definition des Timings

Das Timing gehört zu den kritischen Designanforderungen und unterliegt damit zwangsläufig Veränderungen, während das Projekt voranschreitet. Die wichtigste Festlegung in diesem Stadium betrifft das Timing der verschiedenen Funktionsblöcke. Nimmt der Temperaturerfassungsblock seine Aktualisierungen asynchron vor und greift der Steuerungsteil lediglich auf den jeweils aktuellsten Wert zu, oder löst das Vorliegen eines neuen Temperaturwertes einen Interrupt in der Steuerung aus? Unterschiedliche Faktoren bestimmen diese Entscheidungen - nämlich wie schnell etwas geschieht und wie schnell darauf reagiert werden muss.

In der einfachsten Ausführung arbeiten alle Blöcke unabhängig voneinander und übermitteln jeweils ihre aktuellsten Daten an die Steuerungslogik (wenn es sich um Eingabeeinheiten handelt) oder führen die neuesten Anweisungen der Steuerungslogik aus (im Falle von Ausgabeeinheiten). Je weniger Vorgaben es für das Timing oder die Verarbeitungsreihenfolge gibt, umso besser. In diesem Schritt geht es darum, sämtliche Timing-Abhängigkeiten zu identifizieren und nach Möglichkeit zu eliminieren.

Im Fall des Temperaturblocks wäre es eine Möglichkeit, Temperatur-erfassungen durch die Steuerungslogik immer dann anzustoßen, wenn diese einen neuen Temperaturwert benötigt. Zweifellos wäre damit stets die aktuellste Information verfügbar - aber zu welchem Preis? Entweder muss die Steuerungslogik auf das Ende der Umwandlung warten, was das gesamte System ausbremst, oder die Einheit, welche die Umwandlung vornimmt, muss so schnell sein, dass sie das System nicht verlangsamt.

Eine entsprechend teurere Lösung wäre dann nötig. Es lohnt sich, etwas tiefer in die Materie einzusteigen und die normalen Betriebsbedingungen (wenn der Ofen heizt und ein neuer Temperaturwert die angeforderte Heizleistung verändert) von besonderen Situationen zu unterscheiden, in denen sofortiges Handeln nötig ist (z.B. Erkennung einer gefährlich hohen Temperatur, möglicherweise durch einen Kurzschluss ausgelöst).

Für dringende und ungewöhnliche Situationen lassen sich Interrupts reservieren, auf die umgehend reagiert wird, während die regulären Temperaturwerte asynchron an die Steuerungslogik übertragen werden. Mit einer ähnlichen Situationsanalyse lassen sich die Timing-Grenzen für jeden Block festlegen, wobei das Worst-Case-Timing definiert wird, um die Einhaltung der Produktanforderungen zu gewährleisten, während jedem Funktionsblock dennoch der größtmögliche Freiraum gewährt wird.


  1. Embedded-Entwicklung: Wenn sich Anforderungen ändern
  2. Aussitzen - aber richtig!

Lesen Sie mehr zum Thema


Jetzt kostenfreie Newsletter bestellen!

Weitere Artikel zu Cypress Semiconductor GmbH