3. Mai 2021 (Corona)

Praktische Versuche mit dem Beagle Bone Black auf „elinux-remote“

1 Rechner „elinux-remote“

Allgemeine Beschreibung

http://hhoegl.informatik.hs-augsburg.de/hhwiki/ElinuxRemote

Einloggen

Variante 1

  1. VPN zur Hochschule aufbauen

  2. ssh elinux-remote.informatik.hs-augsburg.de

    Mit RZ Zugangsdaten einloggen

Variante 2 (ohne VPN)

  1. ssh login.rz.hs-augsburg.de

  2. Vom Login Rechner aus eingeben:

    ssh elinux-remote.informatik.hs-augsburg.de

Lokaler Arbeitsbereich auf SSD

  • NICHT IM HOME-VERZEICHNIS DES RZ KOMPILIEREN!!!

  • Verwende lokale SSD Platte /home/elinux_work und /home/elinux_work2 oder ihren eigenen Rechner.

  • Jede/Jeder legt sich Arbeitsbereich an nach dem Muster

    /home/elinux_work/<nachname> + "_" + <vorname[0]>
    /home/elinux_work2/<nachname> + "_" + <vorname[0]>
    

    Beispiele:

    • /home/elinux_work/hoegl_h

    • /home/elinux_work2/schaeferling_m

Achtung: Beim Kompilieren von U-Boot, Kernel, Buildroot fallen einige Gigabyte an Daten an. Beim Kompilieren von Yocto fallen bis zu 60 GByte Daten an. Das kann dann natuerlich nicht jeder zur gleichen Zeit machen. Der Kompiliervorgang dauert im worst case auch mehrere Stunden!

2 BBB auf elinux-remote booten

  1. Einloggen auf elinux-remote

  2. Board reservieren mit bbb --reserve.

  3. Verbindung über serielle Schnittstelle herstellen. Falls Board 1 reserviert wurde z.B. eingeben:

    $ picocom -b 115200 /dev/rtlab/tty_elinux-001
    
  4. Root werden mit su - root

  5. Das Kommando reboot now eingeben.

    Alternative: bbb --erc reset

  6. Möchte man den Bootvorgang stoppen, so dass man auf dem U-Boot Prompt landet, muss man sofort nach dem reboot now Kommando auf die Leertaste drücken und drauf bleiben. Das erkennt U-Boot und bleibt auf dem Prompt (=>) stehen. Mit dem U-Boot Kommando boot startet der Linux Bootvorgang. Am Schluss wird der Linux Prompt beaglebone1 login: angezeigt.

3 U-Boot kompilieren

An Anleitungen von Robert C. Nelson halten. Er ist Applikationsingenieur bei Texas Instruments und hat praktisch das komplette Linux auf AM335x angepasst.

https://forum.digikey.com/t/debian-getting-started-with-the-beaglebone-black/12967

 sudo apt install bison

 wget -c https://releases.linaro.org/components/toolchain/binaries/6.5-2018.12/arm-linux-gnueabihf/gcc-linaro-6.5.0-2018.12-x86_64_arm-linux-gnueabihf.tar.xz
 tar xf gcc-linaro-6.5.0-2018.12-x86_64_arm-linux-gnueabihf.tar.xz
 export CC=`pwd`/gcc-linaro-6.5.0-2018.12-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-

 git clone -b v2019.04 https://github.com/u-boot/u-boot --depth=1

 wget -c https://github.com/eewiki/u-boot-patches/raw/master/v2019.04/0001-am335x_evm-uEnv.txt-bootz-n-
fixes.patch
 wget -c https://github.com/eewiki/u-boot-patches/raw/master/v2019.04/0002-U-Boot-BeagleBone-Cape-
 Manager.patch
 cd u-boot/
 patch -p1 < 0001-am335x_evm-uEnv.txt-bootz-n-fixes.patch
 patch -p1 < ../0001-am335x_evm-uEnv.txt-bootz-n-fixes.patch
 patch -p1 < ../0002-U-Boot-BeagleBone-Cape-Manager.patch

 make ARCH=arm CROSS_COMPILE=${CC} distclean
 make ARCH=arm CROSS_COMPILE=${CC} am335x_evm_defconfig
 make ARCH=arm CROSS_COMPILE=${CC}
  • Wie konfiguriert man das U-Boot?

