
Ein eingebettetes System (auch englisch „embedded system“) ist ein meist kompakter Computer, der in einen technischen Kontext eingebunden (eingebettet) ist. Dabei übernimmt der Rechner entweder Überwachungs-, Steuerungs- oder Regelfunktionen oder ist für eine Form der Daten- und/oder Signalverarbeitung zuständig, beispielsweise beim Ver- bzw. Entschlüsseln, Codieren bzw. Decodieren oder Filtern. Weitere verwandte Bezeichnungen und/oder Geräte sind System-on-a-Chip (SoC) und die Controller. Die Systeme bzw. Geräte werden als Teil des Embedded Software Engineering entwickelt.
Eingebettete Systeme verrichten – weitestgehend unsichtbar für den Benutzer – ihren Dienst in einer Vielzahl von Anwendungsbereichen und Geräten, beispielsweise in einer Vielzahl von Fahrzeugen (Kraftfahrzeugen oder Flugzeugen), Haushaltsgeräten wie Waschmaschinen oder Kühlschränken, Fernsehgeräten, aber auch Mobiltelefonen oder allgemein in Geräten der Unterhaltungselektronik.
Im Fall von Gesamtsystemen handelt es sich dabei meist um eine Vernetzung einer Vielzahl von ansonsten autonomen eingebetteten Einzelsystemen, beispielsweise die verschiedenen Steuergeräte aus der Automobilelektronik.
Oft werden eingebettete Systeme speziell an eine Aufgabe angepasst. Aus Kostengründen wird eine optimierte gemischte Hardware-Software-Implementierung gewählt. Dabei vereint eine solche Konstruktion die große Flexibilität von Software mit der Leistungsfähigkeit der Hardware. Die Software dient dabei sowohl zur Steuerung des Systems selbst als auch zur Interaktion des Systems mit der Außenwelt über definierte Schnittstellen oder Kommunikationsprotokolle wie z. B. CAN-Bus, ZigBee für drahtlose Kommunikation oder TCP/IP über Ethernet.

Der erste prominente Einsatz eines eingebetteten Systems war der des Apollo-Guidance-Computers, der von Charles Draper zusammen mit dem MIT Instrumentation Laboratory entwickelt wurde. Jeder Flug auf den Mond hatte zwei dieser Systeme dabei (Redundanz), die zur Steuerung verwendet wurden. Das Inertial Guidance System wurde sowohl im Kommandomodul als auch in der Mondlandefähre (Lunar Excursion Module) verwendet. Zu Beginn des Apollo-Programms wurde dieses System als eine der riskantesten Komponenten des Projektes angesehen.
Die ersten eingebetteten Systeme wurden aber schon vorher in der Minuteman-Interkontinentalrakete (ICBM) eingesetzt und in Serie produziert. Die Anwendung war ein Wege-Such-System, das der Rakete nach einmaliger Programmierung ein unabhängiges Manövrieren ermöglichte. Durch den Preisverfall öffneten sich die verwendeten integrierten Schaltungen (ICs) allmählich einem größeren Kreis von Anwendungen und eröffneten neue elektronische Möglichkeiten beim Bau von Steuergeräten. Die entscheidende Eigenschaft des Minuteman-Computers war, dass der Weg-Finde-Algorithmus später programmiert werden konnte, wodurch sich die Rakete wesentlich präziser einsetzen ließ. Ein weiterer Vorteil bestand in der Selbsttestfunktion der Rakete zur Statusabfrage sowie darin, dass man zugunsten des Gewichtes auf größere Mengen von Kabeln verzichten konnte.

