Debian (armhf) su BeagleBone

beaglebone

beagleboneIn questo articolo faremo una breve prova su strada della nuova nata in casa BeagleBoard.org, la BeagleBone, installandoci su una Debian Wheezy (armhf).

La scheda è interessante perché supporta una nuova CPU super-scalar ARM Cortex-A8 (armv7a) a 720MHz con la quale è possibile usare il nuovo supporto ARM Hard Float (indicato con armhf). Inoltre a bordo ci sono diverse periferiche accessibili dal connettore d’espansione che la rendono molto versatile.

Le periferiche subiro accessibili sono: 1xUSB device (per la console), 1x USB host, 1x Ethernet e 1x microSD; mentre sul connettore di espansione ci sono 2x I2C, 5x UART, I2S, SPI, CAN, 66x 3.3V GPIO e 7x ADC.

Come prova su strada farò vedere come installare una distribuzione Debian su questa scheda ricompilandosi il bootloader e il kernel ed installando un rootfs minimale.

Il bootloader

Innanzitutto vediamo come avviene la fase di boot. La CPU, appena accesa esegue un ROM boot code il quale, a seconda di alcuni impostazioni esterne, inizia a tentare di caricare il bootloader da una pariferiferica di massa. Nel nostro caso dalla microSD; quindi dobbiamo installare il bootloader lì.

Il bootloader che utilizzeremo è U-Boot, vediamo come compilarlo (nota preliminare, i comandi che userò sono validi per una distro compatibile con la mia Ubuntu 12.04).

Innanzi tutto verifichiamo il cross-compilatore. Se lo avete già sulla vostra macchina dovreste ottenere una cosa del genere:

$ arm-linux-gnueabihf-gcc -v
Using built-in specs.
COLLECT_GCC=/usr/bin/arm-linux-gnueabihf-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/4.6/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: ../src/configure -v –with-pkgversion=’Ubuntu/Linaro 4.6.3-1ubuntu5′ –with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs –enable-languages=c,c++,fortran,objc,obj-c++ –prefix=/usr –program-suffix=-4.6 –enable-shared –enable-linker-build-id –with-system-zlib –libexecdir=/usr/lib –without-included-gettext –enable-threads=posix –with-gxx-include-dir=/usr/arm-linux-gnueabihf/include/c++/4.6.3 –libdir=/usr/lib –enable-nls –enable-clocale=gnu –enable-libstdcxx-debug –enable-libstdcxx-time=yes –enable-gnu-unique-object –enable-plugin –enable-objc-gc –enable-multilib –disable-sjlj-exceptions –with-arch=armv7-a –with-float=hard –with-fpu=vfpv3-d16 –with-mode=thumb –disable-werror –enable-checking=release –build=x86_64-linux-gnu –host=x86_64-linux-gnu –target=arm-linux-gnueabihf –program-prefix=arm-linux-gnueabihf- –includedir=/usr/arm-linux-gnueabihf/include –with-headers=/usr/arm-linux-gnueabihf/include –with-libs=/usr/arm-linux-gnueabihf/lib
Thread model: posix
gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)

Se invece ottenete un errore allora potete installare il cross-compilatore con il comando:

$ sudo aptitude install gcc-arm-linux-gnueabihf

A questo punto scarichiamoci i sorgenti di u-boot:

$ git clone git://git.denx.de/u-boot.git
$ cd u-boot/
$ git checkout v2013.01.01 -b v2013.01.01

ed aggiungiamo due patch per il supporto della immagine in formato zImage e l’assegnazione automatica del nome del file DTB.

$ wget https://raw.github.com/RobertCNelson/Bootloader-Builder/master/patches/v2013.01/0001-enable-bootz-and-generic-load-features.patch
$ wget https://raw.github.com/RobertCNelson/Bootloader-Builder/master/patches/v2013.01/0002-bone-use-dtb_file-variable-for-device-tree-file.patch
$ git am 000*.patch

Ok, se tutto è andato bene possiamo passare alla compilazione:

