Tief eingebettete Software auf Mikrocontrollern

In vielen Produkten, die uns täglich umgeben arbeitet Software auf Mikrocontrollern mit sehr begrenzten Ressourcen (Speicher, Rechenleistung, Energie). Diese muss hochoptimiert sein, um mit den eingeschränkten Mitteln der Hardware zuverlässig ihren Dienst zu verrichten...

Die Gründe, warum auf manchen Plattformen nur sehr begrenzte Ressourcen zur Verfügung stehen sind vielfältig: Oft handelt es sich um Geräte, die in hohen Stückzahlen hergestellt werden (z.B. Haushaltsgeräte), so dass sich durch den Einsatz von nur um wenige Cent billigeren Hardwarebausteinen (z.B. leistungsärmerer Prozessor, kleinerer Speicher) erhebliche Kosten einsparen lassen. In anderen Fällen geht es darum, mit wenig Energie möglichst lange Gerätelaufzeiten zu erreichen (z.B. batteriebetriebene Verbrauchszähler, Handheld-Messgeräte).

Häufig kommen heute in solchen Applikationen 32-Bit Mikrocontroller basierend auf ARM Cortex-M Kernen bzw. sehr stromsparende 16-Bit Mikrocontroller (z.B. TI MSP430) zum Einsatz. Vereinzelt findet man auch noch Plattformen mit 8-Bit-Mikrocontrollern (z.B. Atmel ATmega).

redlogix ist mit den speziellen Herausforderungen der Embedded Softwareentwicklung für diese Art von Anwendungen bestens vertraut und hat für eine Vielzahl solcher Produkte Software entwickelt.

Beispiele

  • Bedienschnittstellen mit grafischen Touch-Displays für (gastronomische) Spülmaschinen
  • RFID-Lesegeräte für das Produkt-Tracking und Lagerhaltung in der industriellen Fertigung
  • Bediengeräte für industrielle Steuerungsaufgaben
  • kompakte Laserdistanzmessgeräte
  • mobile Messgeräte zur Messung von Entladeströmen in Schaltanlagen und Kabeln
  • Verbrauchszähler (z.B. Wasser, Wärme, elektrische Energie)
  • Verkaufsautomaten (z.B. für Parkscheine)
  • Tracker-Armband zur Unterstützung der Armrehabiliations-Therapie von Schlaganfallpatienten
  • Steuerungsmodule für Bodenreinigungsgeräte
  • Kombianzeigeinstrumente in Baumaschinen und Nutzfahrzeugen (z.B. Betriebsstunden, Temperatur, Ladezustand)
  • Steuerungsanwendung für einen Pedelec-Antrieb inkl. integriertem Automatikgetriebe

Eingesetzte Technologien und Tools

  • C bzw. C++
  • CAN
  • GSM
  • M-Bus
  • WLAN
  • Bluetooth LE
  • I2C
  • SPI
  • UART
  • NFC / RFID
  • Segger emWin
  • Keil µVision
  • IAR Workbench
  • Atollic TrueSTUDIO
  • redBlocks Toolkit und SiL-Tests mit redBlocks Simulator

„Bare Metal“

Ein wesentliches Merkmal von solch tief eingebetteter Software ist der Umstand, dass die Software auf der blanken Hardware arbeitet, d.h. direkt auf die extern angeschlossenen oder in den Mikrocontroller integrierten Peripheriebausteine zugreifen muss. Dementsprechend besteht ein Großteil der Software aus Treibern für diese Hardwarekomponenten und wird zum Teil im Kontext von Interrupt-Service-Routinen ausgeführt.

Auf dieser Gattung von Plattformen kommt (anders als z.B. bei Systemen auf Basis von Embedded Linux) kein Betriebssystem zum Einsatz, das eine standardisierte Ausführungsumgebung für die Softwareanwendung bietet. Stattdessen wird der Programmcode typischerweise direkt aus dem Flash des Mikrocontrollers ausgeführt und Datenspeicherzugriffe erfolgen direkt auf den physikalischen Adressraum der CPU, d.h. ohne Zugriffschutz durch die virtuelle Speicherverwaltung eines Betriebssystems. Weil Datenspeicher nur in sehr begrenztem Umfang zur Verfügung steht, verbietet es sich daher, dass die Software zur Laufzeit in nicht deterministischer Weise dynamischen Speicher anfordert und wieder freigibt (Risiko der Speicherfragmentierung).

Software-Architektur

Gerade weil durch die Plattform selbst keine saubere Trennung zwischen hardwareabhängigen und hardwareunabhängigen Softwareteilen vorgegeben ist, ist es bei dieser Art von Softwareanwendungen nötig, diese Trennung durch eine geeignete plattform- und anwendungsspezifische Softwarearchitektur zu realisieren. Nur so ist es möglich bei der Softwareverifikation mit Unit-Tests zu arbeiten und die Applikationsfunktionalität mit überschaubarem Aufwand auf eine andere Hardware zu portieren.

Und auch bei tief eingebetteter Software möchte man nicht jede benötigte Funktionalität anwendungsspezifisch immer wieder von neuem entwickeln, sondern möglichst auf generische und wiederverwendbare Softwarekomponenten zurückgreifen. Weil die zur Verfügung stehenden Hardware-Ressourcen allerdings sehr beschränkt sind, darf dadurch kein nennenswerter Overhead (größerer Code, zusätzliche Fallunterscheidungen zur Laufzeit, usw.) entstehen.

