Loslegen mit DevOps für eingebettete Systeme unter Verwendung des ATmega328P

Ari Mahpour
|  Erstellt: Mai 29, 2024  |  Aktualisiert am: Juli 1, 2024
Einstieg in DevOps für eingebettete Systeme mit dem ATmega328P

DevOps und Agile Methoden haben die Softwareentwicklung durch die Betonung von Zusammenarbeit, Automatisierung und kontinuierlicher Verbesserung transformiert. Die Anwendung von DevOps-Prinzipien auf meine Entwürfe und Projekte war ein Game-Changer, der Effizienz und Zuverlässigkeit verbessert hat. In diesem Artikel werden wir durch die Einrichtung eines Continuous Integration (CI)-Workflows für ein bestehendes Embedded-Systems-Projekt gehen, das den ATmega328P-Mikrocontroller verwendet. Am Ende dieses Artikels sehen Sie, wie diese Praktiken Ihren Entwicklungsprozess rationalisieren und Produkte von höherer Qualität liefern können.

Verständnis von DevOps und Agile für eingebettete Systeme

DevOps ist eine Reihe von Praktiken, die in der Softwarewelt populär geworden sind und die Softwareentwicklung (Dev) und IT-Betrieb (Ops) in einen kontinuierlichen Fluss überführen. In der Softwarewelt war es üblich, Software zu entwickeln und sie dann „über die Mauer“ an die Betriebsleute zur Bereitstellung an die Kunden zu werfen. DevOps führte eine Methode ein, nicht nur diese Mauer einzureißen, sondern den gesamten Prozess von Anfang bis Ende zu automatisieren. In der Hardwarewelt finden wir Ähnlichkeiten zwischen Produktentwicklung und Produktion, indem wir das Design ständig „über die Mauer“ an unsere Fertigungsingenieurteams werfen, um sicherzustellen, dass alles bereit ist für die Produktion.

Bei der Entwicklung eingebetteter Produkte müssen wir unsere Software immer noch durch die Produktion bringen, stehen aber vor der Herausforderung, schneller denn je zu sein und die höchstmögliche Qualität zu liefern. Mit DevOps-Prinzipien zielen wir darauf ab, einige dieser Herausforderungen zu lösen.

  • Hardwareabhängigkeiten: Eingebettete Systeme hängen von Hardware und spezifischen Revisionen dieser PCBs ab. Dies kann das Testen und die Bereitstellung komplex machen, wenn es nicht so gestrafft wird, dass es automatisiert und hoch skalierbar ist. DevOps-Praktiken helfen, diese Prozesse zu automatisieren, indem sie die gleiche Einrichtung sowohl für die Hardware als auch für die Software verwenden und sie durch automatisierte Continuous Integration (CI)-Systeme schicken.
  • Lange Bauzeiten: Das Erstellen eingebetteter Software kann schwierig einzurichten sein und zu langen Bauzeiten führen. CI automatisiert und beschleunigt diesen Prozess, indem Builds in die Cloud ausgelagert werden, die leistungsfähigere Instanzen nutzen, auf die Entwickler normalerweise keinen Zugriff haben.
  • Manuelles Testen: Das Testen auf tatsächlicher Hardware ist unerlässlich, aber oft manuell, mühsam und zeitaufwändig. Automatisierung durch Hardware-in-the-Loop (HIL)-Tests verbessert Effizienz und Genauigkeit und kann auf eine Einrichtung von automatisierten Testgeräten ausgelagert werden, die mit Ihrem CI-System konfiguriert sind.

Durch die Anwendung von DevOps-Prinzipien können wir schnell iterieren, indem wir Agile Methoden innerhalb des Build-Test-Deploy-Paradigmas für jedes zusätzliche Feature verwenden, das wir zur Produktion freigeben möchten.

Wie es funktioniert

„Build, test, and deploy“ ist eine häufig gehörte Wortkombination, wenn es um DevOps geht. In eingebetteten Systemen machen wir dasselbe, da unsere Bereitstellung ebenfalls in die Produktion (und dann zum Endkunden) geht. Im Projektrepository verwenden wir Gitlab CI, um unseren End-to-End-Workflow für Embedded DevOps zu steuern. Wir verwenden sogenannte „Pipelines“, um Jobs zu erstellen, die bestimmte Aufgaben wie das Kompilieren der Software, das Ausführen von Tests auf dem Zielgerät oder das Veröffentlichen als offizielles Paket erfüllen. In Gitlab ist eine Pipeline eine Sammlung von Jobs, die in einer sequenziellen Abfolge wie folgt ausgeführt werden:

Beispiel-Pipeline

Abbildung 1: Beispiel-Pipeline, die mit dem ATmega328P DevOps-Workflow in Gitlab verwendet wird

