Un diverso embedded

Uboot o RedBoot

Immagine slide
  • http://ecos.sourceware.org/redboot/ fa parte di Ecos, che è un sistema operativo open source orientato ai sistemi embedded
  • Esistono però dei bootloader generici, che possono essere adattati a varie configurazioni hardware e CPU
  • Il bootloader spesso è scritto dal produttore del chip o della scheda ed a volte è software proprietario
  • Normalmente questi boot-loader fanno parte di progetti più grandi orientati allo sviluppo embedded

Uboot o RedBoot

Immagine slide

Particolarità dell'embedded

Immagine slide
  • Per questo motivo difficilmente si può utilizzare una distribuzione normale "off the shelf" come la Debian che è disponibile per la maggior parte delle architetture
  • Normalmente una scheda embedded ha poca RAM e poco "disco" (in realtà normalmente della ROM)
  • Anche ammettendo di utilizzare una distribuzione "normale", occorrerà ottimizzarla per ridurne l'imnpegno di disco e di memoria
  • Ma probabilmente anche questo non basta. Occorre usare dei trucchi, come delle applicazioni semplificate, per ridurre l'uso di RAM e disco.

Particolarità dell'embedded

Immagine slide
  • Inoltre normalmente il sistema operativo viene eseguito su di un supporto in sola lettura (in genere una ROM), quindi occorrerà un'installazione simile a quella delle distribuzioni live

μClibc

