• GNU/Linux • GNU software • Linux kernel • Minimal • Size and number of utilities • Complexity of scripts • Embedded system • Custom boards • Low resources
LeopardBoard 365 • DM365 SoC (Texas Instruments) • ARM processor • Linux support • TI evaluation board (DaVinci) • LeopardBoard differs from TI evaluation board • Board Support Package available
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
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
Small components • Kernel is less than 4MB • Rootfs fits in 32MB (unpacked) • No different configurations • The same system is used both for flashing and production • Software development is easier • Need more space? • Minimal rootfs is able to mount other NAND partitions PC (tftp server) Board NAND
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
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
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 • Both files are directly flashed, without storing them in RAM RAM NAND NAND
(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
stages • U-Boot also provides an UBL for DaVinci boards • TI UBL may be replaced with U-Boot UBL • UBL sets the ARM processor frequency, so i might want to change that values • Very hard to debug • 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
• 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
• 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
Loading is performed by the bootloader • Arguments are passed to the kernel • 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) args bootloader /sbin/init pid = 1
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}
Bootloader is never touched • Environment holds kernel arguments • This layout may be statically written in kernel sources, or passed through arguments bootloader environment kernel rootfs 30 blocks 256 KB 4 MB 32 MB
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
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