ARM

Come modificare il modulo brain & vision di I-droid01


Non mi assumo nessuna responsabilita' per danneggiamenti, perdita di dati o danni personali come risultato diretto o indiretto dell'uso delle informazioni contenute in queste pagine. Questo materiale e' fornito cosi' com'e' senza nessuna garanzia implicita o esplicita.


work in progress

Attenzione: questa pagina non e' ancora finita! Il lavoro e' ancora in corso.

work in progress

Home
Hardware
Software

Abstract
Test preliminare
La toolchain
Il bootloader
Installare u-boot
Linux kernel
Board pinout
Download
Links
FAQ
Contatti

Abstract

Questa pagina spiega come modificare il modulo brain & vision di I-droid01, distribuito in Italia ba DeAgostini e come riutilizzarla nei tuoi progetti. Il modulo di I-droid01 (ora scheda ARM) e' basato su un microprocessore Freescale MC9328MXL, sulla scheda ci sono inoltre una RAM da 16MB e una Flash da 16MB per immagazzinare il firmware. Vedremo come costruire un kernel Linux per questa scheda, come collegarla alla Linux box, come caricare il file immagine nella Flash e come bootare. Alla fine dovremmo avere una nuova Linux box nella scheda stessa.

Test preliminare

La scheda che tieni in mano e' un concentrato di potenza in grado di fare qualunque cosa tu possa immaginare (e anche di piu'): e' basata su un microprocessore Freescale MC9328MXL, un microprocessore ARM con un clock a 150MHz, equipaggiato con 16MB di RAM e 16MB di Flash.
Prima di fare qualsiasi altra cosa hai bisogno di qualche strumento: hai bisogno di un convertitore RS232-TTL e della mia versione di miniterm (sei libero di usare il tuo emulatore di terminale preferito ma io preferisco il mio).
Procediamo!

1) Collega il convertitore RS232-TTL alla linea seriale come mostrato in figura. I pins 4 e 5 sul connettore seriale sono i segnali RTS e CTS, per il momento non abbiamo bisogno dell'handshake quindi collegali tra di loro.

2) Collega il lato RS232 del convertitore RS232-TTL alla tua Linux box utilizzando un cavo pin to pin (in questo esempio /dev/ttyS0).

3) Chiudi il jumper di programmazione al centro della scheda ARM.

4) Avvia miniterm, in questo momento non ci interessa la velocita' del collegamento, quindi digita:

$ miniterm -d /dev/ttyS0

5) Alimenta la scheda ARM con un alimentatore stabilizzato a 3.3V. Attenzione la tensione deve essere molto precisa, se usi un classico alimentatore a 5V puoi distruggere la scheda. I microprocessori ARM necessitano di un'alimentazione a 3.3V, se non hai una sorgente stabilizzata a 3.3V puoi pensare di cannibalizzare un alimentatore per PC e utilizzare l'uscita a 3.3V per alimentare la scheda. In questo caso ricordati di caricare l'uscita a 3.3V dell'alimentatore con una resistenza da 5.6ohm o meno per evitare che l'alimentatore si spenga per mancanza di carico. Misura la tensione in uscita con un voltmetro digitale prima di alimentare la scheda.

6) Premi il tasto a, dovresti leggere il carattere : (duepunti). Se funziona sei a posto!
Il bootstrap loader presente all'interno dell'MC9328MXL ha ricevuto la tua a, ha individuato la velocita' della linea ed ha risposto con : (duepunti).

Ora sei pronto per il prossimo passo: scaricare ed installare una toolchain per microprocessori ARM, scaricare e compilare un bootloader, caricarlo sulla scheda, giocare un po' con esso, scaricare e compilare il kernel di Linux, caricare il kernel di Linux sulla scheda, caricare il filesystem, caricare altri sfronzoli, riavviare...
...niente panico! Porcederemo passo per passo.

La toolchain

Ci sono due modi per installare una toolchain per microprocessori ARM:

Primo
Andare alla pagina di Phil Blundell e seguire le sue istruzioni per installare una toolchain per ARM.

