Linux für den Zynq

Zynq FPGA

In diesem Artikel zeige ich euch wie ihr ein Linux Betriebssystem für den Zynq vorbereitet und dieses anschließend bootet.
Dieses Linux Betriebssystem kann anschließend mit eigener oder fertiger Hardware erweitert werden, wodurch es möglich ist den Chip flexibel an verschiedene Einsatzgebiete anzupassen.

-> Vorbereitungen:

Bevor mit der Erstellung des Betriebssystems losgelegt werden kann, müssen einige Dinge vorbereitet werden.
Für die Erstellung der notwendigen Dateien wird ein Linux Betriebssystem benötigt.
Mit folgender Software treten keine Probleme auf:

  • Ubuntu 14.04
  • Vivado 2014.3.1

Jetzt müssen noch ein paar Zusatzpakete installiert werden:

Das Programm git wird nachher verwendet um die notwendigen Dateien herunter zu laden. Alle anderen Pakete werden zum kompilieren benötigt.
Im nächsten Schritt werden drei Verzeichnisse herunter geladen:

Am Ende dieser Anleitung besitzt ihr drei verschiedene Dateien die für den Bootvorgang wichtig sind:

  1. BOOT.bin
  2. devicetree.dtb
  3. uImage

Aber bevor wir mit der Software beginnen, bauen wir uns erst einmal die Hardware…

-> Die Hardware:

Für den Anfang verwende ich ganz einfache Hardware, die nur aus dem Zynq Processing System besteht und wie folgt aufgebaut ist:

Zynq_Linux(1)
Als Konfiguration des Processing Systems verwende ich das normale XML-File von Digilent.
Zusätzlich zu der fertigen Konfiguration muss noch ein Timer aktiviert werden, da das System sonst nicht bootet und eine Fehlermeldung ausgibt (Fehler: mmc0: no vmmc regulator found):

Zynq Linux(1.1)
Sobald ihr fertig seid könnt ihr die Schaltung synthetisieren, den Bitstream erzeugen und den Bitstream ins SDK exportieren.

-> Erstellung des First-Stage-Bootloaders:

Als nächstes wird der First-Stage-Bootloader (FSBL) gebaut. Dieser Bootloader wird beim einschalten des Zynq geladen und ausgeführt. Bei der Ausführung lädt der Bootloader den Bitstream für das FPGA und aktiviert anschließend den zweiten Bootlader namens u-boot, welcher dann das Betriebssystem lädt.
Für die Erzeugung des FSBL öffnet ihr das Xilinx SDK und legt unter File / New / Application Project ein neues Projekt namens FSBL an:

Zynq_Linux(3)
Mit einem Klick auf Next wechselt ihr das Fenster und wählt Zynq FSBL aus. Die Auswahl bestätigt ihr mit einem Klick auf Finish.
Euer Projekt Explorer sieht nun wie folgt aus:

Zynq_Linux(4)
Der FSBL ist nun fertig erzeugt und für die Weiterverwendung bereit.

Hinweis: Sobald ihr Änderungen am Processing System vornehmt, müsst ihr den FSBL aktualisieren, da es sonst sein kann, dass die Änderungen nicht funktionieren!

-> u-boot kompilieren:

Im nächsten Schritt kompilieren wir u-boot. Bei u-boot handelt es sich um einen universellen Bootloader für Linux-Systeme.
Dieser Bootloader hat die Aufgabe das Betriebssystem zu laden und zu starten.
Als erstes wechselt ihr in das vorhin heruntergeladene Verzeichnis u-boot-xlnx.
In dem Unterverzeichnis /include/configs befindet sich eine Datei namens zynq_zed.h, welche ihr öffnen müsst:

Am Anfang des Headerfiles wird anschließend

eingefügt:

Jetzt kann die Datei gespeichert und geschlossen werden.
Nun wechselt ihr in das Verzeichnis u-boot-xlnx und definiert eine Systemvariable für den Cross-Compiler:

Im nächsten Schritt konfiguriert ihr u-boot:

Ihr erhaltet nun folgende Ausgabe:

Zynq_Linux(2)
Im Anschluss daran wird der Bootloader gebaut:

Nach dem Kompilieren findet ihr in dem Verzeichnis u-boot-xlnx eine Datei mit dem Namen u-boot.
Diese Datei kopiert ihr in einen neuen Ordner (z.B. mit dem Namen Linux) und benennt sie in u-boot.elf um.

-> Die Erstellung der Datei BOOT.bin:

In diesem Schritt erstellt ihr das Bootimage für den Zynq. Für diesen Schritt werden folgende drei Dateien benötigt:

  • FSBL.elf
  • System_wrapper.bit
  • u-boot.elf