Eingebettete Systeme können in Einzelfällen auf ähnlicher Hardware wie Arbeitsplatzcomputer basieren (Embedded-PCs). Typischerweise unterliegen sie jedoch stark einschränkenden Randbedingungen: minimale Kosten, geringer Platz-, Energie- und Speicherverbrauch. Einzelne Komponenten wie Prozessor und Arbeitsspeicher basieren oft auf Weiterentwicklungen älterer Komponenten, was die langfristige Einsetzbarkeit und Ersatzteilbeschaffung erleichtert. „Moderne“ eingebettete Systeme basieren häufig auf Prozessorplattformen, die mit der PC-Welt wenig gemeinsam haben, aber in Bezug auf die Peripheriemodule hochintegriert sind und durch moderne Stromspartechniken deutlich weniger Energie verbrauchen.
Bei vielen Anwendungen kann die Verwendung einer älteren Prozessorarchitektur dazu beitragen, Kosten zu senken. So sind die Architekturen der MCS-51-, PICmicro- oder Z80-Serie trotz ihres Alters und bekannter Schwächen immer noch eine beliebte Basis für eingebettete Systeme. Die Wiederverwendung von Programmcodes und Werkzeugen sowie die Scheu vor vollständigen Re-designs „ohne Not“ sind hierbei neben den reinen Materialkosten ebenfalls nicht zu unterschätzende Randfaktoren.
In einem eingebetteten System muss die Software häufig Echtzeitanforderungen genügen. In der Regel existieren, verglichen mit PC-Hardware, nur stark reduzierte Ressourcen, zumeist ohne Festplatte, häufig ohne Betriebssystem, Tastatur oder Bildschirm. Ein ROM- oder Flash-Chip ersetzt mechanische Speicherkomponenten wie eine Festplatte, stromsparende Prozessoren kommen ohne Lüfter aus, denn bewegliche Teile bedeuten Verschleiß und Fehleranfälligkeit. Wenn überhaupt, dann gibt es meistens nur ein Tastenfeld, und die Ausgabe wird – soweit vorgesehen – durch ein LCD realisiert.
Die Software auf einem solchen Gerät wird Firmware (FW) genannt. Sie befindet sich gewöhnlich auf einem ROM (oder ähnlichem Halbleiterspeicher), immer häufiger jedoch auf Flash-Speicher. Im Falle eines Flash-Speichers besteht die Möglichkeit eines Firmware-Updates, ohne dass der Chip ausgewechselt werden muss. Ist nur ein ROM vorhanden, muss zumeist der gesamte Chip ausgewechselt werden, manchmal auch die gesamte Schaltung.
Im Wesentlichen besteht die Firmware, also der lauffähige Programmcode (Executable) für ein embedded System, aus drei Komponenten:
Bei kleinen eingebetteten Systemen können die drei Softwareteile zusammengefasst sein. Bei größeren Systemen können sogar mehrere Firmwares verteilt und genutzt werden.
Eingebettete Systeme werden mittels vieler verschiedener Mikroprozessor- oder Mikrocontroller-Architekturen (8051, Arm, AVR, TI MSP430, MIPS, PowerPC, 68000/Coldfire, Intel x86, 68HC12, C167, Renesas M16C, H8S und diverser anderer 8/16/32-Bit-CPUs) realisiert.
Eine Untergruppe der Architekturen sind die Prozessorfamilien (beispielsweise 8051, AVR, PIC16, ARM7, PowerPC 5xx, MIPS 4k, AMD AU1000, Intel Pentium M), bei denen verschiedene Varianten mit denselben Entwicklungswerkzeugen und Debugger-Werkzeuge betrieben werden können. Unterschiede innerhalb einer Prozessorfamilie bestehen bei der Geschwindigkeit und vor allem der Ausstattung mit Speicher und Peripheriebausteinen.
Eine besonders flexible Plattform sind hochintegrierte FPGA-Bausteine (Field Programmable Gate Array), mit denen zum einen unterschiedliche CPU-Architekturen nachgebildet werden können (beispielsweise 68000 und PowerPC 405 auf einem Chip) und zum anderen auch gut parallele Rechenleistung ohne Prozessor – nur mittels dedizierter Logik – zur Verfügung gestellt werden kann. In realen Anwendungen werden oft beide Ansätze in einem FPGA als System-on-a-Chip (SoC) integriert. Zum Einsatz kommen hierbei als Prozessor sowohl fest verdrahtete Hardmakros wie die PowerPC-Kerne in verschiedenen Xilinx-Virtex-FPGAs als auch flexibel konfigurierbare Softcore-Prozessoren wie Alteras Nios II, Xilinx MicroBlaze, der Mico32 von Lattice oder auch IP-Cores eines Mikrocontrollers wie PICmicro oder die MCS-51-Baureihe.
Die Softwareumgebung zur Programmentwicklung, also Compiler, Assembler und Debugger (benötigen meist externe Hardware), wird in der Regel von verschiedenen Herstellern angeboten:
Manche Hersteller bieten auch System Design Kits an, die eine Prototypenplatine mit dem entsprechenden Prozessor zusammen mit einem Software Development Kit (SDK) und Dokumentation zu Hard- und Software enthalten.
Die Softwareentwicklung für eingebettete Systeme unterscheidet sich grundsätzlich von der für Anwendungssoftware für PCs, da hierbei der Fokus auf den Möglichkeiten der elektronischen Ein-/Ausgabe liegt. Die Funktionen dafür sind hardwareabhängig und für jedes System spezifiziert, d. h. die Software wird mit der Computerhardware gepaart und ist in der Regel nicht übertragbar auf andere Systeme. Hier spielt auch das Konfigurationsmanagement eine übergeordnete Rolle.
Die Software für Embedded Systeme, also die Firmware, wird in der Regel über einen Cross-Compiler erzeugt. Dieser Compiler läuft auf dem Entwicklungssystem (Host-System), also normalerweise einer anderen Rechnerarchitektur als der des Zielsystems. Cross-Compiler sind dabei nicht auf einen bestimmten Prozessor begrenzt, sondern können Maschinencode für eine ganze Prozessorfamilie erzeugen, wie ARM7, PowerPC 8xx.
Die bevorzugte Programmiersprache für eingebettete System ist in der Regel C, aber auch C++ oder Java (siehe OSGi oder Embedded Java) finden Verwendung. Assemblersprache wird dann eingesetzt, wenn Gerätetreiber-Funktionen vor allem in Interrupts programmiert werden oder wenn das Betriebssystem selbst an eine neue Umgebung bzw. CPU angepasst werden muss. Oberhalb des Betriebssystems ist Assembler eher eine Randerscheinung, in Systemen ohne Betriebssystem (Bare Metal) und vor allem bei massiven Speicherrestriktionen kommt Assembler jedoch noch zur Anwendung.
Bei „kleinen“ Systemen kommt häufig kein Betriebssystem zum Einsatz. Man spricht dann auch von einem Bare-Metal-System, welches nur laufzeitfähige Funktionen aufruft und ausführt. Wenn in eingebetteten Systemen ein Betriebssystem eingesetzt wird, handelt es sich meistens um darauf spezialisierte Betriebssysteme (Beispiele: QNX, VxWorks, Nucleus, OSEK, OS-9, RTEMS oder ECos). Auch eingebettete Varianten von Standardbetriebssystemen wie Linux (Embedded Linux), NetBSD oder Microsoft Windows (3.x, CE, XP Embedded, Automotive oder Windows Embedded POSReady 2009/POSReady 7) kommen zum Einsatz.
Oftmals haben Anwendungen weiche oder gar harte Echtzeitanforderungen. Hierfür müssen spezielle Echtzeitbetriebssysteme (englisch Real-Time Operating System (RTOS)) oder Betriebssysteme mit entsprechend angepassten Kerneln verwendet werden.
Das Testen von Software für eingebettete Systeme findet oft in frühen Entwicklungsphasen auf dem Host-PC statt. Dafür muss die Umgebung der Anwendung, mit der das eingebettete System kommuniziert, simuliert werden. Diese Simulation nennt sich Model in the Loop (MIL) oder Software in the Loop (SIL). Wenn die Software auf der Zielhardware implementiert ist, spricht man dagegen von Hardware in the Loop (HIL); der Zugriff auf die Testhardware vom Host-PC aus erfolgt dabei in der Regel über einen Hardware-Emulator.
Ein Systemtest kann mittels HIL durchgeführt werden, bei dem das fertige eingebettete System an eine spezielle Hardware angeschlossen wird, die die Umgebung des Systems simuliert. Auf diese Weise kann das Verhalten des Systems mit Testfällen detailliert untersucht werden.
Bei eingebetteten Systemen wird dem Debugging ein stärkerer Fokus eingeräumt. Debugging umfasst Fehlerbeseitigung sowohl in der Software als auch im integrierten System.
Für derartige hardwarenahe Softwaretests kann ein In-Circuit-Emulator (ICE) verwendet werden, eine Kombination aus Programm und Hardware, welcher es erlaubt, die Software im System, also auf der Zielhardware zu testen. Traditionellerweise muss dazu der eigentliche Controller gegen die ICE-Hardware (ein sogenannter Bond-out-Prozessor) ausgetauscht werden. Das erlaubt es, die Software komfortabel und ohne weitere Eingriffe in der Zielhardware zu entwickeln. Da mit dem ICE-Zugriffe auf die Peripherie der CPU möglich sind, lassen sich Software- von Hardwarefehlern unterscheiden und trennen. Früher wurde dazu ein Logikanalysator benötigt, der als Zusatzoption die Ziel-CPU emulieren konnte.
Einige eingebettete CPUs haben schon einen „Schmalspur“-ICE an Bord, so dass der Hardware-ICE nicht unbedingt benötigt wird. Demgegenüber sind die Einwirkungsmöglichkeiten der Debugging-Software auf die Ziel-CPU/MPU eingeschränkt. Eine komplette Überwachung der CPU ist nicht möglich, dafür sind jedoch die Kosten erheblich geringer. Kostet ein voll ausgebautes ICE-System für ein 68000-Derivat einen bis zu sechsstelligen Eurobetrag, liegen die Kosten für solch ein „Schmalspur“-System im unteren 3-stelligen Eurobereich. Meist kommt eine Schnittstelle vom Typ JTAG zum Einsatz. Eine Alternative für Coldfire- und 68000-Derivate ist die Schnittstelle Background Debug Module (BDM) von Motorola.
Auch bei ARM-Architekturen, z. B. Microcontrollern mit Cortex-M3, ist eine JTAG-Schnittstelle als spezieller Debugging-Zugang vorhanden. Damit ist ein Teil des Microcontrollers gemeint, der für den normalen Programmablauf nicht nötig und nur für das Debugging eingebaut bzw. konfiguriert wurde. Dieser Debugging-Teil kann mit einer Debugging-Software über einen JTAG- oder SWD-Adapter angesprochen werden. Damit lässt sich der Prozessor an beliebigen Stellen im Programm anhalten, und die Werte der Register oder des Speichers können angesehen oder verändert werden. Auch ein schrittweises Abarbeiten des Codes zur Fehlersuche ist möglich. Als Hardware ist hier ein JTAG- oder SWD-Adapter notwendig. Die Debuggersoftware kann von voll funktionsfähiger Freeware (gdb + ddd, gdb + kgdb, Eclipse) bis zu professioneller Software im Tausend-Euro-Bereich reichen.
Alternativ wird oft mit Simulatoren gearbeitet, welche die interne Struktur und die Peripherie des Mikrocontrollers in Software nachbilden. Beim Debugging sind die „externen“ Signale (Tasten, Display) „von Hand“ nachzubilden, wobei Interrupts benutzt werden müssten, die im Simulator nicht realisierbar sind.
Ein sogenannter Microcode-Interrupt lässt den Debugger auf der Hardware arbeiten statt nur auf der CPU. Vom Standpunkt der CPU aus können CPU-basierte Debugger dann benutzt werden, um die Elektronik des Computers zu testen und gegebenenfalls Fehler zu diagnostizieren. Diese Fähigkeit wurde an der PDP-11 (siehe Programmed Data Processor) erforscht und entwickelt.
In sicherheitskritischen Anwendungen, wie bei Flugsteuerungsrechnern (vgl. Avionik und DO-178C), wird die Sprache Ada eingesetzt – man muss hier allerdings differenzieren zwischen den zeitkritischen und den sicherheitskritischen Anwendungsebenen, für die ggf. innerhalb des Systems unterschiedliche Anwendungen und Programmiersprachen verantwortlich sein können. Für Geräte, Maschinen, Anlagen und viele andere sicherheitskritische Anwendungen gelten Normen wie die IEC 61508. Für den Automobilbau gilt die ISO 26262.
Moderne Mikroelektronik-Bausteine wie die Mikrocontroller besitzen außerdem (teilweise) umfangreiche Sicherheitskapazitäten wie Speicherschutzmechanismen wie eine Memory Protection Unit (MPU) bzw. Memory Management Unit (MMU), die dafür sorgt, dass sich die einzelnen Programmfunktionen nicht gegenseitig beeinflussen.
Nicht nur in der Automobilindustrie findet eine sogenannte modellbasierte Entwicklung mit Matlab/Simulink oder ASCET Anwendung. In zunehmendem Maße erfolgt die Softwareentwicklung für eingebettete Systeme mit Hilfe modellbasierter Entwicklung, mit welchen modellbasiert und graphisch das Verhalten des Systems modelliert und spezifiziert wird, welches dann im Idealfall mittels Codegenerierung in die Zielprogrammiersprache überführt wird.
Bei der Konzeption eingebetteter Systeme gibt es einige ingenieurstechnische Überlegungen und Aspekte zu berücksichtigen.
Viele Anwendungen werden erst dadurch sinnvoll und nutzbar, dass die dafür erforderliche Signalverarbeitung in Echtzeit erfolgt. Geräte, Systeme und Verfahren, die mit dem Attribut „Echtzeit“ versehen werden, sollten nach objektiven Maßstäben Kriterien wie „Rechtzeitigkeit“, „Vorhersagbarkeit“, „Sicherheit“ und „Zuverlässigkeit“ erfüllen. Dies setzt eine Echtzeitplanung von Prozessen voraus. Überdies muss die maximale Laufzeit zur Erfüllung einer Aufgabe aus der Systemumgebung bestimmbar, also einem deterministischen Prozessablauf zugehörig sein. Die Reaktionszeit des Systems zur Erfüllung der Aufgabe muss dem Kriterium der „Rechtzeitigkeit“ genügen. Zur Realisierung der Echtzeitverarbeitung finden unter Berücksichtigung der Benutzerschnittstelle(n) und der Programmierschnittstellen verschiedene Softwarekonzepte Anwendung.
Die nachfolgend aufgeführte sogenannte „Regelschleife“, die auf den Entwurf eines Reglers hinausläuft, ist allenfalls für äußerst einfache regelnde Embedded-Systeme in der Industrie geeignet. Sie muss noch nicht mal mit Echtzeit unterlegt sein. Davon zu unterscheiden ist der sogenannte „reaktive Ansatz“, der auf den Entwurf eines sogenannten „reaktiven Systems“ hinausläuft, das sich in ständiger Interaktion mit der Umgebung befindet, wobei die Umgebung dominiert und das reaktive System sich dieser unterordnet.
Regelschleifen werden für Regelungssysteme eingesetzt, die zyklisch Berechnungen aufgrund von Eingangssignalen vornehmen und Ausgangssignale senden (siehe Regelungstechnik). Dies wird auch als „zeitgesteuertes Design“ bezeichnet.
Der reaktive Ansatz führt zum Entwurf eines Prozessablaufs, in welchem aperiodisch auftretende Ereignisse, wie etwa ein Tastendruck oder eine Folge von Tastendrücken, verarbeitet und daraus resultierende Aktionen veranlasst werden. Derartiges wird als „ereignisgesteuertes Design“ bezeichnet.
Alle eingebetteten Systeme haben einen Start-up Code, der nach dem Einschalten durchlaufen wird. Normalerweise deaktiviert dieser die Interrupts, kalibriert die interne Elektronik, testet den Computer (RAM, ROM, CPU) und startet den eigentlichen Programmcode, nachdem alles erfolgreich getestet wurde.
Viele dieser Systeme sind innerhalb von 100 ms einsatzbereit. Selbst nach einem kleinen Stromausfall oder einer Spannungsschwankung laufen diese Geräte sofort weiter, da die interne Hardware den Selbsttest der Hardware und Software überspringt. Es tritt jedoch durch möglicherweise veränderte Bits im RAM undefiniertes Systemverhalten auf, das eine Schaltung zur Spannungsüberwachung (Supply Voltage Supervisor, SVS oder auch Brownout Detection genannt) vermeidet. Der SVS löst einen „richtigen“ Reset aus, so dass das System komplett initialisiert wird und auch die Selbsttests durchläuft.
Die Dauer des Systemstarts ist bei der Kfz-Elektronik an den Kontrollleuchten erkennbar, die nach Einschalten der Zündung aufleuchten und nach kurzer Zeit wieder erlöschen. Der Systemstart führt bei vielen Geräten dazu, dass das Einschalten länger dauert als bei analogen Geräten, beispielsweise bei Autoradios.
Zwischen dem eingebetteten System und einer Systemumgebung, welche das eingebettete System aufnimmt, befinden sich in der Regel verschiedene Schnittstellen. Diese Schnittstellen können je nach Anwendungszweck des eingebetteten Systems in der Praxis sehr unterschiedlich ausgeführt sein. Die folgenden Schnittstellen müssen berücksichtigt werden:
Folgende Aspekte spielen bei Entwurfsentscheidungen von eingebetteten Systemen eine Rolle:
Mit dem verstärkten Einsatz von eingebetteten Systemen in beispielsweise Automobilen macht sich ein weiteres Problem bemerkbar: Die Anzahl der Systeme ist so hoch, dass der verfügbare Platz in einem Auto nicht ausreicht und der Verkabelungsaufwand steigt. Deshalb werden mehrere Steuerfunktionen in einem Steuergerät vereint, ermöglicht durch leistungsfähige Mikrocontroller. Der Trend zur Konsolidierung der Software- und Hardware-Architektur setzt sich auch nach den 2010er Jahren fort. In diesem Bereich entwickeln sich konventionelle Motorsteuergeräte zu Fahrzeugcomputern weiter.
Auch sollte die Verbreitung von 8/16-Bit-Controllersystemen nicht unterschätzt werden. In diesem Marktsegment gilt die Maxime der Stromverbrauchs- sowie der Kostenminimierung und daher das Prinzip „nur so viel wie nötig“.
Typische Rechnerarchitekturen für eingebettete Systems sind:
Ältere Systeme (Legacy, Abgekündigt oder Obsolet)