Secondo
Continuare a leggere questa pagina e seguire la mia esperienza, ovviamente io preferisco questa via.
Se il tuo gcc e' gia' aggiornato puoi saltare il passo 2 e passare direttamente dal passo 1 al 3, altrimenti se hai bisogno di aggiornare il gcc o non ce l'hai per niente, segui tutti i passi. Attenzione: la documentazione ufficiale del gcc raccomanda di utilizzare lo stesso gcc per compilare un cross compiler, questo significa compilare gcc due volte. Io mi riferiro' a gcc-3.2.3 ma tu puoi installare qualsiasi versione.

1) Scarica gcc-3.2.3.tar.gz in /usr/local/src

$ cd /usr/local/src
$ tar -zxvf gcc-3.2.3.tar.gz

2) Installa gcc come compilatore C nativo:

$ mkdir gcc-3.2.3-build
$ cd gcc-3.2.3-build
$ /usr/local/src/gcc-3.2.3/configure --prefix=/usr/local/gcc-3.2.3 --enable-languages=c++,c
$ make CFLAGS='-O' LIBCFLAGS='-g -O2' LIBCXXFLAGS='g -O2 -fno-implicit-templates' bootstrap
$ make install (come root)

Attenzione: prima di installare gcc devi installare (o aggiornare) le binutils; io ho saltato questo passaggio perche' nel mio sistema le avevo gia' aggiornate per altri motivi, in caso di dubbio puoi consultare il manuale di gcc.

3) Scarica binutils-2.17.tar.gz (o superiore) in /usr/local/src

$ tar -zxvf binutils-2.17.tar.gz
$ mkdir binutils-2.17-build-arm
$ cd binutils-2.17-build-arm
$ /usr/local/src/binutils-2.17/configure --target=arm-elf --prefix=/usr/local/gcc-3.2.3-arm --program-prefix=arm-
$ make
$ make install

4) Ricompila gcc per ARM:

$ cd /usr/local/src
$ mkdir gcc-3.2.3-build-arm
$ cd gcc-3.2.3-build-arm
$ /usr/local/src/gcc-3.2.3/configure --target=arm-elf --prefix=/usr/local/gcc-3.2.3-arm --program-prefix=arm- --disable-threads --disable-shared --with-newlib --enable-languages=c,c++
$ make
$ make install

5) Scarica newlib-1.15.0.tar.gz in /usr/local/src

$ tar -zxvf newlib-1.15.0.tar.gz
$ mkdir newlib-1.15.0-build-arm
$ cd newlib-1.15.0-build-arm
$ /usr/local/src/newlib-1.15.0/configure --target=arm-elf --prefix=/usr/local/gcc-3.2.3-arm --program-prefix=arm- --enable-target-optspace
$ make
$ make install

Attenzione: io ho avuto qualche problema durante l'installazione della newlib seguendo parola per parola questo processo: ho dovuto creare alcuni link nel mio /usr/local/gcc-3.2.3-arm/bin per far si che i binari apparissero come arm-elf-nomefile e non come arm-nomefile. Una soluzione migliore potrebbe essere quella di usare --program-prefix=arm-elf- nei passi 3 e 4.

Ora dovresti avere una toolchain per microprocessori ARM funzionante.
Il prossimo passo sara' compilare un bootloader per la nostra scheda e caricarlo.

Un altro esempio
Ecco un'altro esempio di toolchain per ARM basata su gcc-3.3.5 (gcc-3.3.5 era gia' installato come compilatore di sistema):