$ export ARCH=arm
$ export CROSS_COMPILE=arm-linux-gnueabihf-
$ make am335x_evm_config

$ make

Alla fine avremo ottenuto i file MLO e u-boot.bin. Il secondo file è ben noto a chi sa usare u-boot mentre il primo non è altro che un pre-bootloader… cioè un bootloader che viene caricato prima del bootloader vero e proprio! Questo perché la CPU della BeagleBone non ha sufficiente memoria RAM interna per contenere tutto u-boot e quindi è necessario dividere la fase di boot in due passi successivi:

  1. Il ROM Boot code cercherà un file di nome MLO nella prima partizione VFAT della microSD; se lo trova lo carica nella RAM interna alla CPU e lo esegue;
  2. a sua volta MLO cerchera nella prima partizione della microSD un file di nome u-boot.bin; se lo trova lo carica nella RAM del sistema (una volta inizializzata) e lo esegue.

Ok, ora per verificare che tutto funzioni proviamo a far partire u-boot dalla microSD. Inseriamola nel nostro PC host e formattiamola in modo tale che risulti come riportato sotto (verificate nel vostro sistema che la microSD corrisponda al device /dev/sdg altrimenti adeguate i seguenti comandi al vostro sistema):

$ sudo sfdisk -l /dev/sdg

Disk /dev/sdg: 474 cylinders, 255 heads, 63 sectors/track
Units = cylinders of 8225280 bytes, blocks of 1024 bytes, counting from 0

   Device Boot Start     End   #cyls    #blocks   Id  System
/dev/sdg1   *      0+      8       9-     72261    c  W95 FAT32 (LBA)
/dev/sdg2          9     443     435    3494137+  83  Linux
/dev/sdg3          0       –       0          0    0  Empty
/dev/sdg4          0       –       0          0    0  Empty

Quindi formattiamo le prime due partizioni (le altre non vengono usate):

$ sudo mkfs.vfat -F 16 /dev/sdg1 -n boot
$ sudo mkfs.ext4 /dev/sdg2 -L rootfs

a questo punto se togliete e reinserite la microSD la vostra Ubuntu (o distro equivalente) dovrebbe auto-montare la microSD nel directory /media come segue:

$ ls /media/
boot/
rootfs/

quindi installiamo i bootloader:

$ sudo cp -v MLO /media/boot/
$ sudo cp -v u-boot.img /media/boot/

Bene, ora possiamo fare una prima prova! Rimettiamo la microSD nella BeagleBone e accendiamo; dal terminale seriale dovrebbe apparire:

U-Boot SPL 2013.01.01-dirty (Feb 22 2013 – 17:00:30)
OMAP SD/MMC: 0
reading u-boot.img
reading u-boot.img

U-Boot 2013.01.01-dirty (Feb 22 2013 – 17:00:30)

I2C:   ready
DRAM:  256 MiB
WARNING: Caches not enabled
NAND:  No NAND device found!!!
0 MiB
MMC:   OMAP SD/MMC: 0, OMAP SD/MMC: 1
*** Warning – readenv() failed, using default environment

musb-hdrc: ConfigData=0xde (UTMI-8, dyn FIFOs, bulk combine, bulk split, HB-ISO
Rx, HB-ISO Tx, SoftConn)
musb-hdrc: MHDRC RTL version 2.0
musb-hdrc: setup fifo_mode 4
musb-hdrc: 28/31 max ep, 16384/16384 memory
USB Peripheral mode controller at 47401000 using PIO, IRQ 0
musb-hdrc: ConfigData=0xde (UTMI-8, dyn FIFOs, bulk combine, bulk split, HB-ISO
Rx, HB-ISO Tx, SoftConn)
musb-hdrc: MHDRC RTL version 2.0
musb-hdrc: setup fifo_mode 4
musb-hdrc: 28/31 max ep, 16384/16384 memory
USB Host mode controller at 47401800 using PIO, IRQ 0
Net:   cpsw, usb_ether
Hit any key to stop autoboot:  0
mmc0 is current device
SD/MMC found on device 0
reading uEnv.txt
** Unable to read file uEnv.txt **
** File not found /boot/uImage **