4 Kernel kompilieren

Anleitung von R. C. Nelson: https://forum.digikey.com/t/debian-getting-started-with-the-beaglebone-black/12967

git clone https://github.com/RobertCNelson/bb-kernel
cd bb-kernel/
git checkout origin/am33x-v4.19 -b tmp

Immer wieder:
warning: konnte nicht auf '/rzhome/hhoegl/.config/git/attributes' zugreifen: Keine Berechtigung

Installieren: lzop,

./build_kernel.sh   # siehe build_kernel.log
  • Wie konfiguriert man den Kernel?

5 Vorarbeiten zum Booten ueber TFTP/NFS

Auf dem Hostrechner ist ein TFTP Server und ein NFS Server zu installieren.

Auf dem TFTP Server wird der Kernel (uImage) und der Device Tree liegen.

Auf dem NFS Server wird das Root Filesystem liegen. Der Kernel wird am Ende des Bootvorgangs das Root Filesystem ueber NFS mounten.

5.1 TFTP

Installiere „tftpd-hpa“ Server und „tftp-hpa“ Client (zum Testen).

apt install tftpd-hpa
apt install tftp-hpa
man tftpd
man tftp

systemctl status tftpd-hpa.service

Konfigurationsdatei: /etc/init/tftpd-hpa.conf

Server Verzeichnis: /srv/tftp/

Test: tftp -v 127.0.0.1 -c get <Pfad/zur/Datei>

Defaults::

$ cat /etc/default/tftpd-hpa
# /etc/default/tftpd-hpa

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="--secure"

5.2 NFS

apt install nfs-kernel-server

man nfsd
man exports
man exportfs
man nfsstat
man showmount

/etc/default/nfs-kernel-server

systemctl status nfs-kernel-server.service

/etc/exports

sudo exportfs -ra    # bei Aenderungen der /etc/exports Datei, oder Daemon
                     # restart

Beispiele fuer Eintraege in ``/etc/exports``:

   /pfad/zu/den/dateien *(rw,sync,subtree_check)
   /nfs 10.11.12.1/255.255.255.0(rw,sync,no_root_squash)
   /media/disk/avr32-work/rootfs 10.11.12.2(rw,sync,no_root_squash,subtree_check)
   /srv/ngw100     192.168.1.2(rw,no_root_squash,sync,no_subtree_check)

   /srv/bbb/rootfs    *(rw,no_root_squash,sync,no_subtree_check)    <=== Mein aktueller Eintrag

Client (zum Test):

   mount -t nfs <IP>:/pfad/zu/den/dateien /mnt
   sudo mount -t nfs 127.0.0.1:/srv/bbb/rootfs mnt/
   mount -t nfs -o nfsvers=2,nolock 10.11.12.2:/nfs /mnt

showmount -e   # show exports

6 Yocto Project, Versuch 1

Lit.:

6.1 Installation, Konfiguration und Kompilation

Auf dem elinux-remote Rechner ist bereits Miniconda installiert im Verzeichnis /opt/miniconda3. Zum Aktivieren muss die Datei /opt/miniconda3/bin/activate „gesourced“ werden:

$ source /opt/miniconda3/bin/activate

Nachher sieht man, dass sich der Shell Prompt erweitert um (base), z.B. sieht das bei mir so aus:

(base) hhoegl@elinux-remote:~$

Das drückt aus, dass das Miniconda „Base Environment“ aktiviert wurde.

Bemerkung

Python 3 installieren (Miniconda Distribution)

wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh
bash miniconda.sh

Im Normalfall wird Miniconda im Ordner ~/miniconda3 im Home-Verzeichnis installiert. Gelegentlich wird man Ja/Nein Fragen gefragt, die beantwortet man alle mit Ja. Auch die letzte Frage mit „yes“ beantworten:

Do you wish the installer to initialize Miniconda3
by running conda init? [yes|no]
[no] >>> yes