$ cd
$ mkdir build $ cd build $ wget ftp://ftp.gnu.org/gnu/binutils/binutils-2.17.tar.gz
$ wget ftp://ftp.lip6.fr/pub/gcc/releases/gcc-3.3.5/gcc-3.3.5.tar.gz
$ wget ftp://sources.redhat.com/pub/newlib/newlib-1.15.0.tar.gz
$ tar -zxvf binutils-2.17.tar.gz
$ mkdir binutils-2.17-build-arm
$ cd binutils-2.17-build-arm
$ ../binutils-2.17/configure --target=arm-thumb-elf --prefix=/usr/local/gcc-3.3.5-arm --program-prefix=arm-
$ make
$ make install
$ cd $HOME/build
$ export PATH=$PATH:/usr/local/gcc-3.3.5-arm/bin
$ tar -zxvf gcc-3.3.5.tar.gz
$ mkdir gcc-3.3.5-build-arm
$ cd gcc-3.3.5-build-arm
$ ../gcc.3.3.5/configure --target=arm-thumb-elf --prefix=/usr/local/gcc-3.3.5-arm --program-prefix=arm- --disable-threads --disable-shared --with-newlib --enable-languages=c
$ make
$ make install
$ cd /usr/local/gcc-3.3.5-arm/bin
$ ln -s arm-thumb-elf-cpp arm-cpp
$ ln -s arm-thumb-elf-gcc arm-gcc
$ ln -s arm-thumb-elf-gcc-3.3.5 arm-gcc-3.3.5
$ ln -s arm-ar arm-thumb-elf-ar
$ ln -s arm-as arm-thumb-elf-as
$ ln -s arm-nm arm-thumb-elf-nm
$ ln -s arm-ld arm-thumb-elf-ld
$ ln -s arm-ranlib arm-thumb-elf-ranlib
$ export PATH=$PATH:/usr/local/gcc-3.3.5-arm/bin
$ cd $HOME/build
$ tar -zxvf newlib-1.15.0.tar.gz
$ mkdir newlib-1.15.0-build-arm
$ cd newlib-1.15.0-build-arm
$ ../newlib-1.15.0/configure --target=arm-thumb-elf --prefix=/usr/local/gcc-3.3.5-arm --program-prefix=arm- --enable-target-optspace
$ make
$ make install

Il bootloader

Qualcuno potrebbe chiedere: Perche' abbiamo bisogno di un bootloader? Se vuoi installare ed eseguire un'applicazione custom, senza usare un vero sistema operativo, si puo' fare senza usare un bootloader. In questo caso la Flash conterra' solo la tua applicazione e nient'altro, quindi il processore eseguira' solo questo codice.
Se vuoi caricare ed eseguire un vero sistema operativo come Linux hai bisogno di un bootloader, il bootloader ha due funzioni: prima di tutto puo' essere usato come debugger, ti fornisce un interprete dei comandi che puo' eseguire alcune operazioni come visualizzare il contenuto della memoria, scrivere del codice nella Flash, caricare codice o immagini della memoria, etc. Secondo puo' avviare il kernel di Linux, questa cosa puo' essere fatta in modi diversi: per esempio il kernel puo' essere caricato dalla Flash e scompattato nella RAM, oppure puo' risiedere su una memory stick, caricato da li e scompattato nella RAM. Alcuni bootloader possono scaricare l'immagine del kernel da un server TFTP o caricarlo da disco fisso. Come puoi vedere lo scenario e' molto ampio, l'unico limite e' la tua immaginazione.
Possiamo dire che un bootloader puo' aiutarti qualsiasi uso tu abbia in mente quer questa scheda.

Ci sono molti bootloader che puoi utilizzare nelle tue applicazioni embedded, ecco qui una piccola lista:

Non tutti i link in questa lista sono affidabili, qualche link potrebbe puntare alla pagina sbagliata.

Io sto' usando u-boot nei miei esperimenti, quindi questa pagina illustrera come utilizzare questo bootloader con la scheda di I-Droid01.
Quindi andiamo a creare la nostra imagine di u-boot.

1) Crea un nuovo albero per i files ARM nella tua home directory:

$ cd
$ mkdir -p micro/mc9328mx1/src
$ cd micro/mc9328mx1/src

2) Scarica u-boot in $HOME/micro/mc9328mx1/src

$ bunzip2 u-boot-1.1.6.tar.bz2
$ tar -xvf u-boot-1.1.6.tar

3) Scarica la mia patch (la puoi rovare nella sezione download) in $HOME/micro/mc9328mx1/src ed applicala:

$ patch -p0 < u-boot-1.1.6-idroid-patch-0.02.diff

Questo modofichera' alcuni files di configurazione per permettere ad u-boot di girare sulla ARM board.
Prima di compilare u-boot controlla che nel file u-boot-1.1.6/include/configs/mx1ads.h queste due righe non siano commentate:

        #define CONFIG_SKIP_LOWLEVEL_INIT	1
	#define CONFIG_SKIP_RELOCATE_UBOOT	1
      