Ok, funziona! :)

Il kernel

Ora vediamo come fare per il kernel. Innanzi tutto scarichiamoci i sorgenti:

$ git clone git://github.com/RobertCNelson/linux-dev.git
$ cd linux-dev/
$ git checkout origin/am33x-v3.8 -b am33x-v3.8

Quindi compiliamo il tutto eseguendo il comando:

$ ./build_kernel.sh

Alla fine nella directory deploy dovremo ottenere diversi file: uno chiamato 3.8.0-bone4.zImage, che è il kernel vero e proprio, e uno chiamato am335x-bone.dtb (nella sottodirectory dtbs) che è invece il file di configurazione del kernel per la nostra BeagleBone.

Copiamoli nella microSD (dopo averla reinserita nel PC host, ovviamente):

$ sudo cp -v deploy/3.8.0-bone4.zImage /media/boot/zImage
$ sudo cp -v deploy/dtbs/am335x-bone.dtb /media/boot/

Ok, ora proviamo a far partire il kernel. Reinseriamo la microSD nella BeagleBone e diamo i seguenti comandi ad u-boot:

U-Boot# setenv bootargs console=ttyO0,115200n8        
U-Boot# fatload mmc 0:1 0x80300000 zImage
U-Boot# fatload mmc 0:1 0x815f0000 am335x-bone.dtb
U-Boot# bootz 0x80300000 – 0x815f0000

## Flattened Device Tree blob at 815f0000
   Booting using the fdt blob at 0x815f0000
   Loading Device Tree to 8fe3a000, end 8fe420db … OK

Starting kernel …