Hier ist eine Aufschlüsselung des CI-Skripts (.gitlab-ci.yml-Datei), um Ihnen eine Vorstellung davon zu geben, wie dies funktioniert.

  • Docker: Wie in Containerizing Build and Runtime Environments for Hardware in the Loop Testing besprochen, erstellt diese Phase Docker-Images, um eine konsistente Umgebung für das Bauen, Testen und Flashen des Codes zu schaffen. Dies stellt sicher, dass der Build-Prozess auf verschiedenen Maschinen und Architekturen (wie einem Desktop-PC im Vergleich zu einem Raspberry Pi) reproduzierbar ist.
  • Test: Diese Phase führt Unit-Tests durch, um zu überprüfen, ob Ihr Code das tut, was Sie beabsichtigen. Automatisierte Tests sind schnell und wichtig, wenn bestehender Code geändert oder refaktorisiert wird.
  • Build: Diese Phase kompiliert den Quellcode in Binärdateien. In diesem Projekt werden Artefakte wie .elf- und .hex-Dateien generiert, die verwendet werden, um den ATmega328P-Chip zu flashen.
  • HIL (Hardware-in-the-Loop): Diese Phase beinhaltet das Testen der Software auf tatsächlicher Hardware, um sicherzustellen, dass sie unter realen Bedingungen korrekt funktioniert. Sie lädt die Software auf die Hardware und führt Tests durch, um die Funktionalität, die wir entworfen haben, auf dem Endprodukt zu überprüfen.
  • Deploy: Diese Phase kümmert sich um die Veröffentlichung der gebauten Artefakte in einem Paketregister, sodass sie zur Verwendung verfügbar sind.
  • Release: Diese Phase erstellt eine neue Softwareversion, automatisiert den Lieferprozess, um schnelle und zuverlässige Updates zu gewährleisten. Dies ist das, was das Produktionsteam verwenden würde, um die benötigte Softwareversion für ihre gesamte Produktmontage abzurufen.

Feinheiten

Es gibt einige kleinere Details, die diesen Workflow von einer grundlegenden DevOps-Implementierung zu einem reibungslos laufenden, gut dokumentierten und leicht zu beobachtenden System machen. Es gibt ein paar subtile Details innerhalb des CI-Workflows, die hervorzuheben sind.

  • Semantische Versionierung: Das Festlegen einer Version, sei es über einen automatisierten Mechanismus oder manuell, ist besonders wichtig für den Release-Zyklus, insbesondere bei der Arbeit mit der Produktion. Als Beispiel wird dies als Variable innerhalb des CI-Skripts festgelegt und dann in den Publish- und Release-Jobs verwendet.
  • Docker-Build-Logik: Sie werden bemerken, dass es einen Block von Logik gibt, der für die Docker-Container-Builds verwendet wird:

 


if [ "$CI_COMMIT_REF_SLUG" == "$CI_DEFAULT_BRANCH" ]; then

  export IMAGE_TAG=$CI_REGISTRY_IMAGE/$IMAGE_TYPE:latest

else

  export IMAGE_TAG=$CI_REGISTRY_IMAGE/$IMAGE_TYPE:$CI_COMMIT_REF_SLUG

fi

 

Diese Logik legt fest, dass unser „latest“ Tag nur das Docker-Image verwendet, das im Hauptzweig gebaut wurde (d.h. nachdem eine Merge-Anfrage erfolgreich durchgeführt wurde). Dies stellt sicher, dass nur erfolgreiche Merge-Anfragen das neueste und beste Docker-Image veröffentlichen, von dem jeder und jede Pipeline zieht.

  • Berichte und Abdeckung: In modernen CI-Systemen wie Gitlab können wir Test- und Abdeckungsberichte innerhalb unserer Merge-Anfragen und Pipelines extrahieren und anzeigen. Zum Beispiel haben wir in dieser Merge-Anfrage die Codeabdeckung erfasst:
Codeabdeckung innerhalb einer Merge-Anfrage

Abbildung 2: Codeabdeckung innerhalb einer Merge-Anfrage

In diesem Screenshot fasst Gitlab die Tests zusammen, die auf dem Zielhardware durchgeführt wurden:

Testzusammenfassung für Tests, die auf dem Ziel durchgeführt wurden

Abbildung 3: Testzusammenfassung für Tests, die auf dem Ziel durchgeführt wurden

Am Ende, nachdem unser Code sowohl mit Unit-Tests als auch auf dem Ziel validiert wurde, erzeugen die Veröffentlichungs- und Freigabestufen ein schönes Paket, das vom Produktionsteam verwendet werden kann:

Freigabe des Softwarepakets

Abbildung 4: Freigabe des Softwarepakets

Mit all diesen automatisierten Schritten können wir ein neues Feature iterativ auf Agile Weise freigeben. Es besteht keine Notwendigkeit, viele Features zu entwickeln, sie an die QA-Abteilung zu senden und dann eine Überprüfung für die Paketfreigabe durch das Produktionsteam. Alles hier geschieht in einem einzigen Workflow und ist vollständig automatisiert.

Fazit

In diesem Artikel haben wir untersucht, wie DevOps- und Agile-Methoden auf die Entwicklung eingebetteter Systeme angewendet werden können, speziell unter Verwendung des ATmega328P-Mikrocontrollers. Wir diskutierten die Vorteile der Implementierung eines CI-Workflows in Gitlab, zu denen Automatisierung, schnellere Build-Zeiten und effizientes Testen gehören. Indem wir das CI-Skript detailliert erläuterten und jede Phase erklärten, zeigten wir, wie man einen robusten und gestrafften Entwicklungsprozess erstellen kann, der die Effizienz und Produktqualität steigert. Indem Sie diesem praktischen Leitfaden (und dem Quellcode im Repository) folgen, sollten Sie in der Lage sein, Ihren eigenen Embedded DevOps-Workflow ebenfalls einzurichten.

Der Quellcode des Projekts kann hier gefunden werden:https://gitlab.com/embedded-designs/atmega328p-serial-led-control.

Über den Autor / über die Autorin

Über den Autor / über die Autorin

Ari ist ein PCB-Designer mit umfassender Erfahrung in der Entwicklung, Herstellung, Prüfung und Integration verschiedener Softwaresysteme. Dabei bringt er leidenschaftlich gern Entwickler aus den Bereichen Design, Prüfung und Abnahme zusammen, um gemeinsam an Projekten zu arbeiten und diese voranzutreiben.

Ähnliche Resourcen

Verwandte technische Dokumentation

Zur Startseite
Thank you, you are now subscribed to updates.