Das bewirkt, dass ein Abschnitt zum Aktivieren von Miniconda in die Datei ~/.bashrc aufgenommen wird (bitte selber nachher in .bashrc ansehen!). Alle durch Miniconda installierten Programme befinden sich in ~/miniconda3/bin. Man kann das Miniconda Environment auch manuell durch conda activate und conda dectivate aktivieren bzw. deaktivieren.

Verwende entweder Yocto Version „dunfell“ (3.1) oder „hardknott“ (3.3).

Es kann sein, dass man vorher auf dem Kompilier-Rechner noch ein paar Pakete installieren muss. Bei mir waren das:

apt install chrpath diffstat gawk

Das haengt aber von der verwendeten Distribution ab.

$ git clone -b dunfell git://git.yoctoproject.org/poky.git

$ cd poky

$ source oe-init-build-env

Neues Buildverzeichnis "build" wird angelegt.

$ cd build/

In conf/local.conf die richtige MACHINE setzen:

MACHINE ?= "beaglebone-yocto"

Kompilierung starten mit

$ bitbake core-image-base

Kompilierung dauert je nach Rechner mehrere Stunden. Es muessen auch viele Pakete aus dem Netz geholt
werden, deswegen braucht man eine gute Internetverbindung. Ein moderner 6-Kern oder 8-Kern Prozessor
und 32 GByte RAM ist empfehlenswert. Die Xeon CPU im Rechner "elinux-remote" hat 4 Kerne und ist damit
gerade halbwegs dafuer geeignet.

6.2 Erzeugte Dateien

Siehe poky/build/tmp/deploy/images/beaglebone-yocto/

6.3 Device Tree

DTB in das tftpd Verzeichnis kopieren:

sudo cp am335x-boneblack.dtb /srv/tftp

6.4 Kernel

Kernel (zImage) nach uImage umwandeln (U-Boot eigenes Format). Benoetige „mkimage“.

sudo apt install u-boot-tools

man mkimage

Allgemeiner Aufruf:

mkimage -A <arch> -O linux \
        -T kernel -C none -a <load-address> -e <entry-point> \
        -n "Linux kernel" -d arch/arm/boot/zImage uImage

Fuer BBB:

Arch: arm
Load address: 0x80800000 oder 0x82000000
Entry point:  0x80800000
(base) hhoegl@msi:~/poky/build/tmp/deploy/images/beaglebone-yocto$ mkimage \
-A arm -O linux -T kernel -C none -a 0x80800000 -e 0x80800000 -n "Linux kernel" -d
zImage uImage
Image Name:   Linux kernel
Created:      Mon May  3 20:25:50 2021
Image Type:   ARM Linux Kernel Image (uncompressed)
Data Size:    7568576 Bytes = 7391.19 KiB = 7.22 MiB
Load Address: 80800000
Entry Point:  80800000

Mit „mkimage -l“ prüfen:

(base) hhoegl@msi:~/poky/build/tmp/deploy/images/beaglebone-yocto$ mkimage -l uImage
Image Name:   Linux kernel
Created:      Mon May  3 20:36:23 2021
Image Type:   ARM Linux Kernel Image (uncompressed)
Data Size:    7568576 Bytes = 7391.19 KiB = 7.22 MiB
Load Address: 80800000
Entry Point:  80800000

Schauen Sie sich die Optionen von mkimage an. Dazu einfach ohne Argumente starten.

Danach uImage in TFTP Verzeichnis kopieren:

$ sudo cp uImage /srv/tftp/

6.5 Kernel und Busybox konfigurieren (optional)

bitbake -c menuconfig virtual/kernel

bitbake -c menuconfig busybox

bitbake -c menuconfig ???    # U-Boot, wie geht das?

6.6 Root Filesystem

Im Yocto Ausgabeverzeichnis poky/build/tmp/deploy/images/beaglebone-yocto/ folgendes Kommando aufrufen:

sudo tar jxvf core-image-base-beaglebone-yocto.tar.bz2 -C /srv/bbb/rootfs/

Damit wird das Root Filesystem im NFS Ordner des Hostrechners entpackt.