Immagine slide
  • Potremmo quindi risparmiare molto spazio se invece di usare la libreria completa usassimo una libreria ridotta, che contenesse solo le funzioni realmente necessarie per il nostro sistema
  • Una grossa parte delle funzioni contenute nella libreria glibc standard vengono usate molto di rado e praticamente mai nei sistemi embedded
  • Una libreria C che appunto non contiene tutte le funzioni della libreria standard è μClib (http://www.uclibc.org/)

μClibc

Immagine slide
  • Questa è una versione ridotta ed adattata della libreria glibc standard, adtta per sistemi embedded con poca RAM e poco disco
  • Naturalmente per poter utilizzare µClibc occorre compilare i programmi per µClibc utilizzando versioni adatte di compilatore e linker

Cross-compilazione

Immagine slide
  • Abbiamo visto che per utilizzare µClibc occorre utilizzare compilatori e linker diversi dai normali
  • Le soluzioni sono due: o installiamo un compilatore sulla nostra scheda oppure installiamo sul nostro sistema un compilatore che produca codice per la nostra scheda che chiameremo sistema target
  • Il compilatore ed il linker del nostro sistema producono eseguibili contenenti istruzioni per un processore IA32 o AMD64, vale a dire quello del nostro PC

Cross-compilazione

Immagine slide
  • C'è un motivo ben più importante che ci costringe ad utilizzare compilatori e linker diversi da quelli del nostro sistema per compiare i programmi che andranno sul nostro sistema
  • Se installiamo un compilatore per un diverso microprocessore rispetto a quello del nostro sistema, si dice che stiamo eseguendo una cross-compilazione o del cross-sviluppo
  • La nostra scheda embedded però non monta un processore IA32 o AMD64. Nel nostro caso il processore è della famiglia MIPSel

Differenze Hardware

Immagine slide
  • Essendo basati sullo stesso chip di base (o su chip simili - esistono varie versioni simili del processore video, con caratteristiche leggermente diverse) anche le caratteristiche hardware sono in gran parte simili
  • Entrambi gli apparati presentano un'interfaccia Ethernet e connettori USB sia periferica che host
  • La differenza fondamentale è che l'hard disk è opzionale nell'unità 4Geek mentre è fissa (da 500G nel mio caso) nell'unità Iomega

Differenze Hardware

Immagine slide
  • Questo comporta il fatto che il sistema operativo sia completamente in FLASH nell'uinità 4Geek mentre sia sul disco fisso nell'unità Iomega, lasciando solo il boot loader in flash.
  • Gli apparati differiscono nelle interfacce video: l'unità 4Geek è più ricca; l'unità Iomega manca dell'interfaccia SCART e dell'uscita audio ottica

Dispositivo MTD

Immagine slide
  • Linux può utilizzare una FLASH come dispositivo a blocchi (come fisse un hard disk)
  • Tornando ai nostri sistemi, Iomega ha il sistema completamente basato su disco fisso, utilizzando un filesystem ext3
  • Per quanto riguarda invece il sistema 4Geek, può anche funzionare senza hard disk, quindi tutto il sistema è contenuto nella FLASH da 32M
  • Questa driver implementa la lettura e scrittura nei dispositivi Flash.

Dispositivo MTD

Immagine slide
  • Per usare una flash come disco occorre la driver MTD (Memory Type Device).
  • Un dispositivo può essere suddiviso in partizioni (indivisuate come /dev/mtd0 /dev/mtd1 ...) in vari modi:
    • Tramite una tabella di partizioni RedBoot
    • Tramite parametri passati alla riga di comando del kernel

Bootloader

Immagine slide
  • Nei normali computer, per caricare il sistema operativo si utilizza un boot manager come ad esempio Grub o Lilo.
  • Il boot manager è un piccolo programma che, oltre a presentare un menù d'avvio, si occupa di leggere il file con il sistema operativo (vmlinuz) in memoria, caricare eventualmente un'immagine d'avvio initrd ed invocare il kernel passandogli una serie di parametri.
  • Nei sistemi embedded c'è qualcosa di simile, ma non è sul disco come Lilo o Grub. E' registrato in una rom o nella stessa flash dove ci sono le partizioni MTD.

Bootloader

Immagine slide
  • Questo bootloader in genere è molto più potente di Grub o Lipo perché normalmente consente anche di programmare la flash con una nuova immagine di file system, di configurare l'interfaccia di rete e di fare altre operazioni.
  • Per fare queste operazioni si deve collegare un'interfaccia seriale alla scheda, per poter impartire comandi al bootloader ed eventualmente per scaricare nella scheda il file system da registrare in flash.
  • Nel nostro caso (come in molti altri) la seriale è implementata direttamente nel micro, ma occorre aggiungere esternamente un transceiver che adatti le tensioni a quelle di una normale RS232

Compilazione residente

Immagine slide
  • Avendo un sistema con una buona disponibilità di disco fisso, sebbene in genere lento, possiamo anche pensare di compilare i programmi direttamente sul dispositivo
  • In questo caso sarebbe utile avere un sistema operativo "full featured".
  • Visto che in genere non è possibile avere un sistema dual boot, possiamo pensare di avere il nostro sistema in una sottodirectory ed eseguirlo con il comando chroot

Compilazione residente

Immagine slide
  • In questo modo potremo caricare tutti i pacchetti che ci servono, anche se potranno girare solo nell'ambiente chroot Debian.
  • Se usiamo un sistema Debian, che è disponibile per le principali architetture usate nei sistemi embedded, possiamo usare il pacchetto debootstrap per creare la directory con il sistema
  • Ancora avremo bisogno di procurarci una toolchain, visto che dovremo compilare eseguibili per librerie diverse da quelle di Debian (µClibc invece che glibc)

Toolchain

Immagine slide
  • Occorre poi avere i file di intestazione (header file) e le librerie di sviluppo per la libreria µClibc e le sue librerie correlate
  • Se ci riferiamo ad un sistema GNU (Linux) ci serviranno le GNU binutils, la GNU Compiler Collection GCC, e uClibc
  • In realtà per produrre un eseguibile, che faccia riferimento a delle librerie dinamiche non basta il compilatore
  • L'insieme degli eseguibili e delle librerie, compilati per produrre codice per l'architettura target, prende il nome di toolchain

Toolchain

Immagine slide
  • Occorre almeno un linker, che colleghi tra loro i vari file compilati in un singolo eseguibile
  • Le librerie di sviluppo sono librerie statiche che non contengono di fatto il codice delle funzioni che contengono, ma solo un riferimento alle librerie dinamiche che lo contengono.

Quale Embedded

Immagine slide
  • Oppure possiamo rivolgerci ai box multimediali, che spesso montano già un Linux di serie
  • Oppure possiamo procurarci un access point wireles, come il WRT54GL della Linksys e caricarvi Linux usando OpenWRT
  • Normalmente quando si parla di embedded si pensa ad una bella scheda a microprocessore, collegata con una serie di interfacce a chissà che cosa
  • Insomma, si pensa a realizzare qualcosa di più elettronico che informatico, di costruire un controllo

Quale Embedded

Immagine slide
  • In realtà noi possiamo comprare un sacco di embedded già pronto da programmare
  • Per esempio possiamo comprare un telefonino e scrivere applicazioni Java da scaricarvi

Caratteristiche Hardware

Immagine slide
  • Nel mio caso, ho rivolto la mia attenzione a due box multimediali: il Medley+ della 4geek ed lo ScreenPlay Pro HD di Iomega
  • Entrambi sono box multimediali in grado di registrare un segnale TV analogico dall'esterno e di riprodurre un'ampia serie di formati video, prelevati da varie sorgenti, su di un TV tramite varie uscite tra cui l'HDMI
  • Per questo processore Realtek stessa distribuisce un sistema operativo Linux preconfigurato, purtroppo non Open Source

Caratteristiche Hardware

Immagine slide
  • Entrambi gli apparati sono basati sul processore video Realtek RTD1281 che contiene un encoder/decoder MPEG hardware ed un core MIPS

Libreria C standard - glibc

Immagine slide
  • Una grossa parte della memoria e del disco sono utilizzati dalla libreria standard del C glibc
  • Quando noi compiliamo un programma, le funzioni standard che noi richiamiamo, come ad esempio la printf, non vengono aggiunte in coda all'eseguibile, ma viene messo nell'eseguibile un riferimento alla libreria standard dinamica del C
  • In questo modo, quando lancio più programmi, non devo ricaricare ogni volta il codice delle funzioni standard ma invece carico una volta sola la libreria dinamica con un grande risparmio di memoria.

Libreria C standard - glibc

Immagine slide
  • Il problema è che la libreria standard contiene centinaia di funzioni che svolgono i compiti più diversi.

Shell e comandi fondamentali

Immagine slide
  • A ben guardare, i vari piccoli programmi condividono una serie di funzioni di servizio con la shell, come ad esempio quelle che analizzano i parametri a riga di comando o leggono e interpretano la riga immessa dall'utente
  • Normalmente nei sistemi Linux tradizionali la shell è un programma abbastanza impegnativo e complesso, in genere è bash
  • Inoltre c'è sempre un comando fondamentale chiamato shell, che serve per dare comandi da riga di comando o eseguire gli script di configurazione all'avvio.

Shell e comandi fondamentali

Immagine slide
  • Per prima cosa, Linux ha una lunga serie di piccoli comandi che eseguono operazioni fondamentali come creare e cancellare directory o montare volumi.

Lavorare con JFFS2

  • Per creare un'immagine di file system JFFS2 da scaricare in una partizione del target esiste il comando mkfs.jffs2 appartenente al pacchetto Debian mtd-utils
  • Questo comando prende un'albero di directory e crea un'immagine di file system jffs2 che contiene l'albero stesso.
  • Purtroppo non esiste un comando che estragga dal file immagine l'albero di directory contenuto
  • Di più, il file system jffs2 pretende un dispositivo di tipo mtd per funzionare, quindi non funziona nemmeno col il dispositivo loop per montare direttamente il file immagine, come si fa con i CD-ROM

File System Squashfs

  • Per poter fare stare un sistema operativo in una memoria così piccola, occorre usare un file system compresso.
  • Abbiamo visto che il sistema 4Geek deve fare stare l'intero sistema nella è FLASH da 32M
  • Squashfs è un file system compresso in sola lettura, ottimizzato per essere scritto in una ROM
  • La maggior parte del file system non va normalmente scritta in un sistema che si comporta di fatto come una distribuzione live

Lavorare con Squashfs

  • Il sistema target dovrà montare il file system Squashfs per poterlo usare, quindi dovrà possedere un modulo adeguato nel suo kernel
  • Se vogliamo modificare il file system del nostro sistema target non ci servirà montare il file system nel sistema host (tanto è in sola lettura e non potremmo modificarlo)
  • La soluzione migliore è quella di scompattarlo in una directory (un albero di directory), modificare i file nella directory e poi ricompattarlo.
  • I programmi per fare questo sono contenuti nel pacchetto Debian squashfs-tools

Lavorare con Squashfs

  • Con il programma unsquashfs potremo scompattare la nostra immagine.
  • Con il programma mksquashfs potremo prendere il contenuto della nostra directory e ricostruire l'immagine del file system

Montare e copiare un file system JFFS2

  • Per operare con un file system JFFS2 occorre prima di tutto creare un dispositivo di tipo MTD in memoria
  • Occorre poi copiare l'immagine del file system JFFS2 nel dispositivo
  • A questo punto potremo montare il dispositivo ed accedere ai file

Montare e copiare un file system JFFS2

  • I comandi per fare queste operazioni sono:
    modprobe mtd
    modprobe jffs2
    modprobe mtdram total_size=<dimensione_disco_in_Kb> erase_size=256
    modprobe mtdchar
    modprobe mtdblock
    dd if=<file_immagine.jffs2> of=/dev/mtd0
    mount -t jffs2 /dev/mtdblock0 /mnt

Busybox

Immagine slide
  • Un'idea per risparmiare spazio su disco e memoria è quello di creare una shell semplificata che contenga anche il codice di una serie di piccoli comandi (magari semplificati anch'essi)
  • Questa shell esiste e si chiama busybox (http://www.busybox.net/)
  • Dato che molti script di shell fanno riferimento direttamente al nome del file dei vari comandi come rm mkdir ecc, tutti i nomi di questi comandi sono collegati (in genere con hard link) a busybox

Busybox

Immagine slide
  • Dato che in Linux un programma può conoscere con che nome è stato invocato, busybox sa se, ad esempio, è stato invocato con il nome "mount" ed in questo caso esegue solo le operazioni di mount e termina.

Loader

Immagine slide
  • Nel nostro caso invece, almeno in un primo momento, possiamo fare uso dell'hard disk del sistema e della sua connessione di rete
  • Utilizzando i programmi sul dispositivo (ad esempio wget), la condivisione del disco (l'Iomega funziona come NAS con un server SAMBA) oppure collegandolo come disco USB al PC possiamo copiare il programma compilato sull'hard disk del dispositivo
  • Una volta spostato il programma sul dispositivo, possiamo eseguirlo come più ci piace e copiarlo dove vogliamo.

Loader

Immagine slide
  • Nei sistemi embedded "classici" si utilizzano dei "rom emulator" oppure si programma la flash di sistema tramite una connessione seriale ed un software adeguato, generalmente il bootloader
  • Nei sistemi embedded, una volta compilato il programma che ci interessa si pone il problema di trasferirlo sul nostro sistema target

Filesystem JFFS2

  • In genere il nostro sistema avrà bisogno di memorizzare nella flash dei dati (la configurazione).
  • Il file system Squashfs è in sola lettura, quindi non ci consente di registrare dati
  • Potremmo formattare una "partizione" della flash con un file system tradizionale, ma avrebbe prestazioni scarse e soprattutto scarsa durata (la flash ha un numero limitato di scritture disponibili)
  • La soluzione è quella di usare JFFS2 (Journal Flash File System 2).

Filesystem JFFS2

  • JFFS2 è un file system journaled (come ext3) ottimizzato per usare una FLASH come supporto.
  • Le sue principali caratteristiche sono di comprimere i dati e di usare a rotazione i blocchi della flash, in modo da spargere le scritture sull'intero dispositivo, minimizzandone il numero
[any material that should appear in print but not on the slide]