Embedded Linux

mit Raspberry Pi und Co.

Ralf Jesse

Teil IV: Treiberentwicklung in der Praxis

Aufbauend auf den Grundlagen der Treiberentwicklung in Teil 3 enthält dieser Teil drei konkrete Beispiele für selbstentwickelte Zeichengeräte-Treiber.

Das erste Beispiel (Kapitel 11) ist dabei noch recht einfach gehalten, da hier mithilfe eines Schieberegisters vom Typ SN74HC595 einfach nur ein paar Leuchtdioden angesteuert werden. Da die Übertragung seriell erfolgt, werden deutlich weniger GPIO-Ports benötigt, als wenn die Daten parallel übertragen werden.

Das zweite Beispiel in Kapitel 12 ist schon um einiges komplexer: Um den Maxim 7219 werden Sie einen Treiber entwickeln, der in der Lage ist, LED-Matrizen von jeweils bis zu 64 Leuchtdioden anzusteuern.

Das letzte Beispiel in Kapitel 13 beschreibt den Entwicklungsprozess um einen Gerätetreiber für den HD44780, einem Controller, der für die Ansteuerung von einfachen Text-LC-Displays verwendet wird. Hier liegt der Fokus vor allem auf der Steuerung des Displaytreibers aus dem User Space heraus: Dies ist nämlich nur mit einigem Aufwand zu bewerkstelligen!

In diesem Teil:

Teil III: Grundlagen der Treiberentwicklung

Dieser Teil beschreibt die Grundlagen der Treiberentwicklung. Hier werden Sie die wichtigsten Techniken kennenlernen, die Sie für die Entwicklung eigener Gerätetreiber und Kernelmodule benötigen. Sie beginnen mit der Entwicklung einfachster Treiber für virtuelle Geräte und lernen zum Schluss die Programmierung von Treibern für »echte« Hardware.

In diesem Teil:

Teil II: Techniken zur Programmierung von Kernel und rootfs

Der zweite Teil beschreibt die Techniken, die für die Entwicklung eigener Kernel wichtig sind. Hier erfahren Sie ebenfalls, wie Sie ein angepasstes root-Dateisystem erzeugen. Um die Vorteile des Cross-Developments weiter auszubauen, wird gezeigt, wie Sie unter Einsatz von »Das U-Boot« den Entwicklungs-PC verwenden können, um von ihm über eine Netzwerkverbindung den Kernel und das root-Dateisystem auf dem Embedded System testen zu können.

In diesem Teil:

Teil I: Einführung und Einrichtung einer Entwicklungsumgebung

Der erste Teil bietet einen sanften Einstieg in die Welt der Mikrocontroller. Dabei erfahren Sie den Unterschied zwischen sogenannten Bare-Metal-Systemen und solchen Systemen, die über ein eigenes Betriebssystem verfügen. Da Embedded Systeme aufgrund eingeschränkter Ressourcen komfortables Arbeiten nahezu unmöglich machen, wird hier auf der Basis einer VirtualBox-Installation von Linux Mint eine Cross-Development-Umgebung eingerichtet. Um die auf diesem System entwickelte Software auf das Embedded System übertragen zu können, gibt es eine kurze Einführung in Samba. Ebenfalls zu den Grundlagenkenntnissen gehört die Shellprogrammierung. Auf die Auffrischung bekannter Grundlagen geht Kapitel 3 ein. Kapitel 4 befasst sich dann mit der konkreten Installation meiner Cross-Development-Umgebung.

In diesem Teil:

Impressum

Bibliografische Information der Deutschen Nationalbibliothek

Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über <http://dnb.d-nb.de> abrufbar.

ISBN 978-3-95845-063-9

1. Auflage 2016

www.mitp.de

E-Mail: mitp-verlag@sigloch.de

Telefon: +49 7953 / 7189 - 079

Telefax: +49 7953 / 7189 - 082

© 2016 mitp Verlags GmbH & Co. KG

Dieses Werk, einschließlich aller seiner Teile, ist urheberrechtlich geschützt. Jede Verwertung außerhalb der engen Grenzen des Urheberrechtsgesetzes ist ohne Zustimmung des Verlages unzulässig und strafbar. Dies gilt insbesondere für Vervielfältigungen, Übersetzungen, Mikroverfilmungen und die Einspeicherung und Verarbeitung in elektronischen Systemen.

Die Wiedergabe von Gebrauchsnamen, Handelsnamen, Warenbezeichnungen usw. in diesem Werk berechtigt auch ohne besondere Kennzeichnung nicht zu der Annahme, dass solche Namen im Sinne der Warenzeichen- und Markenschutz-Gesetzgebung als frei zu betrachten wären und daher von jedermann benutzt werden dürften.

Lektorat: Sabine Schulz

Sprachkorrektorat: Irmgard Böger

Coverbild: © Dolnikov – fotolia.com

electronic publication: III-satz, Husby, www.drei-satz.de

Dieses Ebook verwendet das ePub-Format und ist optimiert für die Nutzung mit dem iBooks-reader auf dem iPad von Apple. Bei der Verwendung anderer Reader kann es zu Darstellungsproblemen kommen.

Der Verlag räumt Ihnen mit dem Kauf des ebooks das Recht ein, die Inhalte im Rahmen des geltenden Urheberrechts zu nutzen. Dieses Werk, einschließlich aller seiner Teile, ist urheberrechtlich geschützt. Jede Verwertung außerhalb der engen Grenzen des Urheherrechtsgesetzes ist ohne Zustimmung des Verlages unzulässig und strafbar. Dies gilt insbesondere für Vervielfältigungen, Übersetzungen, Mikroverfilmungen und Einspeicherung und Verarbeitung in elektronischen Systemen.

Der Verlag schützt seine ebooks vor Missbrauch des Urheberrechts durch ein digitales Rechtemanagement. Bei Kauf im Webshop des Verlages werden die ebooks mit einem nicht sichtbaren digitalen Wasserzeichen individuell pro Nutzer signiert.

Bei Kauf in anderen ebook-Webshops erfolgt die Signatur durch die Shopbetreiber. Angaben zu diesem DRM finden Sie auf den Seiten der jeweiligen Anbieter.

Anhang E: Code::Blocks

Die Beispiele in diesem Buch wurden unter Einsatz der integrierten Entwicklungsumgebung Code::Blocks​ erstellt. Die Entscheidung für diese Entwicklungsumgebung fiel aus verschiedenen Gründen:

  1. Code::Blocks ist für Windows, Linux und Mac OS X verfügbar.

  2. Code::Blocks ist vollständig in der Programmiersprache C++ geschrieben und benötigt daher keinen Unterbau in Form einer Laufzeitumgebung, wie dies beispielsweise für NetBeans oder Eclipse erforderlich ist.

  3. Code::Blocks ist Open Source und völlig kostenlos.

  4. Ihr Einsatz ist einfach und leicht bedien- und erlernbar.

Code::Blocks kann von der Projektwebseite http://www.codeblocks.org heruntergeladen werden.

E.1  Projekteinstellungen

Die wichtigsten Projekteinstellungen – nach dem Herunterladen und der Installation einer geeigneten Cross-Toolchain – können Sie über die in Abbildung E.1 markierten Menüeinträge Build options ... und Properties ... vornehmen.

Abb. E.1: Build options ... und Properties ... einstellen

E.1.1  Properties

Wenn Sie diesen Menüeintrag anklicken, öffnet sich der in Abbildung E.2 gezeigte Dialog Project/targets options.

Alle für dieses Buch entwickelten Projekte basieren auf der Verwendung sogenannter Makefiles. Dies muss Code::Blocks explizit über die Markierung des Eintrags »This is a custom Makefile« mitgeteilt werden!

Im nächsten Reiter Build targets lassen sich die Entwicklungsziele festlegen. Unter »Entwicklungsziel« ist hier nicht zu verstehen, »ein funktionierendes Projekt zu erstellen«: Der Begriff stammt aus der Terminologie des Programms make und den Makefiles. Entwicklungsziele sind in diesem Zusammenhang eher als Etappen zu verstehen, die voneinander abhängig sind: Ein Entwicklungsschritt kann nur dann abgeschlossen werden, wenn alle Teiletappen bis zu diesem Punkt erfolgreich erreicht wurden. Standardmäßig schlägt Code::Blocks mit Release und Debug zwei Etappenziele vor, von denen mindestens eines vorhanden sein muss. Makefiles verwenden hingegen in den meisten Fällen die Ziele all (dies entspricht dem Ziel Release) und zum Aufräumen das Ziel clean. Fügen Sie diese beiden Ziele zu den Build targets hinzu und löschen Sie die Ziele Release und/oder Debug. Abbildung E.3 verdeutlicht, wie dies gemeint ist:

Abb. E.2: Project/Target options

Abb. E.3: Build targets einstellen

Die anderen Reiter in diesem Dialog werden in diesem Buch nicht benötigt und daher auch nicht beschrieben.

E.1.2  Build options ...

In den Build options ... können Sie Schritte definieren, die vor dem Starten bzw. nach Abschluss eines Übersetzungsvorgangs durchgeführt werden sollen. Wenn Sie den Erläuterungen in Anhang D gefolgt sind, können Sie hier in den Post-build steps die automatische Übertragung des Ergebnisses mit scp an das Embedded System auslösen.

Im nächsten Reiter Custom variables können Sie benutzerdefinierte Variablen festlegen, die Ihnen viel Tipparbeit abnehmen. Abbildung E.5 zeigt, dass hier die Variablen KDIR (Verzeichnis, in dem sich der Kernel-Sourcecode befindet), CC (Name der Cross-Toolchain) und ARCH (für die verwendete Prozessorarchitektur) angelegt und definiert werden.

Abb. E.4: Automatische Übertragung des Ergebnisses mit scp

Abb. E.5: Benutzerdefinierte Variablen

Im letzten Reiter legen Sie dann die Kommandos für das Programm make fest.

Abb. E.6: Kommandos für das Programm make

Alle weiteren Einstellungen – dies gilt in besonderem Maße für die Einrichtung der Cross-Toolchain – wurden bereits in Abschnitt 4.3 eingehend beschrieben, sodass dies hier nicht wiederholt werden muss.

Anhang D: Kopieren mit scp

scp​ (Abkürzung für secure copy) ist ein Tool zur gesicherten Datenübertragung zwischen zwei Computern, dem sogenannten Host- und dem Ziel-Computer (Destination). Besonders während der Cross-Entwicklung von Software werden Sie zu Testzwecken die Software vom Entwicklungs-PC auf das Embedded System (oder auch einen beliebigen anderen Computer) übertragen müssen. Um sicherzustellen, dass Sie berechtigt sind, die Daten auf das Zielsystem zu transferieren, verlangt scp von Ihnen

  1. die Bestätigung mit »yes«, dass die Datei wirklich kopiert werden soll und es sich nicht um den versehentlichen Aufruf des scp-Tools handelt.

  2. die Eingabe des Passworts des Zielsystems, mit dem Sie scp bekannt machen, dass Sie die entsprechenden Zugriffsrechte besitzen.

Auf Dauer gesehen kann dies sehr lästig werden. Dies gilt umso mehr, wenn Sie den allgemein gültigen Regeln zur Erstellung eines komplexen Passworts folgen.

Um sich den zweiten Schritt – also die Eingabe dieses Passworts – zu ersparen, können Sie auf dem Entwicklungs-PC einen privaten und einen öffentlichen Schlüssel generieren. Der Schlüssel (sowohl der private als auch der öffentliche) wird auf dem Entwicklungs-PC automatisch in der Datei /home/<Ihr Benutzername>/.ssh/ hinterlegt.

Das Schlüsselpaar habe ich auf meinem Entwicklungs-PC folgendermaßen erzeugt:

ssh-keygen -t rsa.

Dies erzeugt im Verzeichnis /home/<Ihr Benutzername>/.ssh die beiden Dateien id_rsa und id_rsa.pub. Kopieren Sie nun mit scp oder ftp die Datei mit dem öffentlichen Schlüssel (id_rsa.pub) auf das Zielsystem, zum Beispiel also den Embedded Computer. Hierfür müssen Sie das Passwort des Zielsystems natürlich noch einmal eingeben. Erweitern Sie nun den Inhalt dieser Datei mit

cat id_rsa.pub >> /home/<Ihr Benutzername>/.ssh/authorized_keys

in die Datei authorized_keys.

Ändern Sie nun die Zugriffsrechte auf diese Datei durch die Eingabe von chmod 700 authorized_keys und löschen Sie id_rsa.pub aus Ihrem /home-Verzeichnis.

Wenn Sie nun – so wie es in der Code::Blocks-Schablone hinterlegt ist – eine Datei mit scp auf das Embedded System übertragen wollen, so werden Sie nun ein letztes Mal dazu aufgefordert, auf dem Entwicklungs-PC das Passwort des Zielsystems einzugeben: Alle weiteren Übertragungen »verhandeln« die beteiligten Systeme automatisch über den Abgleich des öffentlichen mit dem privaten Schlüssel.

Anhang C: Safety und Security

Die Begriffe Safety​ und Security​ werden häufig miteinander verwechselt. Dabei behandeln sie im IT-Bereich zwei völlig verschiedene Dinge:

C.1  Security

In diesem Bereich – ich gebe es zu – bin ich kein Experte. Wenn Sie berücksichtigen, dass es zu den Kernaufgaben von IT-Abteilungen in Unternehmen zählt, interne IT-bezogene Abläufe funktionsfähig zu halten, so haben Sie bereits eine Vorstellung davon, was Bestandteil dieses großen und wichtigen Themas ist.

Die Funktionsfähigkeit eines firmeninternen Netzwerks ist heutzutage absolute Grundlage dafür, dass ein Unternehmen reibungslos arbeitet. Der Schutz vor Computerviren durch den Einsatz von Antivirenprogrammen, die Verringerung bzw. Vermeidung von Spam-Nachrichten durch geeignete Filter sowie der Schutz vor externen (und natürlich unerwünschten) Zugangsversuchen durch Cracker mithilfe von Firewalls stellen wichtige Teilbereiche im Aufgabengebiet von IT-Abteilungen dar.

Werkspionage durch externe Angreifer, aber auch durch eigene Mitarbeiter, lässt sich verhindern, indem man in geeigneter Weise Zugriffsrechte vergibt. Häufig ist es nicht einmal möglich, USB-Sticks an Arbeitsplatz-Computern zu verwenden, und auch das Drucken bestimmter Dokumente verlangt nach besonderen Berechtigungen für die entsprechenden Mitarbeiter.

Ein häufig vernachlässigter Teilbereich besonders in kleineren Unternehmen besteht in der Sicherung unternehmenskritischer Daten durch intelligente Backup-Strategien. Nicht nur die Wiederherstellung von Daten, die durch defekte Festplatten oder Computer verloren gehen, ist hiervon betroffen. Versuchen Sie einmal, einem Wirtschaftsprüfer (bzw. direkt dem Finanzamt gegenüber) verloren gegangene Daten durch ein lapidares »die Daten sind halt verloren gegangen« zu begründen: Hierzu wünsche ich Ihnen viel Erfolg und noch mehr Glück! In sehr schlimmen Fällen können solche Probleme zum Ruin eines ansonsten sehr gesunden Unternehmens führen.

