Mirko Damiani How to build a minimal GNU/Linux embedded system

Mirko Damiani
How to build a minimal
GNU/Linux embedded system
. . . from scratch!
Better Embedded Conference
Firenze, Sept. 24-25, 2012
Terms of Interest
●
●
●
GNU/Linux
●
GNU software
●
Linux kernel
Minimal
●
Size and number of utilities
●
Complexity of scripts
Embedded system
●
Custom boards
●
Low resources
2 / 35
Mirko Damiani – [email protected]
Prerequisites
●
●
Entry level
●
GNU/Linux kernel
●
Hardware schematics
●
Operating systems
●
Computer architectures
Intermediate level
●
GNU/Linux utilities
●
SW development
3 / 35
Mirko Damiani – [email protected]
Reference board
●
●
LeopardBoard 365
●
DM365 SoC (Texas Instruments)
●
ARM processor
Linux support
●
TI evaluation board (DaVinci)
●
LeopardBoard differs from TI evaluation board
●
Board Support Package available
4 / 35
Mirko Damiani – [email protected]
Overview
●
Board flashing
●
●
System startup
●
●
Bootloader
Kernel
●
●
Strategy
How to load and start it
Root filesystem
●
How to create it
5 / 35
Mirko Damiani – [email protected]
Board flashing
●
Common methods
●
Flashing strategy
●
Rootfs archive
●
Read-only rootfs
●
Flashing on the fly
6 / 35
Common methods
●
●
Utilities to program the NAND flash
●
SD/MMC card
●
USB (memory stick or protocol)
●
Serial port
Custom boards may need a specific
flashing strategy
●
SD/MMC or USB may be missing
●
Flashing utilities might not work
●
Serial port is almost always present
7 / 35
Mirko Damiani – [email protected]
Flashing strategy
●
●
●
Let's suppose we are able to flash
at least the bootloader
We load the entire system in RAM
●
Kernel is always loaded in RAM
●
Rootfs is passed as an initramfs archive
●
Kernel extracts its initramfs in RAM when it boots up
System is flashed for permanent setup
●
Linux starts from NAND flash
8 / 35
Mirko Damiani – [email protected]
Flashing strategy
●
●
Small components
●
Kernel is less than 4MB
●
Rootfs fits in 32MB (unpacked)
No different configurations
●
●
●
PC
(tftp server)
The same system is used both for
flashing and production
Software development is easier
Need more space?
●
Board
NAND
Minimal rootfs is able to mount
other NAND partitions
9 / 35
Mirko Damiani – [email protected]
Rootfs archive
●
●
The same rootfs must be saved in 2 different formats
●
Initramfs (gzipped cpio archive)
●
SquashFS image (read-only archive)
Different kernel parameters, for instance:
●
●
Initramfs
rdinit=/sbin/init initrd=0x82000000,0x82a190
SquashFS
init=/sbin/init root=/dev/mtdblock3 rootfstype=squashfs
10 / 35
Mirko Damiani – [email protected]
Read-only rootfs
●
Still need to have some R/W folders
●
●
/etc, /tmp, /var, /dev
Move contents in RAM and remount from there
●
mount -n -t tmpfs none /mnt/rwfs -o size=4096k
●
mkdir -p /mnt/rwfs/etc
●
cp -a /etc/* /mnt/rwfs/etc
●
mount -n --bind /mnt/rwfs/etc /etc
●
Now we don't have write errors anymore
●
Read-only filesystems are fast
Mirko Damiani – [email protected]
11 / 35
Flashing on the fly
●
●
Kernel and rootfs are downloaded via tftp server again
It's not convenient to save files in RAM,
since we might not have enough room
RAM
●
NAND
Both files are directly flashed,
without storing them in RAM
NAND
12 / 35
Mirko Damiani – [email protected]
System startup
●
DM365 as reference
●
Boot overview
●
Boot loading stages
●
Debug at early stages
13 / 35
Boot overview
●
Board initialization
●
●
Persistent configuration (kernel params)
kernel
Kernel loading
●
●
bootloader
Bootloader execution
●
●
Low level, hardware related
Operating system and devices setup
rootfs
System startup
●
/sbin/init and other scripts
14 / 35
Mirko Damiani – [email protected]
Bootloader stages (DM365)
●
ROM boot loader (RBL)
●
●
●
ARM subsystem initialization
User boot loader (UBL)
●
RBL
(1st stage)
External devices initialization
UBL
(2nd stage)
U-Boot
●
Power on
Kernel loading
U-Boot
(3rd stage)
15 / 35
Mirko Damiani – [email protected]
Bootloader stages (DM365)
Power on
NAND
UART
RBL
(1st stage)
Get UBL
USB
Store in IRAM
(32KB)
UBL
(2nd stage)
U-Boot
(3rd stage)
16 / 35
Mirko Damiani – [email protected]
Bootloader stages (DM365)
Power on
NAND
UART
RBL
(1st stage)
Get U-Boot
USB
Store in RAM
(128MB)
UBL
(2nd stage)
U-Boot
(3rd stage)
17 / 35
Mirko Damiani – [email protected]
Bootloader stages (DM365)
Power on
RBL
(1st stage)
Get Kernel
Scripts
Parameters
Environment
Run Linux
UBL
(2nd stage)
U-Boot
(3rd stage)
18 / 35
Mirko Damiani – [email protected]
RBL NAND loading (DM365)
●
Loading algorithm
●
●
●
●
NAND memories are organized
in sectors and pages
RBL searches for a valid block
In case of read errors,
next block is searched for
a valid UBL (up to #24)
Robustness
●
●
Multiple UBL / U-Boot pairs
may be saved in NAND
Flashing utilities do this for you
19 / 35
Mirko Damiani – [email protected]
Debug at early stages
●
U-Boot also provides an UBL for DaVinci boards
●
●
●
UBL sets the ARM processor frequency,
so i might want to change that values
Very hard to debug
●
●
●
TI UBL may be replaced with U-Boot UBL
Commons methods (printf, debugger, gdb, valgrind...)
are not available
Boards simply don't boot,
without any evidence of errors
A useful approach: exploit GPIO pins
20 / 35
Mirko Damiani – [email protected]
LeopardBoard GPIO
●
Access some registers (memory mapped I/O)
●
Setup pin multiplexing
●
Select GPIO direction
●
Drive GPIO as output high or low
21 / 35
Mirko Damiani – [email protected]
Kernel
●
Board Support Packages
●
Configuration and build
●
Loading and parameters
●
Patches
●
NAND partitioning
22 / 35
Board Support Packages
●
●
●
●
●
Kernel and drivers are patched to work with the
specified development board
We must understand how they works,
e.g. a camera driver would use video4linux
Custom boards may differ from development boards,
so additional SW patches are required
Ad-hoc drivers are not easy to write from scratch,
e.g a camera driver we would support only a specific
sensor and very few operation modes
Minimal drivers lead to an higher code maintenance
23 / 35
Mirko Damiani – [email protected]
Configuration and build
●
●
Compilation
●
Download from www.kernel.org
●
Toolchain: Sourcery Codebench Lite
Select the correct system and board, e.g.:
●
ARM system type
●
DaVinci 365 based system
●
Disable all which is not needed
●
Vanilla
●
We have a mainstream kernel
●
Easy to maintain (update)
●
Recent version
Mirko Damiani – [email protected]
24 / 35
Kernel loading
●
●
●
●
●
Loading is performed
by the bootloader
Arguments are passed
to the kernel
bootloader
args
Kernel sets up its devices
When booting is completed,
/sbin/init is called
(from within the rootfs)
/sbin/init is responsible for
bringing up the rest of the
system (the userland)
/sbin/init
pid = 1
Mirko Damiani – [email protected]
25 / 35
Kernel patches
●
●
DaVinci RTC on LeopardBoard 365
●
Driver is tested on DM360 EVM
●
LeopardBoard has a different schematic
Mux pins and drive some GPIOs
26 / 35
Mirko Damiani – [email protected]
Kernel parameters
●
Serial console device and options
●
●
console=ttyS0,115200n8
LeopardBoard 365
●
●
MAC address changes at every reboot
We can save it on U-Boot environment,
and pass it to the Linux kernel
–
davinci_emac.macaddr=AA:BB:CC:DD:EE:FF
–
davinci_emac.macaddr=${ethaddr}
27 / 35
Mirko Damiani – [email protected]
NAND partitioning
●
●
●
Bootloader is
never touched
Environment holds
kernel arguments
This layout may be
statically written
in kernel sources,
or passed through
arguments
30 blocks
bootloader
256 KB
environment
4 MB
kernel
32 MB
rootfs
28 / 35
Mirko Damiani – [email protected]
Root filesystem
●
Busybox
●
Accessing bootloader environment
●
Building the root filesystem
29 / 35
Busybox
●
Provides almost a complete environment
for small systems
●
●
Tiny version of common utilities (fewer options)
Single executable
●
Size optimization
●
Static or dynamic library linking
●
Symlinks to busybox executable
–
●
e.g: /bin/ls -> /bin/busybox
Default configuration
●
Static: 2MB
●
Dynamic: 936KB
30 / 35
Mirko Damiani – [email protected]
Busybox
●
Packages
●
Coreutils, Shells, Editors, Network, …
●
Login files
–
●
System logs
–
●
●
/etc/passwd, /etc/shadow, /etc/groups, …
syslogd, klogd
...
Init program (/sbin/init)
●
Reads /etc/inittab
●
Runs /etc/rc.d/rcS
●
Other scripts, /etc/rc.d/init.d/network, ...
31 / 35
Mirko Damiani – [email protected]
Bootloader environment
●
Recall: boot env is stored into the 2nd partition
●
Example: U-Boot
●
●
Provides some tools: fw_printenv, fw_setenv
Generally speaking, it's possible to
access them from userspace.
●
●
Within our flashing procedure,
IP address of tftp server
may be read from the
bootloader environment
System might not save at all
kernel and rootfs into NAND,
while being still configurable
192.168.10.101
Mirko Damiani – [email protected]
32 / 35
Building the root filesystem
folders
structure
rootfs
toolchain
libraries
clean
binaries
busybox
kernel
modules
skeleton
files
33 / 35
Mirko Damiani – [email protected]
Let's Talk
office
+39 055 3984627
e-mail / jabber
[email protected]
web
www.develer.com
License
Creative Commons Attribution 3.0 Unported