Uncompressing Linux… done, booting the kernel.
[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Initializing cgroup subsys cpu
[    0.000000] Linux version 3.8.0-bone4 (giometti@hulk) (gcc version 4.6.3 (Ubu
ntu/Linaro 4.6.3-1ubuntu5) ) #1 SMP Wed Feb 20 15:01:16 CET 2013
[    0.000000] CPU: ARMv7 Processor [413fc082] revision 2 (ARMv7), cr=10c5387d
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instructio
n cache
[    0.000000] Machine: Generic AM33XX (Flattened Device Tree), model: TI AM335x
 BeagleBone
[    0.000000] Memory policy: ECC disabled, Data cache writeback
[    0.000000] AM335X ES1.0 (neon )

Perfetto! Funziona anche questo. Ora ci manca solo il rootfs. Quello lo possiamo scaricare già bello e pronto con:

$ wget -c http://rcn-ee.net/deb/minfs/wheezy/debian-wheezy-minimal-armhf-2013-02-17.tar.xz

Quindi non ci resta che installarlo nella microSD. Rimettiamola nel PC host e diamo i comandi:

$ tar xJf debian-wheezy-minimal-armhf-2013-02-17.tar.xz
$ sudo tar xfvp debian-wheezy-minimal-armhf-2013-02-17/armhf-rootfs-debian-wheezy.tar -C /media/rootfs/

Quindi aggiungiamo anche i moduli del kernel compilati prima:

$ sudo tar xvf deploy/3.8.0-bone4-modules.tar.gz -C /media/rootfs/

In fine dobbiamo solo aggiustare alcuni file di configurazione.

Iniziamo con fstab:

$ sudo mkdir -p /media/rootfs/boot/uboot
$ sudo bash -c ‘cat > /media/rootfs/etc/fstab’
/dev/mmcblk0p2   /           auto   errors=remount-ro   0   1
/dev/mmcblk0p1   /boot/uboot auto   defaults            0   0
[CTRL-D]

Ed aggiungiamo la possibilità del login via seriale modificando la linea:

#T0:23:respawn:/sbin/getty -L ttyS0 9600 vt100

così:

T0:23:respawn:/sbin/getty -L ttyO0 115200 vt102

Ok, ora rimettiamo la microSD nella BeagleBone e diamo i seguenti comandi ad U-Boot:

U-Boot# setenv bootargs console=ttyO0,115200n8 root=/dev/mmcblk0p2 ro rootfstype=ext4 rootwait fixrtc
U-Boot# fatload mmc 0:1 0x80300000 zImage
U-Boot# fatload mmc 0:1 0x815f0000 am335x-bone.dtb
U-Boot# bootz 0x80300000 – 0x815f0000

Se avete fatto tutto giusto dovreste ottenere:

## Flattened Device Tree blob at 815f0000
   Booting using the fdt blob at 0x815f0000
   Loading Device Tree to 8fe3a000, end 8fe420db … OK

Starting kernel …

Uncompressing Linux… done, booting the kernel.
[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Initializing cgroup subsys cpu

e più in basso quando il kernel monta il rootfs sulla microSD:


[    1.956049] EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. O
pts: (null)
[    1.964652] VFS: Mounted root (ext4 filesystem) readonly on device 179:2.
[    1.984484] devtmpfs: mounted
[    1.988250] Freeing init memory: 320K
INIT: version 2.88 booting
[info] Using makefile-style concurrent boot in runlevel S.
[….] Starting the hotplug events dispatcher: udevd[    3.647366] udevd[174]: s
tarting version 175
. ok
[….] Synthesizing the initial hotplug events…done.

e quindi alla fine:

[….] Loading cpufreq kernel modules…done (none).
[….] Starting system message bus: dbus. ok
[….] CPUFreq Utilities: Setting ondemand CPUFreq governor…CPU0…done.
[….] Starting OpenBSD Secure Shell server: sshd. ok

Debian GNU/Linux 7.0 arm ttyO0

arm login:

Fatto! Ora basta inserire l’username root e la password root e si fa login!

Non abbiamo ancora finito però, dobbiamo rendere automatica la fase di boot e per farlo basta aggiungere sulla nostra microSD un file di configurazione per u-boot in modo che questo sappia quali comandi effettuare per lanciare il kernel.

Per farlo basta aggiungere alla microSD un file di testo chiamato uEnv.txt contenente i seguenti comandi di boot:

$ cat /media/boot/uEnv.txt
console=ttyO0,115200n8
mmcroot=/dev/mmcblk0p2 ro
mmcrootfstype=ext4 rootwait fixrtc
 
mmc_load_image=fatload mmc 0:1 0x80300000 zImage
mmc_load_dtb=fatload mmc 0:1 0x815f0000 am335x-bone.dtb
 
mmcargs=setenv bootargs console=${console} root=${mmcroot} rootfstype=${mmcrootf
stype}
mmcboot=run mmc_load_image; run mmc_load_dtb; echo Booting from mmc …

loaduimage=run mmcboot; run mmcargs; bootz 0x80300000 – 0x815f0000

Su Rodolfo Giometti

Ingegnere informatico libero professionista ed esperto GNU/Linux offre supporto per: - device drivers; - sistemi embedded; - sviluppo applicazioni industriali per controllo automatico e monitoraggio remoto; - corsi di formazione dedicati. Manutentore del progetto LinuxPPS (il sottosistema Pulse Per Second di Linux) contribuisce attivamente allo sviluppo del kernel Linux con diverse patch riguardanti varie applicazioni del kernel e dispositivi (switch, fisici di rete, RTC, USB, I2C, network, ecc.). Nei 15+ anni di esperienza su Linux ha lavorato con le piattaforme x86, ARM, MIPS & PowerPC.

Lascia un commento

Utilizzando il sito, accetti l'utilizzo dei cookie da parte nostra. maggiori informazioni

Questo sito utilizza i cookie per fonire la migliore esperienza di navigazione possibile. Continuando a utilizzare questo sito senza modificare le impostazioni dei cookie o clicchi su "Accetta" permetti al loro utilizzo.

Chiudi