LicheePI Zero einrichten


  1. Einleitung
  2. Fertige Linux Images nutzen
  3. Linux Kernel kompilieren
    1. Compiler und Build-Toolchain vorbereiten
    2. Kernel konfigurieren und übersetzen
    3. Neuen Kernel installieren
  4. Administration per serieller Verbindung
  5. GPIO Pins
    1. Pin Funktionen
    2. Digitale Pins per sysfs ansteuern
  6. Weitere Infos

Einleitung

Wenn er hochfährt, meldet er sich als:

1 CPU:   Allwinner V3s (SUN8I 1681)
2 Model: Lichee Pi Zero
3 DRAM:  64 MiB

Der “Lichee Zero” und der “Lichee Nano” sind System-On-Chip Modelle, die ähnlich wie der Raspberry PI kleine Systeme für IOT und Thinclients bereitstellen.
Das folgende Tutorial bezieht sich auf den “Lichee Zero”. Für den Nano müssen entsprechend andere Kernel-Images genutzt werden, der Ablauf von Build und Konfiguration sollte aber recht ähnlich sein.

Lichee-Zero

Die CPU des Lichee Zero läuft zwar mit 1.2 GHz, aber mit nur 64 MB RAM liegt er weit unter den Möglichkeiten eines Raspberry PI Zero mit 512 MB RAM. Trotzdem erfüllt er alle Voraussetzungen um kleine Projekte umsetzen zu können.

Etwas mühsam mit dem Chip ist das Finden bzw. das Aufsetzen des Betriebssystems.
Denn im Gegensatz zum Raspberry PI, für den es viele Linux Distributionen gibt, muss man bei Lichee Modellen entweder sein eigenes Linux zusammenbauen, oder ein fertiges Image finden und dann nachrüsten.

Fertige Linux Images nutzen

Unter dem Link dl.sipeed.com/LICHEE findet man eine Liste von Images für unterschiedlich Lichee Varianten.

Komprimierte RAW-Disk Images befinden sich unter dl.sipeed.com/LICHEE/Zero/Images/dd_img und können nach dem Entpacken 1 zu 1 per Tools wie dd oder Win32DiskImager auf eine MicroSD Karte transferiert werden.

Wer seinen Lichee Zero mit LCD Screen ausgestattet hat, kann das Debian LXDE Image lichee_zero_test_Debian_LXDE.tar.bz2 nutzen und das System als Desktop-Umgebung nutzen.
Ansonsten bietet sich minmin_dd.tar.bz2 an, in dem außer der Paketverwaltung apt und den Linux-Basis Tools sonst nichts installiert ist.

Benötigte Software lässt sich dann per apt install nachrüsten.

Das Image arbeitet mit 2 Partitionen. Einer FAT-Boot Partition, wo das Linux Kernelimage liegt und einer EXT Partition, die während der Linux Sitzung genutzt wird.

Da bei meinem Modell die Ethernet Schnittstelle mit dem Basis-Image nicht funktioniert hat und mir Treiber für USB-LAN und WLAN Adapter gefehlt haben, musste ich den Linux-Kernel neu kompilieren, was nachfolgend beschrieben wird.

Den Linux Kernel kompilieren

Compiler und Build-Toolchain vorbereiten

Nachdem wir üblicherweise auf PCs arbeiten (X86 oder X64) brauchen wir einen Compiler für ARM Systeme um die Quellcodes richtig zu übersetzen. Diesen müssen wir erst herunterladen und installieren. Das sollte unter jeder gängigen Linux-Distribution funktionieren und sogar unter Windows 10 mit dem Subsystem für Linux durchführbar sein.

Man hat zwei Möglichkeiten:

  1. Wir installieren den Compiler über das Paketverwaltungssystem der Distribution. z.B.: sudo apt-get install gcc-arm-linux-gnueabihf
    • Vorteil: Schnelle und korrekte Installation
    • Nachteil: Version kann variieren und eventuell kommt es zu Fehlern beim Übersetzen der Quelltexte.
  2. Oder: Wir laden uns den Compiler manuell herunter und richten ihn selbst ein.
    • Vorteil: Perfekt passende Tool-Chain
    • Nachteil: Muss manuell eingerichtet werden.