Kompletter Pfad: /home/elinux_work/hoegl_h/poky/build/tmp/deploy/images/beaglebone-yocto

6.7 U-Boot Kommandos zum Start ueber NFS

Doku: https://u-boot.readthedocs.io/en/latest

=> setenv ipaddr 192.168.178.107       # feste IP Adresse fuer BBB vergeben, oder ...
=> setenv netmask 255.255.255.0

=> setenv autoload no; dhcp;           # ... dynamische IP Adresse per DHCP holen

=> setenv serverip 192.168.178.111     # TFP/NFS Server (= Entwicklungsrechner)

Kernel Kommandozeile
=> setenv bootargs console=ttyO0,115200 root=/dev/nfs nfsroot=192.168.178.111:/srv/bbb/rootfs,nfsvers=3 rw ip=192.168.178.107

Siehe Kernel-Doku: https://www.kernel.org/doc/Documentation/filesystems/nfs/nfsroot.txt

Kernel holen per TFTP
=> tftp 0x82000000 192.168.178.111:uImage

DTB holen per TFTP
=> tftp 0x88000000 192.168.178.111:am335x-boneblack.dtb

Booten
=> bootm 0x82000000 - 0x88000000

Das Problem vom 4. Mai (RootFS konnte nicht per NFS gemountet werden) lag an der fehlenden Option ,nfsvers=3 am Ende von nfsroot=....

Brauchbare Kernel-Optionen zur Fehlersuche sind loglevel=7 sowie nfsrootdebug.

Siehe https://www.kernel.org/doc/Documentation/admin-guide/kernel-parameters.rst

7 Cross-Kompilierung

Kompilierung mit dem Compiler aus dem Debian/Ubuntu Paket „gcc-arm-linux-gnueabihf“:

apt install gcc-arm-linux-gnueabihf

Siehe C Quelltext cross/cross-compile-for-bbb.c im Repository https://gitlab.informatik.hs-augsburg.de/elinux/material. Im Quelltext steht wie man die Datei auf dem Hostrechner kompiliert. Nach dem Kompilieren wird die Binaerdatei cross-compile-for-bbb in das Root Filesystem auf dem Hostrechner /srv/bbb/rootfs/home/user/ (NFS!) kopiert.

Man kann das Programm auch mit dem Cross-Compiler aus dem Yocto SDK kompilieren! (siehe MELPv3, Kap. 6). Zunaechst das Environment sourcen mit

source /opt/poky/3.1.7/environment-setup-cortexa8hf-neon-poky-linux-gnueabi

Dann kompilieren:

$ $CC -O -o out cross-compile-for-bbb.c

8 Yocto Project, Versuch 2

MELPv3, Kap. 6

git clone -b dunfell git://git.yoctoproject.org/poky.git
source poky/oe-init-build-env
vim conf/local.conf    # MACHINE auswaehlen
bitbake core-image-minimal
bitbake-layers show-layers

Neues Layer „nova“ anlegen.

bitbake-layers create-layer nova
bitbake-layers add-layer nova
mv nova ../poky/meta-nova
bitbake-layers add-layer ../poky/meta-nova
bitbake-layers show-layers
bitbake -c listtasks core-image-minimal
bitbake -c fetch busybox
bitbake core-image-minimal --runall=fetch

Kleines Helloworld Programm anlegen

meta-nova/recipes-local/helloworld
tree recipes-local/
   recipes-local/
   └── helloworld
       ├── files
       │   └── helloworld.c
       └── helloworld_1.0.bb

bitbake helloworld
# Siehe tmp/work/cortexa8hf-neon-poky-linux-gnueabi/helloworld/1.0-r0/
# IMAGE_INSTALL_append = " helloworld"
bitbake core-image-minimal
# ls ../poky/meta*/recipes*/images/*bb

nova-image.bb anlegen:

(base) rtlabor@rtlab:~/elinux/poky/meta-nova/recipes-local$ tree .
.
├── helloworld
│   ├── files
│   │   └── helloworld.c
│   └── helloworld_1.0.bb
└── images
    └── nova-image.bb   <======

$ bitbake nova-image

SDK erzeugen

