Links:
Home Embedded Linux

Downloads

Linux-Treiber entwickeln

Moderne Realzeitsysteme kompakt

Embedded Linux lernen mit dem Raspberry Pi

Hinweise, Ergänzungen und Fehlerkorrekturen




Kapitel 3.1 Der Linux-Kernel, Textfehler auf Seite 38, Tabelle 3-1

In der Tabelle 3-1 sind die Targets "allnoconfig" und "allyesconfig" vertauscht.



Fehlerbild selbst gebautes System: Über die Tastatur sind keine Eingaben möglich.

Kapitel 3.1 Der Linux-Kernel

Aktuelle Linux-Kernel aktivieren in der Minimalkonfiguration keine Tastatur und auch keine Maus mehr. Überprüfen Sie daher in der Kernel-Konfiguration, ob die Option [Device Drivers][Input device support][Keyboards][AT keyboard] (Tabelle 3.1) gesetzt ist.



Fehlerbild selbst gebautes Raspberry-System: Netzwerk wird beim Booten nicht automatisch hochgefahren, obwohl in /etc/rcS die Befehle ifconfig oder udhcpc vorkommen.

Mögliche Ursache:

Der Ethernet-Controller des Raspberry Pi ist über USB angeschlossen und benötigt zur Initialisierung einige Sekunden. Daher müssen Sie vor Ausführung der Befehle eine Schlafenszeit von mindestens zwei Sekunden einfügen. Falls das entsprechende Kommando "sleep" vorhanden ist, haben Sie möglicherweise in der Busybox-Auswahl vergessen, das Kommando auch zu konfigurieren?



Fehlerbild selbst gebautes System: Das Kommando "free" oder "cat /proc/meminfo" zeigt nur 128 MByte an, obwohl der verwendete Raspberry Pi ein Model B ist

Ursache:

Das liegt an der Bootloader-Installation. Der Bootloader übergibt dem Kernel in Form von Bootparametern die vorhandene Speichergröße. Um (auf die Schnelle) die korrekte Größe zu bekommen, verwenden Sie die Bootloader-Installation von Raspbian.




Kapitel 3.2 Das Userland, S. 47, Schritt 8

Fehlerbild: Das Kommando "rsync -a ..." schlägt mit folgender Meldung fehl:"

rsync: failed to set times on "/home/quade/embedded/qemu/userland/loop/.": Operation not permitted (1)
rsync: symlink "/home/quade/embedded/qemu/userland/loop/linuxrc" -> "bin/busybox" failed: Permission denied (13)
rsync: recv_generator: mkdir "/home/quade/embedded/qemu/userland/loop/bin" failed: Permission denied (13)


Abhilfe: Starten Sie "rsync" mit Hilfe von "sudo" mit Superuser-Rechten (ein Dankeschön für den Hinweis an Simon A.):
quade@felicia:~/embedded/qemu/userland> sudo rsync -a busybox-1.21.1/_install/ loop



Kapitel 3.2 Das Userland

Fehlerbild: "can't run '/etc/rcS': No such file or directory"
'/etc/rcS' ist dabei vorhanden und ausführbar. Der Aufruf von '/etc/rcS' im Terminal schlägt fehl, in der Variante '/bin/ash /etc/rcS' funktioniert es dagegen, danach kann das Skript sogar direkt ausgeführt werden.
Fehlerbild can't run '/etc/rcS'

Abhilfe: Starten Sie das Skript (Seite 57 unten) über die Shell. Nehmen Sie die folgende Inittab (ein Dankeschön an Jens Stadelmann):

::sysinit:/bin/ash /etc/rcS
::askfirst:/bin/ash



Kapitel 3.2 Das Userland

Fehlerbild: Der Webserver startet nicht

Mögliche Ursache:

Im Skript '/etc/rcS' fehlt die Zeile "httpd -c /etc/httpd.conf". Siehe hierzu Seite 61 vorletzter Spiegelstrich, respektive hier eine verbesserte Version von Beispiel 3.7 (S. 62), die die Änderung in rcS berücksichtigt (ein Dankeschön an Ingo Kiehl):

quade@felicia:~/embedded/qemu>cd userland/target/
quade@felicia:~/embedded/qemu/userland/target> gedit rcS &
    # Folgende Zeile anfügen:
    httpd -c /etc/httpd.conf
quade@felicia:~/embedded/qemu/userland/target> gedit index.html &
quade@felicia:~/embedded/qemu/userland/target> gedit ps.cgi &
quade@felicia:~/embedded/qemu/userland/target> gedit httpd.conf &
quade@felicia:~/embedded/qemu/userland/target> cd ../busybox-1.21.1/
quade@felicia:~/embedded/qemu/userland/busybox-1.21.1> make menuconfig
...
# [Networking Utilities][httpd] Webserver zur Auswahl hinzufügen
...
quade@felicia:~/embedded/qemu/userland/busybox-1.21.1> make
quade@felicia:~/embedded/qemu/userland/busybox-1.21.1> make install
quade@felicia:~/embedded/qemu/userland/busybox-1.21.1> cd ../..
quade@felicia:~/embedded/qemu> gedit mkrootfs.sh &
quade@felicia:~/embedded/qemu> ./mkrootfs.sh # System generieren
quade@felicia:~/embedded/qemu> ./start_el.sh # System testen



Kapitel 3.2 Das Userland (Qemu-Version)

Fehlerbild: Das System bootet, aber es gibt keine Eingabeaufforderung (Shell)

Mögliche Ursache:
Sie verwenden einen 64-Bit Kernel, das Userland ist aber für 32-Bit generiert und dem Kernel fehlt die 32-Bit Unterstützung.

Abhilfe:
Bauen Sie einen Kernel, der die Option

CONFIG_IA32_EMULATION
gesetzt hat:
[Executable file formats / emulations][IA32 Emulation]



Kapitel 3.2 Das Userland

Fehlerbild: Das selbstgebaute System bekommt per UDHCPC keine IP-Adresse zugewiesen (DHCP-Server ist ok)

Mögliche Ursache:

  • Im Rootfilesystem fehlt die Datei "/etc/simple.script"
  • Die Datei "/etc/simple.script" wird vom udhcpc nicht ausgeführt. Möglicherweise wurde in der Busybox-Konfiguration keine Alias-Shell für "/bin/sh" ausgewählt.

Abhilfe:
  • Installieren Sie die Datei "/etc/simple.script" (siehe Buch S. 71).
  • Passen Sie die Busybox-Konfiguration an (siehe Buch S. 45, Tabelleneintrag "Shells").



Kapitel 3.2 Das Userland

Fehlerbild: Die Seite ps.cgi wird nicht angezeigt

Mögliche Ursache:
Der Http-Server "httpd" findet keine Shell, um das Skript zu starten.

Abhilfe: Modifizieren Sie "/etc/httpd.conf" (beziehungsweise "userland/target/httpd.conf") so, dass anstelle von "/bin/sh" "/bin/ash" aufgerufen wird (ein Dankeschön an Ralf):

H:/var/www
*.cgi:/bin/ash



Kapitel 3.3 Seite 69*

Buildroot nutzt ab Version 2013.11-rc1 die Konfiguration 'raspberrypi_defconfig' anstelle von 'rpi_defconfig'. Der Aufruf muss also

make raspberrypi_defconfig
lauten (Dank an Marvin R.).


Kapitel 3.3 Seite 69*, die Generierung der Toolchain schlägt fehl

Für die Generierung wird g++ benötigt. Am besten installieren Sie das Paket build-essential (Dank an Marvin R.):

sudo apt-get install build-essential



Kapitel 3.3.2 Cross-Generierung Userland

Fehlerbild: Kein Zugriff auf eine Shell über die serielle Schnittstelle

Bei vom Buch abweichenden (neueren) Versionen des Kernels und der Busybox gibt es unter Umständen keinen Zugriff auf eine Shell über die serielle Schnittstelle.

Abhilfe: Die manuelle Generierung der Gerätedateien im mkrootfs-Skript weglassen (Dank an Markus M.).



Kapitel 3.4 Das U-Boot

Fehlerbild: "** Unrecognized filesystem type **"

Fehlerbild: "** No partition table - mmc 0 **"

U-Boot ist leider sehr empfindlich bezüglich der verwendeten SD-Karten und kann auf viele Typen nicht zugreifen.
Abhilfe:

Fehlerbild 'Unrecognized filesystem type'

U-Boot auf dem Raspberry Pi mit dem Mainline-Kernel

U-Boot ist mit den meisten SD-Karten in folgender Kombination einzusetzen:

  • U-Boot in der Version von Stephen Warren
  • Aktueller Mainline-Kernel (getestet 3.17.0-rc1)
    • Konfiguration angepasst
    • Unterstützung für Device-Trees

Im Folgenden werden die Kommandos gezeigt, um den aktuellen Kernel per U-Boot zu laden. Als Rootfilesystem wird das Filesystem auf der SD-Karte verwendet. Voraussetzung ist, dass Sie einen ARM-Compiler per Buildroot installiert haben (siehe PATH). Die SD-Karte ist auf dem Hostsystem unter /media/quade/boot/ gemountet.

Den Linux-Kernel zImage und das U-Boot Binary u-boot.bin finden Sie übrigens vorgeneriert auf der Download-Seite unter Kapitel 3.4.

#
# Vorbereitung
#
cd ~/embedded/raspi/bootloader
#
#
# U-Boot von Stephen Warren herunterladen und generieren
#
git clone git://github.com/swarren/u-boot.git
cd u-boot/
git checkout -b rpi_dev origin/rpi_dev
#
export PATH=$PATH:/home/quade/embedded/raspi/buildroot-2013.05/output/host/usr/bin
make CROSS_COMPILE=arm-linux- distclean
make CROSS_COMPILE=arm-linux- rpi_b_config
make CROSS_COMPILE=arm-linux- u-boot.bin

cp u-boot.bin /media/quade/boot/
vi /media/quade/boot
     # In der letzten Zeile "kernel=u-boot.bin" eintragen

#
# Kernel herunterladen, konfigurieren und generieren
#
cd ~/embedded/raspi/
mkdir mainline-linux
cd mainline-linux
#
# Auspacken
#
wget https://www.kernel.org/pub/linux/kernel/v3.x/testing/linux-3.17-rc1.tar.xz
tar xvf linux-3.17-rc1.tar.xz
...
cd linux-3.17-rc1
#
# Konfigurieren
#

export ARCH=arm
export CROSS_COMPILE=arm-linux-
make bcm2835_defconfig

make menuconfig
[Device Drivers][USB support --->][DesignWare USB2 DRD Core Support]
[Device Drivers][USB support --->][Host only mode]
[Device Drivers][USB support --->][DWC2 Platform]
#
# Kernel Generieren
#
make -j 4 zImage
#
# Device-Tree generieren
#
make -j 4 dtbs
#
# Generierten Dateien (Kernel+Device-Tree) entweder direkt auf die
# SD-Karte oder bei Netzwerk-Boot ins Verzeichnis des
# TFTP-Servers kopieren.
#
cp arch/arm/boot/zImage /var/lib/tftpboot/
cp arch/arm/boot/dts/bcm2835-rpi-b.dtb /var/lib/tftpboot/

# Bootscript erstellen
cd ~/embedded/raspi/bootloader/
vi boot-net.txt
# folgendes eingeben, IP-Adressen unbedingt anpassen!
    usb start
    dhcp 00200000 192.168.69.71:zImage
    tftpboot 00100000 192.168.69.71:bcm2835-rpi-b.dtb
    setenv bootargs console=ttyAMA0 console=tty1 root=/dev/mmcblk0p2 rootwait
    bootz 00200000 - 00100000
# Skript generieren
# Stephen verwendet "boot.scr.uimg" als Default!
arm-linux-mkimage -A arm -O linux -T script -C none -d boot-net.txt boot.scr.uimg
cp boot.scr.uimg /media/quade/boot/

SD-Karte in den Raspberry Pi stecken und booten. Eventuell den Bootprozess unterbrechen und Kommandos einzeln an der seriellen Konsole austesten.




Kapitel 3.4 Das U-Boot, S. 82, Beispiel 3-16

Fehlerbild: Der Kernel lässt sich nicht starten
U-Boot bleibt mit der Meldung "Starting Kernel" hängen.
Abhilfe:
Verwenden Sie eine andere Adresse im Adressraum des Pi als 00008000 (Danke Ralf und Guy):

U-Boot> fatload mmc 0:1 00200000 uimage
U-Boot> bootm 00200000



Kapitel 3.5 Initramfs: Filesystem im RAM

Auf Seite 89 unten, Schritt 3: '... | gzip -9) >initramfs.cpio.gz' ist die schließende Klammer falsch. Korrekt lautet die Zeile (Danke an Ralf):

find . | cpio -o -H newc | gzip -9 >initramfs.cpio.gz



Kapitel 3.5 Initramfs: Filesystem im RAM, Beispiel 3-20

Fehlerbild: mkrootfs.sh meldet:

rsync: failed to set times on "~/embedded/raspi/userland/loop/.": Operation not permitted (1)

Abhilfe:
Auf Seite 90, in Beispiel 3-20 fehlt vor dem Befehle "rsync..." ein "sudo" (Danke an Ralf):
sudo rsync -a busybox-1.21.1/_install/ loop


Kapitel 4.2 Buildroot-Praxis

Auf Seite 101: Nach dem Extrahieren von 'buildroot-2013.05.tar.bz2' und vor dem Aufruf von 'make rpi_defconfig' muss erst in das Verzeichnis 'buildroot' gewechselt werden (Danke an Ralf):

quade@felicia:~> cd ~/embedded/raspi
quade@felicia:~/embedded/raspi> sudo apt-get install git
quade@felicia:~/embedded/raspi> wget http://www.buildroot.net/downloads/buildroot-2013.05.tar.bz2
quade@felicia:~/embedded/raspi> tar xvf buildroot-2013.05.tar.bz2
quade@felicia:~/embedded/raspi> cd buildroot-2013.05
quade@felicia:~/embedded/raspi/buildroot-2013.05> make rpi_defconfig
quade@felicia:~/embedded/raspi/buildroot-2013.05> make menuconfig
# Für die serielle Schnittstelle wählen Sie ttyAMA0 an Stelle von tty1
# aus
#     [System configuration][(ttyAMA0) Port to run a getty (login
#     prompt) on]
# Abwählen des Paketes rpi_firmware
#     [Package Selection for the target][Hardware handling]
#     [Misc devices firmwares][rpi-firmware]
# Abwählen des Paketes rpi_userland
#     [Package Selection for the target][Hardware handling]
#     [rpi-userland]
quade@felicia:~/embedded/raspi/buildroot-2013.05> make


Kapitel 4.3 Systemanpassung, S. 114

Im Text heißt es korrekterweise, dass der Name des Skripts inklusive Pfad unter dem Auswahlpunkt [System configuration][Custom scripts to run before creating filesystem images] mit dem Inhalt "../scripts/postbuild.sh" einzutragen ist. In der nachfolgenden Befehlsliste ist aber fehlerhafterweise "after" statt "before" abgedruckt (Dank an Patrick R.). Richtig lautet es:

quade@felicia:~/embedded> cd ~/embedded/raspi/scripts/
quade@felicia:~/embedded/raspi/scripts> gedit postbuild.sh &
# Template anlegen
quade@felicia:~/embedded/raspi/scripts> chmod +x postbuild.sh
quade@felicia:~/embedded/raspi/scripts> cd ../buildroot-2013.05/
quade@felicia:~/embedded/raspi/buildroot-2013.05> make menuconfig
# [System configuration][Custom scripts to run before creating
# filesystem images]
# ../scripts/postbuild.sh


Kapitel 4.3 Systemanpassung, S. 117, Beispiel 4-6

Im Skript 'postbuild.sh' muss es anstelle von '.../S41dhcpc' '.../S41udhcpc' lauten (Danke an Ralf).

# MARK A: Netzwerk starten
echo "Netzwerk starten..."
install -m 755 ../userland/target/S41udhcpc $1/etc/init.d/

# MARK B: Zeit setzen
...


Kapitel 4.3 Systemanpassung, S.124, Ergänzung zu 'postbuild.sh'

Wird das Skript 'postbuild.sh' mehrfach aufgerufen meldet 'mkdir' einen Fehler, da die Verzeichnisse bereits existieren. Außerdem werden die Einträge in '$1/etc/fstab' mehrfach angelegt (Danke an Ralf).

Abhilfe:
Bei 'mkdir' die Option '-p' ergänzen, die Veränderung in der fstab nur dann vornehmen, wenn diese noch nicht getätigt wurden.

# MARK C: SD-Karte einhaengen
mkdir -p $1/boot
mkdir -p $1/data
if ! grep "/dev/mmcblk0p" -q $1/etc/fstab; then
    echo "/dev/mmcblk0p1 /boot  vfat  defaults  0   0" >> $1/etc/fstab
    echo "/dev/mmcblk0p2 /data  ext4  defaults  0   0" >> $1/etc/fstab
fi


Kapitel 4.3 Systemanpassung (dropbear, ssh), 'PTY allocation request failed on channel 0 shell request failed on channel 0'

Der Versuch, sich per SSH auf dem Raspberry Pi einzuloggen scheitert mit der Fehlermeldung:

PTY allocation request failed on channel 0
shell request failed on channel 0

Ursache:
In der Busybox-Konfiguration (im Buildroot-Verzeichnis 'make busybox-menuconfig]) ist der Menupunkt [General Configuration][[Use the devpts filesystem for Unix98 PTYs] nicht ausgewählt.



Kapitel 4.4 Eigene Buildroot-Pakete, S.140/141

Fehlerbild: Beim Versuch das Programm "hello" auf dem Raspberry Pi zu starten kommt die Meldung:

/usr/bin/hello: line 1: syntax error: unexpected "("

Abhilfe:
Die Ursache für die Meldung liegt darin, dass auf dem Image eine Version des Programms "hello" kopiert wurde, die für das Host-System, also die x86-Plattform compiliert wurde. Dass das der Fall ist können Sie dadurch feststellen, dass Sie in das Verzeichnis ~/embedded/raspi/buildroot-2013.05/output/target/usr/bin wechseln und dort das Kommando "file hello" aufrufen. Falls hier

hello: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV),
dynamically linked (uses shared libs), for GNU/Linux 2.6.24,
BuildID[sha1]=4feef3a009967f188f729f22e87e915699538705, not stripped
erscheint, handelt es sich um die falsche Version. Löschen Sie zur Lösung des Problems die generierte Datei hello durch "make clean" und lassen Sie dann das Paket komplett neu generieren (im Buildroot-Verzeichnis "make hello-dirclean" und "make" aufrufen). Hier noch einmal die Kommandos für das Hostsystem in der Zusammenstellung (Danke an Jakob):
     cd ~/embedded/application/hello-20130901/
     make clean
     cd ~/embedded/raspi/buildroot-2013.05/
     make hello-dirclean
     make



Kapitel 5.3 Hardwarezugriffe, Textfehler auf Seite 159, Beispiel 5-8

Im Beispiel 5-8 muss die Zeile

    fd_flags~= O_NONBLOCK; /* nicht blockierenden Modus einschalten */
geändert werden in
    fd_flags&= ~O_NONBLOCK; /* nicht blockierenden Modus einschalten */
(Dank an Ralf)

Kapitel 6.1.2 Aufbau eines Gerätetreibers, Textfehler auf Seite 170, letzter Absatz

Im Text wird der Systemcall "write()" und die Treiberfunktion "driver_write()" erwähnt. Tatsächlich handelt es sich aber um "read()" und "driver_read()". (Dank an Ralf)



Beispiele 6-1, 6-6, 6-10, Verbesserungsvorschlag

Werden die Treiber auf Systemen gestartet, die keine Udev-Unterstützung bieten, wird das Laden der Treiber mit der Fehlermeldung "no udev support" abgebrochen. Um die Treiber dennoch laden zu können, wird in der Funktion "mod_init" nach Aufruf von "class_create" die Zeile "goto free_cdev;" auskommentiert. In der Funktion "mod_exit" wird außerdem das Klassen- und des Geräteobjekt nur dann freigegeben, wenn diese zuvor alloziert wurden. Damit der Treiber verwendet werden kann, müssen die zugehörigen Gerätedateien per "mknod" selbst angelegt werden.

hello_class = class_create( THIS_MODULE, "Hello" );
if( IS_ERR( hello_class ) ) {
    pr_err( "hello: no udev support\n");
    //goto free_cdev; // HIER AUSKOMMENTIEREN
}
...
static void __exit mod_exit( void )
{
    dev_info( hello_dev, "mod_exit called\n" );
    /* Loeschen des Sysfs-Eintrags und damit der Geraetedatei */
    if (hello_dev) device_destroy( hello_class, hello_dev_number ); // HIER AENDERN
    if (hello_class) class_destroy( hello_class ); // HIER AENDERN
    /* Abmelden des Treibers */
    ...
(Dank an Ralf)

Kapitel 6.2 Schneller GPIO-Treiberzugriff, Textfehler auf Seite 176, letzter Satz

Im Text steht fälschlicherweise GPIO7, es handelt sich aber um GPIO17. (Dank an Ralf)



Kapitel 6.7 Schneller GPIO-Treiberzugriff, Textfehler auf Seite 183

Hier steht fälschlicherweise zweimal "fastgpio4", es handelt sich aber um "fastgpio". Richtig ist:

fd_gpio=open("/dev/fastgpio", O_WRONLY);
if (fd_gpio<0) {
    printf("kann /dev/fastgpio nicht oeffnen.\n");
    return -1;
}
(Dank an Ralf)

Kapitel 7.1 Härung des Systems, S.221

Fehlerbild: Das Kommando zum Laden des Watchdog-Treibers schlägt fehl:

# modprobe bcm2709_wdog
modprobe: module bcm2709_wdog not found in modules.dep

Ursache: Der Treibername ist falsch. Statt bcm2709_wdog muss es bcm2708_wdog heißen.

Abhilfe:

# modprobe bcm2708_wdog
#


Copyright © 2014 Jürgen Quade

$Id: index.html,v 1.3 2014/08/20 11:29:47 root Exp root $