Diese beiden gegensätzlichen Anforderungen, also eine saubere Softwarestruktur mit wiederverwendbaren Komponenten ohne nennenswerten Overhead lässt sich durch das Konzept der sogenannten statischen Polymorphie erreichen. Dabei werden die Softwarekomponenten bereits zur Compile-Zeit entsprechend ihres Einsatzzweckes konfiguriert und so miteinander integriert, dass die Konfigurationsoptionen nicht zu Fallunterscheidungen oder Indirektionen (z.B. über Funktionszeiger) zur Laufzeit führen. Das resultierende ausführbare Programm ist dadurch genauso klein und schnell wie eine „hochoptimierte“ Software ohne saubere Struktur, lässt sich aber sehr viel besser warten und kann durch den Einsatz von bereits existierenden Softwarekomponenten meist viel schneller entwickelt werden.

Speziell für solche tief eingebettete Softwareanwendungen hat redlogix das Produkt redBlocks (red steht für rapid embedded development) entwickelt. Die generischen und flexibel wiederverwendbaren Softwarekomponenten aus der redBlocks Komponentenbibliothek setzen ganz konsequent auf das Konzept der statischen Polymorphie und versetzen den Entwickler in die Lage, hocheffiziente Embedded Softwareanwendungen schneller und damit kostengünstiger zu entwickeln. Das Produkt redBlocks kommt in etlichen von redlogix im Kundenauftrag realisierten Softwareanwendungen zum Einsatz, steht aber auch als lizenzierbares Produkt für Eigenentwicklungen unserer Kunden zur Verfügung.

Logo redBlocks

RTOS oder Mainloop-Ansatz?

Häufig werden wir mit der Frage konfrontiert, ob sich der Einsatz eines präemptiven embedded RTOS für diese Art von Anwendungen gegenüber einem einfachen Run-to-Completion Mainloop-Scheduling lohnt. Darauf kann es natürlich keine pauschale Antwort geben. Vielmehr sind die Vor- und Nachteile anhand der jeweiligen Anforderungen individuell abzuwägen. Unsere Erfahrung zeigt, dass in vielen Applikationen ein embedded RTOS eingesetzt wird, weil es vermeintlich „State-of-the-Art“ ist, ohne auch die damit einhergehenden Nachteile zu betrachten (insgesamt höherer Ressourcenbedarf, fehleranfällige Konfiguration der benötigten Stackgröße pro Task, Umgang mit komplexeren Konkurrenzsituationen, Kosten / Aufwand für die Zertifizierung des RTOS-Codes in sicherheitskritischen Anwendungen, …). Dabei lässt sich mit Hilfe eines einfachen Mainloop-Schedulers die gleiche Applikationsfunktionalität häufig sehr viel unkomplizierter realisieren.

Auch die Hoffnung, dass durch den Einsatz eines RTOS besser strukturierter Code entsteht erfüllt sich oft nicht. Wir empfehlen daher, die Anforderungen an die Embedded Software zunächst genau zu analysieren, um auf dieser Basis eine fundierte Entscheidung treffen zu können. Gerne beraten wir unsere Kunden auch in dieser Entwicklungsphase mit unserem langjährigen Know-How auf diesem Gebiet.

C oder C++?

Eine andere oft aufgeworfene Frage ist die Wahl der Implementierungssprache. Häufig trifft man auf Vorbehalte gegen den Einsatz von C++, wenn es um die Implementierung von Softwareanwendungen für extrem ressourcenarme Plattformen geht. Dabei „kostet“ der Einsatz eines C++ Compilers zunächst keinerlei Ressourcen (in Form von größerem oder langsamerem Binärcode). Selbst etliche extrem hilfreiche C++ Sprachfeatures wie Datenkapselung und Zugriffschutz mittels Klassen, Vererbung, die Verwendung von Namespaces, Operatorüberladung, usw. führen zu keinerlei Overhead gegenüber der gleichen mit der Programmiersprache C realisierten Funktionalität. Erst wenn Sprachfeatures wie virtuelle Methoden oder Exceptions bzw. dynamische Speicherverwaltung ins Spiel kommen (z.B. auch „unabsichtlich“ durch den Einsatz von Container-Klassen aus der STL), stellen sich ggf. signifikante Größenunterschiede zwischen C und C++-Programmen ein.

Daher ist es zwingend notwendig, die Programmiersprache C++ sehr genau zu verstehen bevor man ihre vielen Vorteile für die Entwicklung von effizienten Embedded Software-Applikationen nutzen kann. redlogix hat langjährige Erfahrung in der Anwendung von C++ als Implementierungssprache und vermittelt dieses Wissen in Form von Coaching und Schulungen.

Wenn die Wahlfreiheit besteht, gibt es keinen Grund, der gegen den Einsatz von C++ spricht. Es kann jedoch Rahmenbedingungen geben, die für den Einsatz von C sprechen (z.B. existierende C-Codebasis, regulatorische Forderungen, …). Auch bei dieser Entscheidung stehen wir Ihnen gerne als Ansprechpartner zur Verfügung. Zögern Sie also nicht, uns zu kontaktieren, wenn Sie Fragen haben oder eine neutrale Meinung einholen möchten.