$ bitbake -c populate_sdk nova-image
# Resultat: tmp/deploy/sdk/ (selbstinstallierendes Shellskript, Ziel /opt/poky/)
$ source /opt/poky/3.1.7/environment-setup-cortexa8hf-neon-poky-linux-gnueabi
# Prefix der GNU Tools: arm-poky-linux-gnueabi-

(base) rtlabor@rtlab:~/elinux$ echo $CC
arm-poky-linux-gnueabi-gcc -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a8 -fstack-protector- strong -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/opt/poky/3.1.7/sysroots/cortexa8hf-neon-poky-linux-gnueabi

(base) rtlabor@rtlab:~/elinux$ echo $CXX
arm-poky-linux-gnueabi-g++ -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a8 -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/opt/poky/3.1.7/sysroots/cortexa8hf-neon-poky-linux-gnueabi

(base) rtlabor@rtlab:~/elinux$ echo $CPP
arm-poky-linux-gnueabi-gcc -E -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a8 -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/opt/poky/3.1.7/sysroots/cortexa8hf-neon-poky-linux-gnueabi

(base) rtlabor@rtlab:~/elinux$ echo $AS
arm-poky-linux-gnueabi-as (base) rtlabor@rtlab:~/elinux$ echo $LD arm-poky-linux-gnueabi-ld --sysroot=/opt/poky/3.1.7/sysroots/cortexa8hf-neon-poky-linux-gnueabi

Kleines C Programm übersetzen

Das C Beispiel uebersetzen
git clone https://gitlab.informatik.hs-augsburg.de/elinux/material:

$CC -O -o out cross-compile-for-bbb.c

Nur Toolchain statt komplettem SDK bauen

$ bitbake meta-toolchain

License Audit

tmp/deploy/licenses/
tmp/deploy/licenses/helloworld/

9 Echtzeit Kernel

Der Plan war, in Yocto conf/local.conf „einfach“ wie in MELPv3 Kap. 21 beschrieben die zwei Zeilen einzufuegen:

PREFERRED_PROVIDER_virtual/kernel = "linux-yocto-rt"
COMPATIBLE_MACHINE_beaglebone = "beaglebone"

Das klappt aber nicht so einfach, es gibt Fehlermeldungen. Bitte gerne nachvollziehen. Früher (bis Yocto 2.4) gab es die MACHINE „beaglebone“, ab 2.5 heisst die MACHINE „beaglebone-yocto“. Anscheinend hat der neue Name keine Möglichkeit mehr, den Echtzeit Kernel zu bauen. Der alte MACHINE Name „beagleboard“ wird jetzt im „meta-ti“ Layer verwendet. Meine Versuche, den meta-ti Layer zu aktivieren sind aber erst mal mangels umfangreicher Yocto Kenntnisse gescheitert.

Aktuelle Lösung: Kernel „zu Fuss“ kompilieren, siehe MELPv3, Kap. 4

# Toolchain holen (es geht aber auch die SDK Toolchain)
# gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf.tar.xz
https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads
# Pfad erweitern:  export PATH=$PATH:<Pfad-zur-Toolchain>
# Kernel holen
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.4.115.tar.xz

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mrproper
make ARCH=arm multi_v7_defconfig  # fuer AM335x
make -j6 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage
make -j6 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules
make -j6 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs

# Realtime Patches: 5.4.115
https://mirrors.edge.kernel.org/pub/linux/kernel/projects/rt/5.4/

wget https://mirrors.edge.kernel.org/pub/linux/kernel/projects/rt/5.4/older/patch-5.4.115-rt57.patch.gz

(base) gzip -d patch-5.4.115-rt57.patch.gz
(base) rtlabor@rtlab:~/elinux/melp-ch4-kernel/linux-5.4.115$
cat ../rt-patches/patch-5.4.115-rt57.patch | patch -p1

# make menuconfig: General Setup -> Preemption Model -> Fully preemptible

# Kernel installieren. Wie macht man das?

XXX to do: Ein paar Echtzeit-Demoprogramme übersetzen.

10 Kernelmodul/Treiber kompilieren

XXX to do

„out of tree“ kompilieren

Lit.: