Forum: Mikrocontroller und Digitale Elektronik Embedded Linux lernen (mit RPi) - Buchempfehlungen?


von Linuxxer (Gast)


Lesenswert?

Hallo,

kann mir jemand eine gute Lektüre + passenden RPi-Bausatz empfehlen, um 
schnell in das Thema "Embedded Linux" einzusteigen? Am besten wäre es 
wenn man C++ darauf programmiert/kompiliert. Evtl auch mal den Kernel 
updaten.

Embedded Programmierung generell kann ich schon - nur bisher nicht auf 
Linux Systemen.

von Dergute W. (derguteweka)


Lesenswert?

Moin,

LFS-Book und BLFS-Book.
Dabei kommt zwar kein unbedingt "embedded-Linux" raus, aber man kann 
doch mal lernen, wie das alles zusammenhaengt und funktioniert.

Gruss
WK

von Markus F. (mfro)


Lesenswert?

In meinem Sprachgebrauch hat ein RPi nicht unbedingt was mit embedded 
Linux zu tun. Für "echtes" embedded Linux würde ich zumindest einen 
RT-Kernel erwarten.

Auf den Pi's läuft ein "ganz normales" Linux (bloß halt auf einem ARM 
anstatt auf einem PC). Wenn man lernen will, wie man damit umgeht (und 
nicht unbedingt ein Buch braucht), sind die Seiten der RPI Foundation 
m.E. dafür geeignet und ausreichend (z.B.): 
https://curriculum.raspberrypi.org/physical-computing/creator/

von Stefan F. (Gast)


Lesenswert?

Markus F. schrieb:
> Auf den Pi's läuft ein "ganz normales" Linux

Sehe ich auch so. Den Kernel würde ich nur updaten, wenn ich dazu einen 
guten Grund habe. Normalerweise übernimmt der Linux Distributor diese 
Aufgabe.

Wenn du irgendwelche Anleitungen auf der Rasberry Pi Seite vermisst, 
dann schau bei Ubuntu oder Debian nach. Diese beiden Distributionen 
ähneln dem Rasbian sehr, und beide geben sich beide viel Mühe mit der 
Doku.

Hier ist die Anleitung von Ubuntu für das Bauen eines eigenen Kernels: 
https://wiki.ubuntuusers.de/Kernel/Kompilierung/

von PittyJ (Gast)


Lesenswert?

Um Linux richtig kennen zu lernen und zum Kernel kompilieren reicht auch 
ein normaler PC.
Nehme deinen PC, lösche das Windows und arbeite ein Jahr nur mit Linux. 
Dann bist du bereit für mehr. Denn in dem Jahr hast du so viel gelernt, 
dass du Linux dann auch auf kleineren Prozessoren benutzen kannst.

von Stefan F. (Gast)


Lesenswert?

PittyJ schrieb:
> Nehme deinen PC, lösche das Windows

Linux und Windows können beide zusammen installiert sein. Sogar 
Microsoft hat inzwischen gelernt, nicht bei jedem Update alle anderen 
Betriebssysteme zu deaktivieren.

von Dr. Sommer (Gast)


Lesenswert?

PittyJ schrieb:
> Dann bist du bereit für mehr. Denn in dem Jahr hast du so viel gelernt,
> dass du Linux dann auch auf kleineren Prozessoren benutzen kannst.

Dann aber mit Arch oder Gentoo Linux, weil man dann früher oder später 
gezwungen ist irgendwas zu reparieren ;-)

Stefanus F. schrieb:
> Linux und Windows können beide zusammen installiert sein.
Aber dann könnte man aus Faulheitsgründen "versehentlich" Windows 
benutzen...

von Stefan F. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Dann aber mit Arch oder Gentoo Linux, weil man dann früher oder später
> gezwungen ist irgendwas zu reparieren ;-)

Da ist was dran. Bei Ubuntu und Debian ist meine Strategie eher: Wenn 
etwas nicht funktioniert, warte ein paar Wochen. Wenn es dann immer noch 
nicht geht, suche nach Hilfe.