4) Compila u-boot:

$ mkdir u-boot-1.1.6-build-arm
$ cd u-boot-1.1.6
$ export CROSS_COMPILE=arm-elf-
$ export BUILD_DIR=$HOME/micro/mc9328mx1/src/u-boot-1.1.6-build-arm
$ make mx1ads_config
$ make all

Ora dovresti avere una qualche immagine di u-boot nel tuo build tree.

5) Caricare u-boot. Hai bisogno di mxldump per caricare u-boot sulla scheda, vai alla software page e installalo, quindi torna subito qui.
Hai bisogno anche di un'altra cosa per caricare qualsiasi software sulla scheda ARM: hai bisogno di avviare il ciclo di rinfresco della RAM.
Sulla scheda ARM ci sono una memoria Flash ed una RAM, la Flash e' come una ROM e questo non e' un problema, la RAM e' una RAM dinamica mappata ad un preciso indirizzo. Il problema e' che una RAM dinamica deve essere rinfrescata e che in questo momento non c'e' nessuno sulla scheda che sappia dov'e' questa RAM e come funziona.
Se vuoi mettere del codice nella RAM della scheda devi inizializzarla e rinfrescarla.
Questo processo dipende dall'hardware, questo significa che abbiamo bisogno di una procedura per rinfrescare questa RAM in questa scheda. Io ho sniffato la sequenza originale utilizzata per caricare il firmware di I-Droid01 sulla scheda, la sequenza di caricamento incomincia con questo codice:

	00220000C400400C01	; CS0U
	00220004C411110C01	; CS0L
	00221000C491020200	; pre-charge command
	08200000E4		; special read
	00221000C4A1020200	; auto-refresh command
	08000000E4		; 8 special read
	08000000E4		; 8 special read
	08000000E4		; 8 special read
	08000000E4		; 8 special read
	08000000E4		; 8 special read
	08000000E4		; 8 special read
	08000000E4		; 8 special read
	08000000E4		; 8 special read
	00221000C4B1020200	; set mode register
	08088C00E4		; special read
	00221000C481028200	; set normal mode
      

Questa e' una serie di B-records spediti al firmware loader per scrivere e leggere alcuni registri del microprocessore. Se vuoi puoi scaricare raminit.raw qui.
Accendi la tua ARM board e da un terminale digita:

$ cd u-boot-1.1.6-build-arm
$ export MXLDUMP_SPD=8
$ export MXLDUMP_DEV=/dev/ttyS0
$ mxlsync
$ mxlraw < raminit.raw
$ mxlwrite -a 0x08400000 < u-boot.bin
$ mxlexec -a 0x08400000 ;miniterm -s 6 -d /dev/ttyS0

Questa procedura eseguira' i seguenti passi:

  • sincronizzare il loader presente nel micro.
  • avviare il ciclo di refresh della RAM (senza di questo non hai una RAM).
  • caricare il codice di u-boot.
  • eseguire u-boot.
  • eseguire miniterm.
Ora sei pronto per la tua prima esperienza con u-boot, prova i comandi, devi prendere familiarita' con u-boot prima di installare il kernel di Linux.
Se tutto va bene il prossimo passo sara' installare il codice di u-boot nella memoria flash, in modo che u-boot rimanga residente sulla ARM board.


alert

Attenzione: u-boot sta funzionendo ma c'e' un piccolo problema con la flash eprom: la memoria flash montata su questa scheda e' diversa dalla flash montata sulla scheda ADS. u-boot ha un driver solo per quest'ultima e non funziona con la nostra.
Questo significa che non puoi programmare la flash utilizzando u-boot come indicato nel capitolo Installare u-boot, dovresti riscrivere il driver per la memoria flash. In questo momento sto lavorando alla soluzione ma ho molti problemi e poco tempo. Se stai leggendo questo avviso allora non ho ancora rimpiazzato il driver per la flash. Qui puoi trovare alcune note riguardo come modificare u-boot.

alert

Installare u-boot

Prima di tutto devi ricompilare u-boot, quindi commenta queste due righe in include/configs/mx1ads.h e ricompila u-boot

        #define CONFIG_SKIP_LOWLEVEL_INIT	1
	#define CONFIG_SKIP_RELOCATE_UBOOT	1
      