GCC für ARM durch Distribution installieren

Ob eine Linux Distribution einen ARM-Crosscompiler anbietet, ist je nach Hersteller und Version verschieden.
Für uns ist wichtig, dass am Ende der Compiler mit dem Aufruf von arm-linux-gnueabihf-gcc ausgeführt werden kann.

Folgende Installationsaufrufe haben bei mir funktioniert:

  • Ubuntu und Debian: sudo apt-get install gcc-arm-linux-gnueabihf

GCC 6.3.1 für ARM Plattform manuell installieren

  1. Wir starten im Home-Verzeichnis des angemeldeten Benutzers
    cd
  2. Download eines Compilers für ARM Systeme, damit wir den Kernel kompilieren können:
    wget https://licheepizero.us/arm-linux-gnueabihf/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf.tar.xz
  3. Entpacken des Archives mit der Compiler Toolchain:
    tar xvf gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf.tar.xz
  4. Anlegen eines “zentralen” Verzeichnisses, wo wir den Compiler hinverschieben werden: sudo mkdir -m777 /opt/gcc-6.3.1_arm
  5. Verschieben der Compiler-Toolchain:
    mv gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/* /opt/gcc-6.3.1_arm/
  6. Pfad zum Compiler bereitstellen:
    • Wer den Vorgang nur einmal braucht, kann den Pfad direkt einbinden:
      export PATH="$PATH:/opt/gcc-6.3.1_arm/bin/"
    • Wer den Compiler auch in Zukunft braucht, kann ihn ins Start-Script aufnehmen:
      echo PATH="\$PATH:/opt/gcc-6.3.1_arm/bin/" >> ~/.bashrc

Hat alles geklappt, liefert der Aufruf von arm-linux-gnueabihf-gcc -v
die Version des ARM Compilers zurück und wir können mit dem Kompilieren starten.

Kernel konfigurieren und übersetzen

  1. Wir holen uns die Quelldateien von Github
    git clone https://github.com/Lichee-Pi/linux.git
    Es existieren mehrere Branches des Kernels, wobei zero-4.10 als Standard-Konfiguration übermittelt wird. Man kann also auf andere Stände per git checkout wechseln, die neueste Version 5.2 konnte ich allerdings nie zum Laufen bekommen.
  2. Nun wechseln wir ins neu angelegte Unterverzeichnis linux
    cd linux
  3. Und starten das Erzeugen der Standard-Konfiguration
    make ARCH=arm licheepi_zero_defconfig
  4. Als nächstes bauen und starten wir das Konfigurationsmenü mit:
    make ARCH=arm menuconfig
    Hier können alle möglichen Einstellungen des Kernels und das Einbinden weiterer Treiber vorgenommen werden.
  5. Nach der Konfiguration beginnt der Build-Vorgang des Kernels
    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j3
    Der Parameter -j3 lässt 3 Tasks parallel laufen, wer mehr CPU Kerne parat hat, kann die Zahl natürlich erhöhen.
  6. Danach können externe Kernel-Module gebaut werden.
    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j3 INSTALL_MOD_PATH=out modules

    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j3 INSTALL_MOD_PATH=out modules_install
    Diese Schritte sind nur erforderlich, wenn solche Module auch konfiguriert wurden.

Nachdem der Kernel fertig übersetzt wurde, sollte das neue Kernel-Image namens zImage im Unterverzeichnis linux/arch/arm/boot liegen.

Neuen Kernel installieren

Vorherigen Kernel einfach überschreiben

Hat man bereits ein fertiges SD-Karten Image, kann man einfach die erste Partition mit FAT Dateisystem mounten und die neue zImage Datei über die alte kopieren.

Unter Windows wird diese Partition als einzige erkannt und steht damit ebenfalls gleich nach Einlegen der SD Karte ins Lesegerät zur Verfügung.

Hat man Windows Services für Linux genutzt, muss man nur noch das Linux rootfs Verzeichnis auf der Festplatte finden. Es liegt unter

C:\Users\%WINDOWSUSER%\AppData\Local\Packages\ + Linux-Distributions-Paket + \LocalState\rootfs\home\$LINUXUSER\linux\arch\arm\boot

Im Fall von Ubuntu 18.04 lautet der Name des Distributions-Verzeichnisses:
CanonicalGroupLimited.Ubuntu18.04onWindows_79rhkp1fndgsc

Gesamtes Image neu erstellen

Will man das gesamte Boot Image neu erstellen, muss man auch einen neuen Stand des angepassten u-boot Bootloaders bauen und das SD-Karten Image manuell neu zusammensetzen.

Eine Anleitung für diese Prozedur befindet sich unter:

licheepizero.us/build–uboot-for-licheepi-zero

Kompliziert daran ist, dass die Daten an bestimmte Positionen der SD Karte geschrieben werden müssen und nicht einfach ins Dateisystem kopiert werden dürfen.

Bekannte Probleme

Während des Updates bzw. der Installation von Software mit apt über meinen per USB angesteckten LAN-Adapter kam es immer wieder zu Unterbrechungen der Verbindung.

Die Übertragung endete und es dauerte dann ein paar Minuten bis die Software ein Response-Timeout meldete und abbrach.

In diesem Fall half ein einfach ifdown gefolgt von einem ifup um die Netzwerkschnittstelle wieder zum Laufen zu bekommen.
apt konnte dann erneut gestartet werden und setzte dort fort, wo es zuvor abgebrochen wurde.

Das Update verlieft auf diese Weise leider sehr schleppend, am Ende konnte ich aber dennoch die Distribution auf den neuesten Stand bringen.

Administration per serieller Verbindung

Wenn der Lichee Zero ohne LCD-Panel betrieben wird, kann man ihn am einfachsten über die serielle Schnittstelle über die UART-0 PINs verwalten.

Die Linux Images nutzen diese Schnittstelle als Standard-Ein/Ausgabe und somit hat man auf einfache Weise ohne Netzwerk eine Linuxkonsole parat.

Lichee-Zero-Serial

Von unten gezählt sind der 6. und 7. linke Pin für das Empfangen und Senden von Daten bestimmt. Gegenüber stellt von unten der 9. Pin noch Ground dar, womit wir alle drei Leitungen haben, über die wir eine Kommunikation mit einem TTL-Serial-to-USB Adapter zum PC herstellen können.

Die Stromversorgung kann entweder der USB Port übernehmen, oder falls dieser für etwas anderes benutzt wird, nutzt man einfach die beiden zusätzlichen Pins gleich rechts neben der linken GPIO-Pin-Leiste, wo man am untersten Pin 5 Volt einspeisen und einen Pin darüber den Ground anlegen kann.

Unter Windows helfen uns Tools wie PuTTY um die serielle Verbindung zu nutzen und gleichzeitig die VT-100 Kommandos von Linux richtig anzuzeigen.
Man wählt die Option Serial im Konfigurationsdialog und trägt bei Serial line den COM-Port des USB-Adapters ein, z.B.: COM4. Als Geschwindigkeit nutzt der Lichee die vollen 115200 Baud, also wird dieser Wert unter Speed in PuTTY eingetragen.

PuTTY Serial

Nun wird eine bespielte MicroSD-Karte ins Gerät eingelegt und die serielle Verbindung in PuTTY gestartet. Wir der Lichee nun mit Strom versorgt werden, sollten kurze Zeit später die ersten Zeichen im Konsolenfenster erscheinen und den Linux Boot-Vorgang dokumentieren.

Die Anmeldung erfolgt mit Benutzer root und dem Passwort toortoor. Laut Doku gibt/gab es auch Images mit dem Root-Passwort licheepi. Man muss also nachlesen bzw. ausprobieren, welches Passwort zum benutzten Image passt.

GPIO Pins

Insgesamt 30 Pins kann man mit “normalen” Pinheadern versehen (2.54mm Abstand), wie man es von Arduino Systemen kennt, um Projekte daran zu betreiben.

Tatsächlich wären fast doppelt so viele verfügbar, wenn man mit den kleineren 1.27mm Pins arbeiten würde … doch dafür besitze ich keine Hardware und auch das Löten wäre bei diesen kleinen Abständen recht schwer.

PIN-Funktionen

Fast jeder PIN lässt sich als digitaler Ein- oder Ausgang nutzen. Aber wenn man I2C oder SPI nutze möchte, sollte man deren reservierte Pins unberührt lassen.

WICHTIG: Keinesfalls sollte man die letzten Pins auf der rechten Seite anfassen, denn diese laufen zur SD-Karte von der meist gebootet wird. Linux würde in diesem Fall nicht mehr auf die Karte zugreifen können und ein fataler Fehlerfall (de facto ein Absturz) bahnt sich dann an!

Den 2. SD-Karten-Slot kann man sowohl für eine Datenkarte oder auch als WLAN-Erweiterung nutzen. In diesem Fall wären auch die oberen Pins der rechten Seite Tabu.

Digitale Pins per sysfs ansteuern

Viele System-on-Chip Boards stellen ihre Pins in Linux durch das sysfs einfach im Dateisystem bereit.

  1. Man schreibt die Pin-Nummer in die virtuelle Datei
    /sys/class/gpio/export
    z.B.: echo "192" > /sys/class/gpio/export
  2. Dann geht setzt man den Pin auf Input oder Output über die direction Datei im Pin-Unterverzeichnis, namens
    /sys/class/gpio/gpioXXX/direction
    z.B.: echo "in" > /sys/class/gpio/gpio192/direction
    oder
    z.B.: echo "out" > /sys/class/gpio/gpio192/direction
  3. Nun kann man über die value Datei den Pin-Status lesen oder schreiben.
    z.B.: echo "1" > /sys/class/gpio/gpio192/value #set HIGH
    z.B.: echo "0" > /sys/class/gpio/gpio192/value #set LOW
    z.B.: cat /sys/class/gpio/gpio192/value #returns: 0=LOW, 1=HIGH
  4. Wird der Pin nicht mehr gebraucht, kann er per unexport wieder freigegeben werden.
    z.B.: echo "192" > /sys/class/gpio/unexport
1 echo "192" > /sys/class/gpio/export
2 echo "out" > /sys/class/gpio/gpio192/direction
3 echo "0" > /sys/class/gpio/gpio192/value #PIN PG0 LOW, grüne LED ein
4 echo "1" > /sys/class/gpio/gpio192/value #PIN PG0 HIGH, grüne LED aus
5 echo "192" > /sys/class/gpio/unexport

Linker PIN Header

Name Nummer Funktion Weitere Info
PE21 149 UART1_TX  
PE22 150 UART1_RX  
PB0 32 UART2_TX  
PB1 33 UART2_RX  
PB4 36 PWM0  
PB5 37 PWM1  
PB6 38 TWI0_SCK I2C / TWI
PB7 39 TWI0_SDA I2C / TWI
PB8 40 UART0_TX Serielle Konsole Senden
PB9 41 UART0_RX Serielle Konsole Empfang
PC1 65 SPI0_CLK SPI
PC3 67 SPI0_MOSI SPI
PC0 64 SPI0_MISO SPI
PC2 66 SPI0_CS SPI
    +5V 5 Volt Ausgang

Rechter PIN Header

Name Nummer Funktion Weitere Info
PG0 192 SDC1_CLK 0 → Grüne LED
PG1 193 SDC1_CMD 0 → Blaue LED
PG2 194 SDC1_D0 0 → Rote LED
PG3 195 SDC1_D1  
PG4 196 SDC1_D2  
PG5 197 SDC1_D3  
    GND Ground Ausgang
    +3V 3.3 Volt Ausgang
    KEY Referenz Spannung
PF0 160 SDC0_D1 SD-Karte
PF1 161 SDC0_D0 SD-Karte
PF2 162 SDC0_CLK SD-Karte
PF3 163 SDC0_CMD SD-Karte
PF4 164 SDC0_D3 SD-Karte
PF5 165 SDC0_D2 Letzter PIN rechts

Fortsetzung folgt…

Weitere Infos