SASE2015 - Booteando Linux en una CIAA NXP

Anuncio
SASE2015 - Booteando Linux en una CIAA NXP
Ezequiel García
Ariel D’Alessandro
August 10, 2015
1 Entorno
Antes de empezar, necesitamos activar el entorno que preparamos anteriormente. Para ello, simplemente
ejecutamos ’ciaa_env’ en una consola.
$ ciaa_env
CIAA environment. ARCH=arm, CC=arm-cortexm3-uclinuxeabi-
IMPORTANTE: Debemos ejecutar siempre ’ciaa_env’ al abrir una consola nueva.
2 U-Boot
El primer paso es compilar el bootloader U-Boot. Para ello, debemos configurarlo con ’ciaa_lpc4337_config’
y luego compilarlo.
$ cd u-boot/
$ make ciaa_lpc4337_config
$ make
Si todo salió bien, deberíamos ver:
[..]
tools/lpc178x_fcg u-boot.bin u-boot-lpc.bin
File u-boot.bin loaded with size 66580 bytes
Word 0: 0x1008a000
Word 1: 0x1a0002a1
Word 2: 0x1a000299
Word 3: 0x1a000299
Word 4: 0x1a000299
Word 5: 0x1a000299
Word 6: 0x1a000299
Word 7: 0x53f75062 (cksum total: 0x00000000)
File u-boot-lpc.bin created with size 66580 bytes
mv u-boot-lpc.bin u-boot.bin
dd if=cpu/arm_cortexm3/lpc18xx/spifilib/spifilib-envm.bin of=u-boot.bin seek=112 bs=1024
8+1 records in
8+1 records out
8312 bytes (8.3 kB) copied, 0.000206441 s, 40.3 MB/s
1
3 Conectar la CIAA
Conectamos el cable miniUSB<->USB. El conector miniUSB debe ir al puerto ”DBG” de la CIAA y el
USB se conecta a nuestra PC o laptop.
Este conector cumple tres funciones: 1) alimentación de la CIAA, 2) conexión JTAG, y 3) conexión al
puerto serie UART2.
Al conectar el cable veremos que se enciende el LED ”PWR” (rojo), el cuál indica que la placa está
alimentada (rail de entrada de 5V energizado).
Además, deberíamos ver que se crean dos nuevos dispositivos tty en nuestra PC o laptop:
$ dmesg | tail | grep tty
usb 2-1.2: FTDI USB Serial Device converter now attached to ttyUSB0
usb 2-1.2: FTDI USB Serial Device converter now attached to ttyUSB1
Esto indica que nuestra PC o laptop detectó correctamente el chip FTDI de la CIAA.
IMPORTANTE: Si no se ven estos mensajes, y la PC o laptop no logra detectar a la CIAA, no es
posible continuar. En ese caso, contactarse con los organizadores.
4 Flashear el bootloader en la CIAA
Ahora que la CIAA se encuentra alimentada, podemos usar openocd para acceder a la flash interna y
grabar el bootloader.
Esto lo debemos hacer usando el openocd que compilamos e instalamos previamente:
$ /usr/local/bin/openocd -f /path/to/buildroot/board/ciaa/lpc4337/openocd.cfg \
-c "init" \
-c "halt" \
-c "flash write_image erase unlock /path/to/u-boot/u-boot.bin 0x1A000000 bin" \
-c "exit"
IMPORTANTE: No se recomienda usar otra versión de openocd. En particular, no estamos seguros
que funcione el openocd provisto por la distribución Linux.
IMPORTANTE: Si openocd termina con un error LIBUSB_ERROR_ACCESS será necesario ejecutarlo con privilegios.
5 Primer booteo de la CIAA
Vamos a usar picocom, conectando al puerto UART2. El bootloader que acabamos de grabar, tiene
configurada la salida de consola en el UART2. En nuestra PC o laptop este puerto el device ttyUSB1.
$ picocom -b 115200 /dev/ttyUSB1
Reseteamos el SoC para verificar si la grabación fue exitosa:
$ /usr/local/bin/openocd -f /path/to/buildroot/board/ciaa/lpc4337/openocd.cfg \
-c "init" \
2
-c "reset" \
-c "exit"
Si todo salió bien vemos:
U-Boot 2010.03-00037-g6823c9c-dirty (Jul 29 2015 - 18:08:59)
CPU : LPC43xx series (Cortex-M4/M0)
Freqs: SYSTICK=144MHz,CCLK=144MHz
Board: CIAA NXP
DRAM:
8 MB
Using default environment
In:
serial
Out:
serial
Err:
serial
Net:
LPC18XX_MAC
Hit any key to stop autoboot:
0
6 Linux kernel
Ahora que tenemos un bootloader listo, vamos a compilar el kernel para poder grabarlo en la flash.
$ cd linux/
$ make ciaa_lpc4337_defconfig
$ make zImage dtbs
NOTA: Esto puede llevar un tiempo largo, dependiendo del sistema. En sistemas SMP se puede usar
-jN para hacer una compilación paralela con N jobs.
7 Generación de uImage
Ahora que ya tenemos la imagen zImage (kernel comprimido) y el binario del DeviceTree, debemos
empaquetarlos usando un formato conocido por U-Boot.
NOTA: Este paso es necesario para poder bootear Linux en un bootloader U-Boot ”antiguo”. Versiones
modernas de U-Boot son capaces de bootear Linux usando directamente el par zImage, dtb.
Primero generamos un archivo contiguo que contiene los dos binarios:
$ cat ./arch/arm/boot/zImage ./arch/arm/boot/dts/lpc4337-ciaa.dtb > zImage.dtb
Y luego, creamos una imagen para U-Boot.
$ ./scripts/mkuboot.sh -A arm -O linux -T kernel -C none -a 0x28008000 -e 0x28008001 \
-n "CIAA-Linux" -d zImage.dtb uImage
3
8 Flashear el kernel en la CIAA
$ /usr/local/bin/openocd -f /path/to/buildroot/board/ciaa/lpc4337/openocd.cfg \
-c "init" \
-c "reset" \
-c "halt" \
-c "flash write_image erase unlock /path/to/linux/uImage 0x14000000 bin" \
-c "exit"
9 Bootear kernel
Volvemos a la terminal donde tenemos picocom corriendo, o lo iniciamos nuevamente:
$ picocom -b 115200 /dev/ttyUSB1
Reseteamos el SoC para verificar si la grabación fue exitosa:
$ /usr/local/bin/openocd -f /path/to/buildroot/board/ciaa/lpc4337/openocd.cfg \
-c "init" \
-c "reset" \
-c "exit"
El bootloader debería iniciar automáticamente. Si esto no sucede, podemos bootear en forma manual:
$ ciaa > run bootcmd
## Booting kernel from Legacy Image at 14000000 ...
Image Name:
CIAA-Linux
Image Type:
ARM Linux Kernel Image (uncompressed)
Data Size:
1236942 Bytes = 1.2 MB
Load Address: 28008000
Entry Point: 28008001
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux... done, booting the kernel.
[
0.000000] Booting Linux on physical CPU 0x0
[
etc
]
EJERCICIO: ¿Por qué el load address es 0x28008000 y el entry point es 0x28008001?
Este kernel aún no tiene un rootfs, y por lo tanto, veremos un mensaje indicando que no se ha podido
encontrar un medio para montar un rootfs.
Freeing unused kernel memory: 60K (28117000 - 28126000)
Kernel panic - not syncing: No working init found. Try passing init= option to kernel.
See Linux Documentation/init.txt for guidance.
---[ end Kernel panic - not syncing: No working init found. Try passing init= option
to kernel. See Linux Documentation/init.txt for guidance.
4
10 Compilar rootfs
La configuración por defecto ’ciaa_lpc4337_defconfig’ de buildroot, tiene habilitadas las opciones para
compilar kernel y bootloader. Dado que esto ya lo hicimos en los pasos previos, desactivaremos esas
opciones para ahorrar tiempo considerable durante la compilación.
Lo primero que haremos es acceder al menú (basado en ncurses):
$ cd buildroot/
$ make menuconfig
Luego destildamos las opciones:
Kernel ---> Linux Kernel
Bootloaders ---> U-Boot
Notar que dentro de cada opción figuran otros parámetros indicando por ej. qué versión y archivo de
configuración utilizar, coincidiendo con los utilizados en los pasos previos. Se alienta a los asistentes a
probar e investigar las distintas configuraciones que ofrece Buildroot.
Finalmente compilamos el rootfs, siendo en este caso de tipo cpio:
$ make rootfs-cpio
Si todo salió bien, deberíamos tener una imagen del rootfs en: /path/to/buildroot/output/images/rootfs.cpio
11 Re-configurar Linux para agregar el rootfs
Ahora que generamos el rootfs, vamos a modificar la configuración de linux para que se compile con el
file system embebido. Para esto ejecutamos:
$ cd linux/
$ make menuconfig
Debemos asegurarnos que la siguiente opción esté tildada:
General setup ---> Initial RAM filesystem and RAM disk (initramfs/initrd) support
Luego, en la opción:
General setup ---> Initramfs source file(s)
insertamos la siguiente cadena de texto:
/path/to/buildroot/output/images/rootfs.cpio
Ahora podemos volver a compilar el kernel con:
$ make zImage dtbs
Por último, repetimos los pasos de la sección ’Generación de uImage’.
5
12 Flashear el kernel+rootfs en la CIAA
$ /usr/local/bin/openocd -f /path/to/buildroot/board/ciaa/lpc4337/openocd.cfg \
-c "init" \
-c "reset" \
-c "halt" \
-c "flash write_image erase unlock /path/to/linux/uImage 0x14000000 bin" \
-c "exit"
13 Bootear el sistema!
Finalmente, podemos bootear la CIAA y ver como bootea hasta un shell Linux típico. En este shell,
podemos ingresar comandos Unix conocidos. Sin embargo, debemos tener en cuenta que es un entorno
reducido y por lo tanto muchos comandos responden en forma limitada o bien no están disponibles.
/ # ls
bin
dev
etc
/ #
PID
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
22
24
ps
USER
root
root
root
root
root
root
root
root
root
root
root
root
root
root
root
root
root
root
root
home
init
lib
lib32
linuxrc
media
VSZ
220
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
232
228
STAT
S
SW
SW
SW
SW<
SW
SW
SW
SW
SW<
SW
SW<
SW
SW
SW<
SW
SW
S
R
mnt
opt
proc
root
run
sbin
sys
tmp
usr
COMMAND
init
[kthreadd]
[ksoftirqd/0]
[kworker/0:0]
[kworker/0:0H]
[kworker/u2:0]
[rcu_preempt]
[rcu_sched]
[rcu_bh]
[khelper]
[kdevtmpfs]
[writeback]
[kworker/0:1]
[kswapd0]
[deferwq]
[kworker/u2:1]
[spi32766]
-/bin/sh
ps
/ # grep
sh: can't execute 'grep': No such file or directory
EJERCICIO: Calcular el footprint de memoria RAM.
6
var
14 Bonus track!
Para seguir investigando podés hacer los siguientes ejercicios. Recordá que dentro del menú de configuración podés buscar la ubicación de una opción determinada presionando la tecla / e insertando su
nombre.
1. Re-compilar el kernel con las opciones CONFIG_HZ_PERIODIC y CONFIG_HZ_1000 habilitadas. ¿Se puede notar alguna diferencia de comportamiento?
2. Re-compilar el kernel eligiendo CONFIG_SLOB. ¿Se puede notar alguna diferencia de comportamiento?
3. Re-compilar el kernel eligiendo CONFIG_PRINTK_TIME. ¿Se puede notar alguna diferencia de
comportamiento?
4. En buildroot, usando make busybox-menuconfig, seleccionar CONFIG_LESS y CONFIG_YES y
re-compilar el kernel+initramfs. Comprobar que se pueden usar los comandos ”less” y ”yes”.
15 Layout de memoria Flash
A continuación se describe el Layout de memoria Flash utilizado durante el taller a medida que se van
realizando los distintos pasos.
Bank 0x1a000000: (memoria flash interna)
-----------| U-Boot |
|
|
| ...
|
|
|
|----------|
Bank 0x14000000: (memoria flash externa SPI NOR)
-----------| Kernel |
|
|
| ...
|
|
|
|----------|
| RootFS |
| appended |
| ...
|
|
|
|----------|
7
Descargar