Ora dovresti avere due versioni leggermente differenti di u-boot: la prima e la stessa senza le due linee sopra. Chiameremo la prima verione ram-only-u-boot.bin e la seconda versione final-u-boot.bin.
Ora resetta la scheda e digita:

$ mxlsync
$ mxlraw < raminit.raw
$ mxlwrite -a 0x08400000 < ram-only-u-boot.bin
$ mxlwrite -a 0x08420000 < final-u-boot.bin
$ mxlexec -a 0x08400000 ;miniterm -s 6 -d /dev/ttyS0
MXL$ ...(continua)

Spegni la scheda ARM, rimuovi il jumper di programmazione e riaccendi la scheda: u-boot dovrebbe partire.
Ora abbiamo la scheda con u-boot installato, il prossimo passo sara' costruire un kernel di Linux e installarlo sulla scheda.

Linux kernel

Il prossimo passa e' costruire, caricare ed eseguire il kernel di Linux; questo puo' essere un pochino complicato da fare e sicuramente lungo da spiegare, cosi' l'ho spostato in un'altra pagina completamente dedicata al kernel di Linux e al filesystem. Se sei interessato clicca qui.

Board pinout

Applicando una tecnica di reverse engineering ho trovato la piedinatura completa della scheda, se sei interessato la puoi trovare qui.


work in progress

Warning: questa pagina non e' ancora finita! Il lavoro e' ancora in corso.

work in progress

Download

Puoi scaricare tutti i files relativi al progetto ARM diretamente da qui.

mxldump-0.05.tar.gz Firmware management suite per il microprocessore MC9328MXL.
MXL-datasheets.tar.bz2 Datasheets ufficiali dell'MC9328MXL.
ADS-schematics.tar.gz MC9328MXL ADS board schematics.
u-boot-1.1.6-idroid-patch-0.02.diff
dab99952044e2aef6fb904e84577d6c2
U-boot patch: modifica i files di configurazione della board mx1ads per adattare u-boot al nuovo hardware.
u-boot-1.1.6-idroid-patch-0.03.diff
ab37704e768f29808a7a4b3bbc918d06
U-boot patch: aggiunti i probes per controllare l'esecuzione dei programmi ed un nuovo comando per gestire direttamente dalla riga di comando lo stato dei probes: i probes utilizzano le 6 linee del connettore J3, col comando probe puoi cambiare lo stato delle linee.

Ricorda di applicare solo l'ultima patch disponibile ad un codice sorgente pulito con lo stesso numero di versione, non applicare mai piu' di una patch alla volta.

Come applicare una patch

Per applicare o creare una patch segui questi passi: io assumo che sia u-boot-1.1.6 la directory contenente i sorgenti originali di u-boot e u-boot-1.1.6-modified la directory contenente i sorgenti modificati.
Prima di creare la patch testa le tue modifiche.

Per creare la patch digita:
$ diff -r -C 3 u-boot-1.1.6 u-boot-1.1.6-modified > u-boot-1.1.6-idroid-patch-0.02.diff

Per applicare la patch digita:
$ patch -p0 < u-boot-1.1.6-idroid-patch-0.02.diff

Per verificare la patch digita:
$ diff -rq u-boot-1.1.6 u-boot-1.1.6-patched

Links

Alcuni link utili riguardo questo progetto:

binutils binutils ftp repository.
GCC GCC homepage.
newlib newlib homepage.
u-boot u-boot repository presso sourceforge.
ARM Linux porting del kernel di Linux per varie architetture ARM.
uClinux La homepage del progetto uClinux: linux per mcroprocessori che non hanno la MMU.
brain & vision descrizione del modulo brain & vision e links ai data sheets.

FAQ

Q:
A:

Contatti

Se hai delle domande, suggerimenti, problemi, etc. puoi contattami a questo indirizzo: bit.trapper@gmail.com

Ultimo aggiornamento: 29 Dic 2012


Questo sito e' stato realizzato interamente con vim.
Grazie a tutta la comunita' open source, alla free software foundation e chiunque scriva software libero.