Es ist dort wirklich so, dass die allermeisten gravierenden Probleme 
rasche von den Entwicklern und Distributoren gelöst werden. Ich habe den 
Eindruck, dass das dort sogar einen Tick besser läuft, als bei Windows.

von Dr. Sommer (Gast)


Lesenswert?

Stefanus F. schrieb:
> Da ist was dran.
Durch Schmerz lernt man doch am Besten ;-) Ich habe schlauerweise auch 
mit Gentoo angefangen (weil cool™) ohne jegliche Ahnung davon zu haben - 
durch die nötige Bastelei habe ich dann einige Erfahrungen gesammelt... 
Mittlerweile nehm ich aber auch Linux Mint weil ich keine Lust mehr habe 
alle 3 Tage irgendwelche Paket-Konflikte aufzulösen...

Linuxxer schrieb:
> Am besten wäre es
> wenn man C++ darauf programmiert/kompiliert.

Das ist unter Linux zum Glück ganz einfach:
1
sudo apt-get install build-essential g++
2
echo -e '#include <iostream>\n\nint main () {\n\tstd::cout << "Hello, World!\\n";\n}\n' > test.cpp
3
g++ test.cpp -o test -std=c++17 -O2 -Wall -Wextra -Wconversion -Werror -pedantic
4
./test

von Stefan F. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Das ist unter Linux zum Glück ganz einfach...

Und jetzt erkläre mal einem Teenager jedes einzelne Zeichen. Dann läuft 
der/die schreiend weg und wird nie wieder programmieren wollen. So 
sichern wir unseren Job :-)

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Einen hab' ich noch:
http://librta.org/book.html

Ansonsten wuerd' ich sagen, dass bei einem embedded linux solche Sachen 
wie:

* Das Ding zu jedem Zeitpunkt vom Strom trennen koennen, ohne dass ein 
Filesystem oder dessen Datentraeger kaputt geht.
* DAU tauglicher Update (Statt setup.exe anklicken nur "sudo apt-get 
gedoens" tippern zu muessen ist nicht embedded-tauglich, wie soll das 
auch gehen, ohne Tastatur/Monitor?)
* Anpassungen von Kernel und Driver auf die eigene Hardware, wenn's nix 
von der Stange ist.

die entscheidenden Punkte sind.

Gruss
WK

von Programmiersprachentheaterintendant (Gast)


Lesenswert?

Stefanus F. schrieb:
> Dr. Sommer schrieb:
>> Das ist unter Linux zum Glück ganz einfach...
>
> Und jetzt erkläre mal einem Teenager jedes einzelne Zeichen. Dann läuft
> der/die schreiend weg und wird nie wieder programmieren wollen. So
> sichern wir unseren Job :-)

Hier der Lehrplan für die 2te Woche: 
https://de.m.wikipedia.org/wiki/International_Obfuscated_C_Code_Contest
(um den TeufelsCreis zu brechen verzichte ich den Link zur Wikiseite auf 
Srpski zu setzen)

von DPA (Gast)


Lesenswert?

Linuxxer schrieb:
> Evtl auch mal den Kernel updaten.

Bei einer gut unterstützten Platform wie dem RPi besteht aufgrund des 
guten Supports durch die bekannten Distributoren dazu meist kein Grund. 
Kernel Updates kommen da direkt vom Distributor über den Package manager 
zusammen mit all den anderen Updates.

Bei Plattformen, die vom Mainline Kernel https://www.kernel.org/ 
unterstützt werden, ist es ziemlich einfach, den Kernel selbst zu 
kompilieren. Zuerst braucht man eine Konfig, in der die benötigten 
Treiber für das System eingeschaltet sind. Wenn man schon eine hat, kann 
man die in das /.config file im den Kernel sourcen kopieren. mit "make 
menuconfig" kann man das dann noch anpassen.

Für diverse Boards gibt es bereits fertige im tree. Bei ARM z.B:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/configs
Bei ARM64 ist die Auswahl noch etwas entteuschend:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/configs

Man kann die ganze Liste der vordefinierten Configs mit "make ARCH=arm 
help | grep defconfig" anschauen.

Die Configs können dan mit "make ARCH=arm defconfig 
KBUILD_DEFCONFIG=name_der_defconfig" verwendet werden, um daraus die 
.config zu erstellen. Um aus der .config wieder eine _defconfig zu 
erstellen, kann man "make ARCH=arm savedefconfig" verwenden.

Das "ARCH=arm" ist nur nötig, wenn man cross compiliert. Wenn man den 
Kernel auf dem Zielsystem kompiliert, kann man es weglassen. Dort kann 
man, wenn man alle nötigen Module schon geladen hat, die Config dann 
auch mit "make localyesconfig" oder "make localmodconfig" für eine 
Minimalconfig erstellen.

Neben localdefconfig gibt es noch oldconfig (bestehende Konfig nehmen 
und bei neuen Optionen nachfragen), defconfig (default config für 
Architektur) und config (alle Optionen nachfragen, das dauert ein paar 
Stunden bis Tage, wenn man alle durchliest.). Bei embeded Boards ist es 
aber oft so, dass man gewisse Sachen für ein Spezifisches Board ein oder 
ausstellen muss, speziell bei solchen wo man die nötigen Config Optionen 
nicht kennt ist das nervig, und viele Boards und Treiber sind noch nicht 
in Mainline. Hersteller von embeded Boards oder Smartphones haben oft 
eigene Forks des Kernels, bis die Anpassungen in Mainline ankommen, 
falls der Hersteller die überhaupt je einsendet kann es ewig dauern. In 
dem Fall muss man den dann erstmal finden.

Zum kompilieren kann man dann einfach "make" eingeben. Beim Cross 
compilieren muss man die Architektur und den Kompiler noch mitgeben, 
also z.B. "make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-" oder "make 
ARCH=arm CROSS_COMPILE=arm-linux-gnu-". Den jeweiligen Kompiler muss man 
natürlich auch noch installiert haben. Für bekannte Distributionen, wie 
z.B. Debian-basierte gibt es noch Targets, die den Kernel in Packete für 
die Distribution verpackt. unter Debian wäre das z.B. "deb-pkg". Das 
ganze Kommando währe dann also z.B. "make ARCH=arm64 
CROSS_COMPILE=aarch64-linux-gnu-".

Das boot verfahren ist je nach Architektur, CPUs und Boards auch sehr 
verschieden. Beim RPI z.B. wird der Kernel vom Grafikchip geladen!!!
Die meisten ARM Boards verwenden uboot um den Kernel zu laden. Dort ist 
auch sehr vieles board spezifisch. Neuere Boards, besonders solche mit 
arm64 Architektur benötigen gewisse Initialisierung schritte, die uboot 
nicht enthält, und verwenden deshalb arm-trusted-firmware dafür als 
first-stage bootloader, der dan uboot als second stage bootloader lädt, 
der dann den Kernel lädt. Die arm-trusted-firmware (ATF) enthält auch 
mechanismen, über die die Signatur der Bootloader mit einem Zertifikat 
in einem Rom beim Boot verifiziert werden kann, und ist damit direkt 
mitverantwortlich, dass man bei fast allen Smartphones als 
Smartphonebesitzer den Bootloader usw. nicht ersetzen kann, also man 
sein Eigentum nicht voll unter Kontrolle hat, was ich eine riesen 
Schweinerei finde. Wie schwer wäre es gewesen, einen internen EEPROM 
stat ROM zu nehmen, und einen Mechanismus zum Austausch der Zertifikate 
der Benutzer einzubauen? Aber ich komme vom Thema ab. Wie die ATF 
geladen wird, da bin ich auch noch überfragt.

Während bei PCs mit PCI und ACPI usw. die Hardware ermittelt werden 
kann, verwendet Android andere Verfahren. Es werden device trees files 
verwendet. Diese kommen in diversen Formen, können von uboot von einem 
File geladen werden, in uboot mit ein kompiliert werden, in den Kernel 
mit ein kompiliert werden, von uboot verändert werden, und uboot und der 
Kernel können unterschiedliche device trees haben. In der regel braucht 
man einfach eins, das zum Board passt. Bei uboot gibt es dann noch 
diverse Möglichkeiten einzustellen, wie der Kernel geladen wird. Man 
kann ein Script schreiben und mit uboot-mkimage in ein uboot script 
umwandeln, oder die fest Einkompilieren, und vieles mehr.

Dann noch zum Starten des Systems durch den Linux kernel. in einer 
intird oder initramfs wird in der regel zuerst /init mit pid 1 
gestartet. Diese mounten dann die Dateisysteme und sstarten das 
eigentliche init, wieder mit pid 1, mit einem exec in /init. Wird ohne 
initrd/initramfs gebooted startet der Kernel statdessen /sbin/init, 
/etc/init, /bin/init oder /bin/sh, jenachdem, welches er in der 
Reihenfolge zuerst findet.

Der init Prozess kann auch ein Script sein. Es gibt 4 Arten, wie unter 
Linux ein Programm gestartet werden kann.
 1) Ein Script gibt das Program, welches dieses interpretiert, mit der 
Shebang Zeile ganz am Anfang an, z.B. "#!/bin/bash" oder "#!  /bin/sh" 
oder "#!  /bin/sh  -l  ". Der Abstand zwischen #! und dem Kommando wird 
ignoriert. Es ist maximal ein zusätzliches Argument möglich. Das 
Programm wird dann mit "/angegebenes/program argument_falls_vorhanden 
pfad/mit/dem/das/script/gestartet/wurde" gestartet.
 2) Bei statisch gelinkten Programmen wird das Programm in den Speicher 
gemappt und direkt gestartet.
 3) Bei dynamisch gelinkten elf Programmen gibt es eine .interp section, 
die ein program/library angibt die statdessen vom kernel geladen wird, 
und dann das eigentliche Programm in den Speicher mapt und ausführt. Das 
ist der dynamic linker/loader, auch bekannt als ld.so.
 4) Mit dem binfmt_misc Mechanismus kann man beliebige Dateiformate 
anhand von magic numbers oder extension usw. mit einem interpreter 
starten lassen.  Damit kann man z.B. windows .exe direkt über wine 
ausführbar machen ohne explizit "wine bla.exe" angeben zu müssen, oder 
man kann es konfigurieren qemu-aarch64-static bei arm Binaries zu 
verwenden, wodurch man diese dann direkt ausführen kann. So sind sogar 
Chroots und Container mit komplett anderer Architektur möglich.

Unabhängig davon, welches verfahren verwendet wird, müssen beim Starten 
einer Anwendung die Interpreter, Libraries und Loader einfach alle 
vorhanden sein. Bei statischen Programmen hat man den Vorteil, dass man 
sich um die verwendeten Libs keine Gedanken machen muss. Das einrichten 
der ganzen build toolchain für eine eigene Distribution kann sehr 
aufwendig sein.

Beim manuellen einrichten von Distributionen oder Images von einem 
anderen System aus haben eigentlich alle Distributionen Tools und 
verfahren das Bootstrapping zu vereinfachen. Gentoo bietet diverse 
Tarballs an, die genug Tools beinhalten den rest zu compilieren und zu 
emergen. Debian hat debootstrap, welches die wichtigsten Packete 
herunterzuladen und zu entpacken. Auf diese weise kann man einfaches 
Rootfs erstellen.


Linuxxer schrieb:
> Am besten wäre es wenn man C++ darauf programmiert/kompiliert.

Will man aber nur eine bestehende Distro anpassen, kann man all das 
ignorieren. Dann nimmt man einfach die Distro und ändert was auch immer 
man will. Bei C++ installiert man halt g++, oder wenn amn cross 
compillieren will halt den aarch64-linux-gnu-g++ oder arm-linux-gnu-g++, 
je nachdem, was man vor hat.

von Jack (Gast)


Lesenswert?

Markus F. schrieb:
> In meinem Sprachgebrauch hat ein RPi nicht unbedingt was mit embedded
> Linux zu tun. Für "echtes" embedded Linux würde ich zumindest einen
> RT-Kernel erwarten.

Embedded ≠ RT.

von Neverever (Gast)


Lesenswert?


Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.