Ein Embedded-Echtzeit-Linux-System aufsetzen (Teil 1)
Anbieter zum Thema
Ein Embedded-Board, eine JTAG-Schnittstelle und freie Software – mehr braucht man nicht für ein fertiges Entwicklungssystem für Embedded-Echtzeit-Linux. Dieses Tutorial zeigt Ihnen, wie das geht.

Dieses Tutorial beschreibt, wie man von der Hardware in Form eines Embedded-Boards über JTAG (Joint Test Action Group) und den Bootloader U-Boot bis zum fertigen Embedded-Echtzeit-Linux-System kommt. Die hier vorgestellte Vorgehensweise wurde so allgemein wie möglich gehalten, um die Nachvollziehbarkeit und gegebenenfalls notwendige Abwandlungen durchführen zu können. Trotzdem wurde als Anschauungsobjekt ein konkretes Board gewählt. So kann der Leser bei Bedarf jeden einzelnen Schritt nachvollziehen.
Die erste Aufgabe besteht darin, eine Verbindung vom Entwicklungsrechner zum Zielsystem (Target) aufzubauen und damit zuerst den Bootloader zu installieren.
Dafür wurden die JTAG-Schnittstelle und darauf aufbauend OpenOCD (Open On-Chip-Debugger, im Netz unter der Adresse http://openocd.sourceforge.net/ zu finden) als Software gewählt. OpenOCD ist sowohl ein Daemon (also ein ohne User-Interface laufender Prozess) als auch die ausführende Einheit im Zusammenhang mit dem JTAG-Debugging. Bei der hier beschriebenen Vorgehensweise wird er als Interpreter von JTAG-Kommandos verwendet. Mit diesem Programm ist es deshalb möglich, den Bootloader zu debuggen und zu flashen.
Sobald der Bootloader läuft, hat man bereits Software, mit der man kommunizieren kann und die es erlaubt, den Rest des Systems aufzubauen. Der Bootloader namens U-Boot übernimmt das Starten eines provisorischen Linux-Kernels mit einer RAM-Disk sowie das Flashen des Kernels. Das Root-Filesystem wird hier durch den intermediären Kernel per RAM-Disk erstellt.
Die Beispiele in diesem Artikel beziehen sich auf ein Board von Wiesemann und Theis (pure.box2) mit einer ARM-Marvell-CPU. Es verfügt über ein Standard-ARM-JTAG-Interface, 1 Gigabyte NAND-Flash, eine serielle Schnittstelle sowie Ethernet und weitere Peripherie. Das JTAG-Interface wird mit einem JTAG-Adapter von Olimex an den USB-Port des Entwicklungsrechners angeschlossen.
Der dafür eingesetzte Chip ist der weit verbreitete Mikrocontroller FTDI-2232. Zwischen dem Board und dem verwendeten JTAG-Adapter ist ein Flachbandkabel mit einer 26-poligen zweireihigen Buchsenleiste (2,54 mm) auf eine 20-polige Steckerleiste (2,00 mm) notwendig, das sich einfach herstellen lässt. Die PIN-Belegung entspricht dem ARM-Standard und muss nicht geändert werden.
Die JTAG-Verbindung zum Zielsystem aufbauen
Auf Seiten des Entwicklungsrechners muss die USB-Seite des JTAG-Adapters angesprochen werden können. Dafür wird OpenOCD verwendet. Dieser Dämon kommuniziert mit dem JTAG-Adapter auf der einen Seite und bietet auf der anderen Seite folgende Server-Socket-Schnittstellen als Interface:
- Terminal (Port 4444) – Interaktive Schnittstelle zur Verwendung von JTAG
- Debugger (Port 3333) – Schnittstelle mit mi-Protokoll zur Verwendung durch den GNU-Debugger gdb.
Die JTAG-Verbindung zum Zielsystem erfolgt von OpenOCD über den USB-Treiber für FTDI-Chips namens libftdi zum JTAG-Adapter. Dieser steht unter der Adresse http://www.intra2net.com/en/developer/libftdi/download.php im Netz.
Zwingende Voraussetzung für libftdi ist die Bibliothek libusb für den systemübergreifenden USB-Zugriff, die zuerst installiert sein muss. Danach kann die Treiberbibliothek libftdi aus dem Internet geladen und installiert werden:
cd /home/linux/inst-wut
tar -xvzf libftdi-0.19.tar.gz
cd libftdi-0.19
./configure --prefix=/usr
make
make install
Anschließend wird der Open On-Chip-Debugger OpenOCD aus dem GIT-Repository geholt, erstellt und mit dem folgenden Skript installiert:
cd /home/linux/inst-wut
git clone
git://openocd.git.sourceforge.net/
gitroot/openocd/openocd
cd openocd
./bootstrap
./configure --enable-maintainer-mode
--enable-ft2232_libftdi
--prefix=/usr
make
make install
Die Konfiguration des Daemons OpenOCD ausführen
Die Installation von OpenOCD erfolgte im Verzeichnispfad /usr/share/openocd/. Im Unterverzeichnis scripts/board der OpenOCD-Installation befinden sich bereits vorgefertigte Skripte für eine ganze Reihe an Boards. Selbstverständlich wird man in aller Regel versuchen, ein vorhandenes Skript zu verwenden und dieses so zu modifizieren, dass es zum jeweils gerade verwendeten Board passt.
Zweckmäßig ist es, sich hierzu das entsprechende Skript ins Arbeitsverzeichnis unter dem Namen openocd.cfg zu kopieren, dann wird es als Default-Skript verwendet, z. B.:
cp /usr/share/openocd/scripts/
board/sheevaplug.cfg
/home/linux/inst-wut/openocd.cfg
In dem vorgefundenen und verwendeten Skript sind einige Anpassungen notwendig, zuvorderst:
CPU-Architektur (source cpu/...)
JTAG-Interface (source interface/...)
JTAG-Geschwindigkeit (jtag_khz)
Notwendige Register-Einstellungen (mww ...) für boardspezifische Initialisierungen in der Prozedur sheevaplug_init(); diese wird in wut_init() umbenannt
OpenOCD installiert eine ausführliche Dokumentation, die beispielsweise mit der folgenden Zeile eingesehen werden kann:
info openocd
Auf der Homepage des Autors ist das angepasste Konfigurationsskript erhältlich.
Start und Verwendung des Daemons OpenOCD
Zur Verwendung von OpenOCD sind zwei bzw. drei Terminals notwendig:
- Start des OpenOCD-Dämons in einem Terminal-Fenster
- Verbindung mit dem Dämon zur Kommando-Eingabe als Socket-Client (netcat)
- Verbindung des gdb mit dem Dämon zum Debuggen.
Der Dämon wird mit der folgenden Zeile gestartet:
openocd
Zur standardmäßigen Konfiguration wird die ins Arbeitsverzeichnis kopierte Datei openocd.cfg verwendet. Wenn sich der Dämon nicht beendet, dann ist eine Verbindung vorhanden. Erscheinen dagegen beim Start des Daemons Fehlermeldungen, dann kommen folgende typische Ursachen in Betracht:
- Das falsche Device-ID vom Interface-Adapter (USB-JTAG-Umsetzer) wird erkannt;
- Gegebenenfalls ist die JTAG-Geschwindigkeit zu hoch eingestellt (jtag_khz) ;
- Oder es ist ein falscher Adapter-Typ angegeben (source interface/...);
- Ein falscher oder unpassender CPU-Typ ist eingestellt (source cpu/...);
- Die Bibliothek libftdi kann nicht benutzt werden;
- Gegebenenfalls wird OpenOCD unter einem nicht privilegierten User ausgeführt (Tipp: User root verwenden);
- Die JTAG-Belegung zwischen dem Adapter und dem Target passt nicht; als eventuelle Ursache kommt ein wackeliger Kontakt in Frage.
In einer weiteren Shell wird das Socket-Terminal-Programm netcat oder auch kurz nc gestartet:
netcat localhost 4444 oder
nc localhost 4444
Hier können Befehle von OpenOCD eingegeben oder auch eigene Prozeduren aus der Konfigurationsdatei aufgerufen werden. Zur Orientierung kann man einfach
> help
> help [Kommando]
eingeben und sich die Kurzbeschreibung der eingebauten Befehle anschauen.
Die OpenOCD-Konfiguration einrichten
Für die boardspezifischen Initialisierungen legt man sich zweckmäßig eine Prozedur in der Konfigurationsdatei openocd.cfg an. In dieser Datei werden das JTAG-Interface zurückgesetzt sowie die Register der CPU richtig eingestellt. Ein Beispiel dafür befindet sich in der Konfigurationsdatei sheevaplug.cfg als Prozedur sheevaplug_init. Wir verwenden diese Prozedur als Ausgangspunkt und nennen unsere wut_init.
Nach dem Start von OpenOCD können wir diese Prozedur im Kommando-Terminal direkt aufrufen: > wut_init
Den Bootloader können wir bei bestehender JTAG-Verbindung jetzt ganz einfach testen. Die Erstellung des Bootloaders wird im zweiten Teil des Tutorials beschrieben. Vom Entwicklungsrechner ins RAM auf dem Target kopieren wir ihn mittels:
> load_image /home/linux/u-boot/u-boot
Dieser Aufruf gibt die Adresse zurück, an die der Bootloader kopiert wurde. Nun können wir die Ausführung an der entsprechenden Adresse fortsetzen:
> resume 0x600000
Soll der Bootloader debugged werden, so wird einfach eine Instruktion an der betreffenden Adresse ausgeführt:
> step 0x600000
Die Ausführung hält an und man kann sich von einem anderen Terminal aus mit dem Debugger gdb verbinden. Die Ausgaben des Bootloaders sollten über eine serielle Schnittstelle sowie einer Terminal-Emulation sichtbar sein.
Debugging der JTAG-Verbindung
Zum JTAG-Debuggen mittels OpenOCD startet man ein eigenes Terminal und wechselt in das Verzeichnis des Bootloaders:
cd /home/linux/u-boot
Dort kann der Debugger aus der Cross-Development-Toolchain mit der folgenden Zeile gestartet werden:
arm-linux-gdb ./u-boot
Nun muss man sich mit dem Target verbinden. Als Übermittler fungiert hier der Daemon OpenOCD:
(gdb) target remote localhost:3333
Jetzt kann das Debuggen beginnen, beispielsweise folgendermaßen:
(gdb) b start_armboot Breakpoint
(gdb) c Continue --> Target läuft
(gdb) n Zeile überspringen
(gdb) s Hineinspringen
(gdb) p abc Variable ausgeben
...
Zum Testen des Bootloaders verbindet man sich durch ein serielles Nullmodemkabel mit dem Board und startet in einer weiteren, neuen Shell ein Terminalprogramm:
minicom -s
(Schnittstelle einstellen: 115,2k 8N1, kein Handshake)
Den Bootloader auf das Flash schreiben
Nachdem der Bootloader funktioniert und alle Probleme beseitigt sind, kann dieser persistent auf das Flash geschrieben, sprich geflashed werden. Dies erfolgt im Kommando-Terminal durch Initialisieren der Hardware, Erasen und Beschreiben des Flash:
> wut_init
> nand probe 0
> nand erase 0 0x0 0x100000
> nand write 0 /home/linux/u-boot.kwb
0x0 oob_softecc_kw
Im Kommandoterminal von OpenOCD startet man den Bootloader mit folgendem Befehl:
> resume
Wenn der Bootloader durchstartet, kann das JTAG-Interface vom Board getrennt und erneut gestartet werden.
* Andreas Klinger ist selbstständiger Diplom-Ingenieur (FH) und bietet Seminare zu Embedded- und Echtzeit-Linux an. Er ist außerdem beliebter Referent der Embedded Linux Woche. Kontakt: ak@it-klinger.de
:quality(80)/images.vogel.de/vogelonline/bdb/1404000/1404039/original.jpg)
Ein Embedded- Echtzeit-Linux-System aufsetzen, (Teil 2)
(ID:31572750)