Auch die Überwachung von Zugängen ist ein kritischer Bereich und gehört zum Bereich der Security.

C.2  Safety

Zum Bereich, der durch den Begriff »Safety« abgedeckt wird, gehört – wie bereits eingangs erwähnt – alles, was Schäden von Menschen und Investitionen bzw. Umwelt vermeidet bzw. die Höhe der Schaden auf ein erträgliches Minimum zurückführt. Nicht nur die Verantwortung eines Unternehmens gegenüber seinen Mitarbeitern, sondern auch das Produkthaftungsrecht sowie die Gefahr eines Imageverlusts haben in Unternehmen einen sehr hohen Standard entstehen lassen, dessen Befolgung durch Unternehmensleitungen streng überwacht wird.

Jedes moderne Kraftfahrzeug verfügt über diverse Systeme, die sich unmittelbar auf die Betriebssicherheit auswirken. Hierzu zählen nicht nur ABS, ESD oder Airbags, sondern auch Abstandswarnsysteme oder Hinweissysteme der Motorelektronik, wenn ein Mangel an wichtigen Betriebsmitteln, zum Beispiel Motoröl, vorliegt. Weitere Beispiele sind Lichtschranken, Näherungsschalter, Temperatur- und Drucküberwachungssysteme in Maschinen und Anlagen.

Diese Beispiele sind im Bewusstsein vieler Nutzer und Anwender inzwischen fest verankert. Nicht ganz so offensichtlich treten Schutzmaßnahmen beispielsweise bei der Bedienung von Maschinen in den Vordergrund: Aber auch technische Maßnahmen, die Maschinen nur im Zweihandbetrieb bedienen lassen, wobei die Bedienelemente außerhalb des Gefahrenbereichs montiert sind, sind Maßnahmen, die in den Bereich der Safety gehören. Nicht vergessen darf man auch die strengen Regeln, die in der Medizintechnik oder der chemischen Industrie zwingend zu beachten sind.

Abhängig von der Situation gibt es für alle Bereiche Normen, die zwingend einzuhalten sind und die durch Sicherheitsbeauftragte in Unternehmen überwacht und durchgesetzt werden müssen. Im Bereich der Entwicklung elektrischer, elektronischer und programmierbarer Anlagen ist beispielsweise die Norm IEC 61508​ anzuwenden.

C.2.1  Maßnahmen in der Automobilindustrie

Bereits erwähnt wurden Vorrichtungen, wie ABS, ESD, Abstandswarnsysteme usw., sodass hierauf nicht weiter eingegangen werden muss. Bei der Entwicklung von elektronischen Systemen in Kraftfahrzeugen (unter anderem Assistenz- und Steuersysteme, aber auch das als HMI bezeichnete Infotainment und natürlich die Navigation) hat sich die Verwendung von AUTOSAR​, dem Automotive-Standard für Embedded Software, durchgesetzt. Die Softwareentwicklung nach dem sogenannten V-Modell stellt hier die Grundlage der Vorgehensweise dar. Die Reihenfolge der einzelnen Schritte in vereinfachter Form lautet dort:

  1. Bedarfsermittlung (Requirements Engineering)

  2. Design (Wie und Warum)

  3. Kodieren

  4. Testen

  5. Integration (Wurden alle Anforderungen berücksichtigt?)

Die Risikoklassifizierung in der Automobilindustrie erfolgt unter anderem nach der bereits erwähnten Norm IEC 61508 sowie die auch als Automotive SIL bezeichnete Norm IEC 26262​.

C.2.2  Umsetzung in der Programmierung

Bei der Programmierung sind bestimmte Techniken vorgeschrieben und andere streng verboten. Die folgende Aufzählung ist längst nicht vollständig, sollte aber ein Gefühl für die Anforderungen hervorrufen können.

Vorgeschriebene Techniken und Empfehlungen

  • Headerdateien sollten nicht mehrfach eingebunden werden. Dies wird durch die auch in diesem Buch verwendete Schreibweise #ifndef <header>#define <header>#endif erreicht.

  • Sogenannte Vorwärtsdeklarationen​ sind zu vermeiden. Stattdessen sollten Headerdateien verwendet werden.

  • Inline-Funktionen​ sollten nur verwendet werden, wenn sie maximal zehn Zeilen Code enthalten.

  • Die Verwendung von Namespaces​ ist empfohlen. Hierdurch werden die einzelnen Bereiche innerhalb eines Softwareprojekts gekapselt (voneinander unabhängig gemacht).

  • Bevorzugen Sie die Verwendung lokaler Variablen​, vermeiden Sie die Nutzung globaler Variablen, wann immer dies möglich ist.

  • Verwenden Sie Standard-Datentypen (siehe hierzu verbotene Techniken: Verwendung von type casts​).

  • Verwenden Sie plattformunabhängige Datentypen (zum Beispiel uint8_t), da sie auf allen Plattformen den gleichen Speicherbereich belegen (zum Beispiel vier Byte unabhängig von der Prozessorarchitektur). Dies erreichen Sie durch die Einbindung der Datei unistd.h.

  • Werten Sie grundsätzlich den Rückgabewert​ einer Funktion aus.

Verbotene Techniken

  • Sie sollten niemals virtuelle Funktionen​ innerhalb von Konstruktoren aufrufen (C++).

  • Verwenden Sie möglichst kein Casting (type casts) zur Typumwandlung.

  • Wenn Sie in C++ programmieren, vermeiden Sie die Verwendung von Strukturen (Schlüsselwort struct)​: Setzen Sie struct nur ein, wenn ausschließlich passive Objekte genutzt werden. Für alles andere gibt es den Datentyp class.

C.3  Ergänzende Literatur

Anhang B: Belegung der GPIO-Ports

In den Kapiteln 4 und 10 habe ich Ihnen die Belegung der GPIO-Ports des Raspberry Pi vorgestellt. Während die Portbelegung in Kapitel 4 an die Bibliothek wiringPi von Gordon Henderson angepasst ist, zeigt Kapitel 10 die Belegung, welche die Firma Broadcom verwendet, dem Hersteller des im Raspberry Pi genutzten Mikrocontrollers. Um Ihnen lästiges Hin- und Herblättern im Buch zu ersparen, zeigt dieser Anhang noch einmal beide GPIO-Belegungen.

B.1  GPIO-Belegung gemäß wiringPi

Die hier gezeigte Belegung des Erweiterungsports entspricht der von Gordon Henderson für seine Bibliothek wiringPi verwendete GPIO-Portbelegung. Sie wird in dieser Form ausschließlich verwendet, wenn Sie wiringPi in Ihren User-Space-Anwendungen einsetzen.

Abb. B.1: GPIO-Belegung, wie sie in wiringPi genutzt wird

B.2  GPIO-Belegung gemäß Broadcom

Die Belegung des Erweiterungsports gemäß Broadcom ist die, die in diesem Buch vorrangig verwendet wird. Wichtig sind in diesem Zusammenhang die Kapitel 8, 9 und 10 sowie die Beispieltreiber, die Sie im Praxisteil Teil IV kennenlernen.

Abb. B.2: GPIO-Belegung gemäß Broadcom

Anhang A: Literaturverzeichnis

In diesem Anhang finden Sie in komprimierter Form noch einmal sämtliche Literatur (inklusive Internetadressen) zu grundlegender und weiterführender Literatur.

A.1  Embedded Systeme, Architektur etc.

A.2  VirtualBox

A.3  Samba

A.4  Shell-Programmierung

A.5  Toolchains und Bibliotheken

A.6  Bootstrapping, Buildroot etc.

A.7  Der Bootprozess

A.8  Pointer und Strukturen in C

A.9  Das Kernel-Buildsystem und Treiber

A.10  Bücher