Im Xilinx SDK öffnet ihr über Xilinx Tools / Create Zynq Boot Image das entsprechende Menü um das Bootimage zu erstellen.
Das Fenster füllt ihr nun wie folgt aus:

Zynq_Linux(5)
Der Zusatz (Bootloader) beim FSBL ist ganz besonders wichtig! Desweiteren müsst ihr die Reihenfolge der Dateien einhalten, sprich immer in dieser Reihenfolge:

  1. FSBL
  2. Bitstream
  3. u-boot

Mit einem Klick auf Create Image erzeugt ihr das Image. Als Resultat solltet ihr zwei Dateien namens

  • BOOT.bin
  • Zybo.bif

erhalten.
Alternativ kann das Bootimage auch über die Konsole erzeugt werden. Dazu wird eine .bif-Datei benötigt (wie die oben erzeugte Datei Zybo.bif).
Die .bif-Datei kann z.B. so aussehen:

Über den Konsolenbefehl

kann die Datei dann erstellt werden. Auf diese Weise erspart ihr euch den Umweg über das SDK und könnt es direkt in der Konsole machen.

-> Erstellen des Device Tree:

Im nächsten Schritt muss der Device Tree erzeugt werden, der die Hardware des Chips beschreibt.
Dieser Device Tree wird beim booten vom Kernel eingelesen, wodurch der Kernel weiß welche Hardware wie verfügbar ist.
Als erstes müsst ihr den Pfad des Device Tree Generators im Xilinx SDK hinterlegen.
Dazu öffnet ihr das SDK und klickt oben in der Menüleiste auf Xilinx Tools und öffnet das Menü Repositories.
Mit einem Klick auf New wählt ihr anschließend den Pfad zu dem Ordner device-tree-xlnx aus:

Zynq Linux(6)
Mit einem Klick auf OK bestätigt ihr die Eingabe.
Danach klickt ihr erneut auf File / New, nur diesmal wählt ihr das Menü Board Support Package aus. In diesem Menü wählt ihr dann device_tree und klickt auf Finish:

Zynq Linux(7)
Direkt nach dem Bestätigen öffnet sich ein neues Menü. Mit Hilfe dieses Menüs könnt ihr den Device Tree konfigurieren.
Für einen vollständigen Device Tree müssen wir noch ein paar bootargs, sprich Befehle die dem Kernel übergeben werden, hinzufügen:

  • console=ttyPS0,115200
    Zum festlegen der seriellen Konsole
  • rootfstype=ext4
    Hiermit wird festgelegt welches Dateisystem die root-Partition besitzt
  • root=/dev/mmcblk0p2
    Hier wird die root-Partition, sprich die Partition mit dem Dateisystem, festgelegt
  • rootwait
    Der Kernel soll mit dem Booten so lange warten bis die root-Partition gemountet werden kann
  • rw
    Die root-Partition soll schreib- und lesbar gemountet werden

Die Argumente werden der Reihe nach in das Feld bootargs eingetragen:

Mit einem Klick auf OK schließt ihr dann das Fenster.
Wenn ihr jetzt die Datei system.dts öffnet, sollten die Bootargumente im Device Tree stehen:

Zynq Linux(8)
Jetzt muss der Devicetree nur noch gebaut werden. Dies macht ihr mit diesem Befehl:

Beim Bauen entsteht eine Datei namens devicetree.dtb. Dies ist der fertige Device Tree den der Kernel benötigt. Diese Datei solltet ihr euch, zusammen mit der Datei BOOT.bin, in einen separaten Ordner kopieren, damit ihr sie leicht wieder findet.

Hinweis: Jede Änderung an der Hardware des FPGAs und der Processing Systems zieht eine Änderung des Device Trees mit sich, sprich ihr müsst bei jeder Änderung den Device Tree aktualisieren und neu bauen.

-> Kompilieren des Kernels:

Als nächstes müsst ihr den Linux-Kernel kompilieren:

Jetzt erscheint folgende Ausgabe:

Zynq Linux(9)
Das Kompilieren des Kernels dauert etwas länger. Sobald der Vorgang abgeschlossen wurde, findet ihr unter ../linux-xlnx/arch/arm/boot eine Datei namens uImage. Dies ist der Linux-Kernel den ihr zum booten benötigt. Auch diese Datei solltet ihr euch zu den anderen beiden Dateien kopieren.

-> Erstellen des root-Filesystems:

Im letzten Schritt wird das root-Filesystem erzeugt, welches quasi die Systempartition des Betriebssystems darstellt.
Für das root-Filesystem verwende ich das Filesystem des Yocto-Project mit einem Xilinx meta-layer.
Als erstes erstellt ihr euch einen Ordner für die notwendigen Dateien:

Im nächsten Schritt müsst ihr euch zwei Git-Repositories runterladen, einmal das  Yocto-Basisverzeichnis und dann noch den meta-layer:

Danach müsst ihr die Konfigurationsdateien erzeugen:

Jetzt müssen noch zwei Dateien angepasst werden.
Als erstes müsst ihr die Datei ../Yocto/poky/build/conf/bblayers.conf um den Xilinx meta-layer ergänzen:

Die zweite Datei ist die Datei ../Yocto/poky/build/conf/local.conf.
Dort müsst ihr das Zielsystem, für das ihr das rootfs erstellen wollt, eingeben:

Jetzt könnt ihr das rootfs bauen. Dies dauert ziemlich lange (je nach Rechner zwischen 1,5h – 3h!):

Kurz nach der Eingabe sollte folgende Ausgabe erscheinen:

Zynq Linux(10)Am Ende des Bauprozesses findet ihr unter ../Yocto/poky/build/tmp/deploy/images einen Ordner namens zedboard-zynq7.
In diesem Ordner finden sich diverse Dateien, ihr benötigt aber nur die Datei core-image-minimal-zedboard…rootfs.tar.gz, welche das gepackte rootfs enthält.

-> Die erste Inbetriebnahme:

Damit der Zynq, mitsamt des Betriebssystems in Betrieb genommen werden kann muss noch eine SD-Karte erstellt werden.
Die SD-Karte sollte idealerweise mindestens zwei Partitionen haben:

  • Partition 1: Für das Bootimage, den Kernel und den Devicetree (/boot)
  • Partition 2: Für das Dateisystem (/root)

Die Formatierung der SD-Karte habe ich nach dieser Anleitung von Xilinx durchgeführt (nur den ersten Absatz Task Descritpion).

Sobald ihr die SD-Karte vorbereitet habt, kopiert ihr die Dateien

  • BOOT.bin
  • uImage
  • devicetree.dtb

auf die boot-Partition der SD-Karte.

Das eben erstellte root-Filesystem (rootfs) wird auf die zweite Partition der SD-Karte kopiert:

Für die Konfiguration des Bootloaders erstellt ihr euch zudem noch eine Datei uEnv.txt, welche ihr auf der boot-Partition der SD-Karte speichert.
In dieser Datei wird die Konfiguration des Bootloaders abgespeichert, die wie folgt aussehen kann:

Über diese Konfiguration könnt ihr den Namen des Devicetrees und des Kernelimages ändern.
Dazu müsst ihr nur den Inhalt der entsprechenden Variablen ersetzen.

Danach kann die SD-Karte entmountet werden:

Jetzt legt ihr die Karte in das Zybo ein und stellt mit dem Jumper SD-Boot ein.
Nach dem Einschalten der Spannung könnt ihr mit Hilfe eines Terminals den Bootvorgang beobachten.
Als erstes wird der u-boot mit der übergebenen Konfiguration gestartet:

Zynq Linux(11)
Und wenig später erscheint dann der Anmeldebildschirm:

Zynq Linux(12)
Hier könnt ihr euch direkt mit dem User root anmelden.
Damit wäre das Linux-System für den Zynq einsatzbereit.

 

Dokumentation:

 

-> Zurück zum FPGA + VHDL Tutorial

4 thoughts on “Linux für den Zynq
  1. Hey,

    danke für das wirklich schön kompakte Tutorial. Leider habe ich noch ein Problem mit dem uboot. Der FSBL scheint zu funktionieren und läd auch das bitfile. Denn die DONE LED geht an. Der u-boot produziert auch einen output, leider scheint die Baudrate noch etwas krumm zu sein, denn ich seh nur Zeichenwirrwar. Ein händisches Ausprobieren aller gängigen Baudraten hat auch keinen Erfolg gebracht. Hast du noch eine Idee wo ich was drehen kann das uboot auf dem richtigen Device und mit der richtigen Baudrate sendet ?

    • Hallo Georg,

      verwendest du ein Zybo?
      Hast du im Hardwaredesigner mal das „Boarddefinition File“ (http://www.digilentinc.com/Products/Detail.cfm?NavPath=2,400,1198&Prod=ZYBO) im Processing System eingefügt? Ich könnte mir schon fast denken, dass das das Problem ist, wenn deine Baudrate nicht stimmt. Dann ist irgendwo ein Takt nicht ganz richtig.
      Ich benutze für mein Zybo eigentlich immer dieses File um die Grobeinstellung zu machen und dann ändere ich die benötigten Sachen händisch um. Aber so vergesse ich keinen Takt umzustellen etc.

      Gruß
      Daniel

    • Ok, erledigt. Copy/Paste fehler, bzw. Gehirn nicht eingeschaltet. Beim normalen Zed-Board muß die config vom u-boot natürlich nicht geändert werden

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Time limit is exhausted. Please reload CAPTCHA.