Introducción
Como he comentado anteriormente, u-boot es un bootloader totalmente libre para dispositivos empotrados de bajo poder computacional. Entre sus múltiples posibilidades, están las de particionar la memoría flash del dispostivo en el que se encuentre corriendo, asignar nombre a dichas particiones, cargar imágenes en RAM desde distintas fuentes, volcarlas a flash, y un largo etcétera….
Aquí hablaré de las opciones que a mi juicio pueden ser mas socorridas para la instalación de un Sistema Operativo en un dispositivo empotrado, en mi caso, tomando como ejemplo la tarjeta de desarrollo mini2440 comentada anteriormente, aunque como es de suponer, las mismas operaciones pueden ser realizadas en distintas plataformas hardware.
Así pues vamos a lo divertido del asunto ¡¡Empezamos!!
Instalando
El proceso de instalación de u-boot consiste básicamente en cargar una imagen de u-boot en la RAM de nuestrá máquina, bien a través de su propio bootloader, bien a través de un JTAG. Una vez cargado en RAM, se lanza y se le dice que se (auto)guarde en la flash de nuestra tarjeta. En este caso y dependiendo de nuestro hardware, puede sobreescribir a su bootloader original o bien coexistir con él. En cualquier caso, deberás consultar el manual de tu tarjeta para comprobarlo.
Para el caso de la MINI2440, ésta viene con dos memorias Flash distintas: por un lado hay una flash NOR de 2MB en la que se encuentra almacenado el bootloader específico para los micros de Samsung (mirco de mi tarjeta de desarrollo): supervivi. Por otro lado, tenemos una memoria flash NAND de 128MB en la que se supone que irá nuestro sistema. En ésta memoria será en la que instalaremos u-boot, configurando posteriormente nuestra mini2440 para que arranque desde ahí (utilizando un conmutador que a tal efecto lleva instalado).
Para comenzar, necesitaremos descargarnos tanto el código fuente de u-boot como el software necesario para poder comunicarnos con supervivi y un compilador cruzado para ARM:
* u-boot:
-
javieralso@rigoberto:~$ mkdir uboot; cd uboot
-
javierlaso@rigoberto:~$ git clone git://repo.or.cz/u-boot-openmoko/mini2440.git
-
* toolchain: Compiladores cruzados para ARM los hay muchos en esto de GNU. Yo, que seguí al dedillo todo lo que leí en montónes de blogs, usé el siguiente:
-
javieralso@rigoberto:~$ wget http://www.codesourcery.com/sgpp/lite/arm/portal/package3696/public/arm-none-linux-gnueabi/arm-2008q3-72-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
-
javieralso@rigoberto:~$ unp arm-none-linux-gnueabi/arm-2008q3-72-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
-
javieralso@rigoberto:~$ export PATH=$PATH:/home/rigoberto/arm-2008q3/bin
* Friendlyarm package: Se trata de un paquete con un uploader ya compilado para comunicarse con supervivi y de una imagen ya compilada de u-boot, que deberemos utilizar para cargar la imagen que compilemos nosotros. El por qué de usar dos imágenes de u-boot se explicará mas adelante.
-
javieralso@rigoberto:~$ wget http://www.kernelconcepts.de/~fuchs/micro2440/friendlyarm2440-package.tar.bz2
-
javieralso@rigoberto:~$ unp friendlyarm2440-package.tar.bz2
Una vez que lo tenemos todo descargado, empezaremos por compilar el bootloader, para ello no debemos olvidar añadir a nuestro PATH la ruta en la que se encuentran los binarios de la toolchain que usemos (como hicimos anteriormente). Una vez hecho esto, podemos pasar a compilar:
-
javieralso@rigoberto:~$ cd uboot/mini2440
-
javieralso@rigoberto:uboot/mini2440$ export CROSS_COMPILE=arm-none-linux-gnueabi-
-
javieralso@rigoberto:uboot/mini2440$ make mini2440_config; make
Después de no mucho tiempo y si todo ha ido bien, deberemos tener un archivo llamado u-boot.bin en la carpeta donde hemos llevado a cabo la compilación. Esa es la imagen de u-boot que se almacenará en la flash de nuestra tarjeta, pero para poder llevar a cabo dicho proceso, necesitaremos otra versión de u-boot (sé que suena bastante raro, y de hecho lo es. Mas adelante explicaré el por qué de ello).
Bueno, llegados a este punto, cogemos nuestra mini2440, deslizamos el conmutador superior hacia la izquierda (para configurar el arranque desde la NOR), conectamos un módem nulo desde su puerto serie a un puerto serie de nuestra máquina y el device USB a un puerto USB libre. Tras ésto, arramcamos minicom y configuramos el puerto serie a 115200 Baudios, 8N1 y sin ningún tipo de contol de flujo.
Hecho ésto, solo queda encender nuestra tarjeta y comprobar que supervivi arranca:
-
##### FriendlyARM BIOS for 2440 #####
-
[x] bon part 0 320k 2368k
-
[v] Download vivi
-
[k] Download linux kernel
-
[y] Download root_yaffs image
-
[c] Download root_cramfs image
-
[a] Absolute User Application
-
[n] Download Nboot
-
[e] Download Eboot
-
[i] Download WinCE NK.nb0
-
[w] Download WinCE NK.bin
-
[d] Download & Run
-
[z] Download zImage into RAM
-
[g] Boot linux from RAM
-
[f] Format the nand flash
-
[p] Partition for Linux
-
[b] Boot the system
-
[s] Set the boot parameters
-
[t] Print the TOC struct of wince
-
[u] Backup NAND Flash to HOST through USB(upload)
-
[r] Restore NAND Flash from HOST through USB
-
[q] Goto shell of vivi
-
Enter your selection:
Seleccionamos la opción q para acceder a la shell de superivi y después le diremos que queremos cargar una imagen en la memoria y arrancar, pero para ello, antes deberemos saber cuando ocupa el bootloader que vamos a cargar (el que ya viene compilado), así que volvemos a la carpeta en la que lo descomprimimos y lo comprobamos:
-
javieralso@rigoberto:friendlyarm2440-package$ ls -l
-
…………………..
-
…………………..
-
-rwxr-xr-x 1 javieralso javieralso 239016 oct 24 11:38 u-boot.bin
-
…………………..
-
…………………..
Podemos ver que ocupa 239016 bytes. Guardamos este dato, nos será util para lo que comentamos anteriormente.
-
Enter your selection:q
-
Supervivi> load flash 0 239016 u
-
USB host is connected. Waiting a download.
Con esto le hemos dicho a supervivi que queremos cargar 239016 bytes de datos (observad que es la misma cantidad de bytes que ocupa la imagen de u-boot) en la RAM de la tarjeta. Ahora supervivi se ha quedado esperando los datos, que deberemos envíarselos vía USB. Habiendo conectado el cable USB como se indicó antes ejecutamos el uploader:
-
javieralso@rigoberto: friendlyarm2440-package$ sudo ./s3c2410_boot_usb u-boot.bin
que deberá ser llamado desde la carpeta friendlyarm2440-package y con sudo para poder tener acceso al puerto USB.
Si todo ha ido bien, supervivi debería mostar algo como esto:
-
Now, Downloading [ADDRESS:30000000h,TOTAL:232706]
-
RECEIVED FILE SIZE: 239016 (28KB/S, 8S)
-
Downloaded file at 0×30000000, size = 232696 bytes
-
Found block size = 0x0003c000
-
Erasing… … done
-
Writing… … done
-
Written 239016 bytes
-
Supervivi>
Ahora, arrancamos u-boot:
-
Supervivi> go 0×30000000
y ya está, nuestra tarjeta arrancará u-boot:
-
U-Boot 1.3.2-mini2440 (May 15 2009 – 21:24:49)
-
I2C: ready
-
DRAM: 64 MB
-
Flash: 2 MB
-
NAND: Bad block table not found for chip 0
-
Bad block table not found for chip 0
-
64 MiB
-
*** Warning – bad CRC or NAND, using default environment
-
USB: S3C2410 USB Deviced
-
In: serial
-
Out: serial
-
Err: serial
-
MAC: 08:08:11:18:12:27
-
Hit any key to stop autoboot: 0
Lo primero que ha hecho u-boot al arranchar ha sido darnos un mensaje de alerta indicando que el contenido de las variables de entorno no está fijado y de ahí el error CRC que se ve. Éstas variables de entorno son necesarias para que u-boot pueda configurarse al arrancar, pero antes de crearlas debemos de preparar la memoria NAND.
Para preparar la NAND, lo primero que haremos será borrar el listado de sectores defectuosos y volver a crearlo nosotros. Los sectores defectuosos son una lista, generalmente almacenada en fábrica, que indica qué sectores de la NAND son defectuosos. Lo normal es que haya alguno y con el tiempo y el uso se irán incrementando.
-
MINI2440 # nand scrub
-
NAND scrub: device 0 whole chip
-
Warning: scrub option will erase all factory set bad blocks!
-
There is no reliable way to recover them.
-
Use this command only for testing purposes if you
-
are sure of what you are doing!
-
Really scrub this NAND flash? <y/N>
-
Erasing at 0x33d4000 — 81% complete.
-
NAND 64MiB 3,3V 8-bit: MTD Erase failure: -5
-
Erasing at 0x3ffc000 — 100% complete.
-
Bad block table not found for chip 0
-
Bad block table not found for chip 0
-
OK
-
MINI2440 #
Con el comando anterior borramos la lista de sectores defectuosos antes mencionada. Después de haber hecho la limpieza, creamos nuestra propia tabla (también conocida como BBT):
-
MINI2440 # nand createbbt
-
Create BBT and erase everything ? <y/N>
-
Skipping bad block at 0×03410000
-
Skipping bad block at 0x03ff0000
-
Skipping bad block at 0x03ff4000
-
Skipping bad block at 0x03ff8000
-
Skipping bad block at 0x03ffc000
-
Creating BBT. Please wait …Bad block table not found for chip 0
-
Bad block table not found for chip 0
-
Bad block table written to 0x03ffc000, version 0×01
-
Bad block table written to 0x03ff8000, version 0×01
Este proceso es relativamente lento, por lo que habrá que esperar que esperar (3-4 minutillos), así que mientras tanto, busca una tarjeta SD y copia el binario u-boot.bin QUE COMPILASTE en dicha tarjeta. La cargaremos desde ahí.
Una vez que tenemos nuestra SD con el binario cargado y que ya se ha generado la nueva BBT, introducimos la tarjeta en el lector de la mini2440 y le decimos a u-boot que la detecte:
-
MINI2440 # mmcinit
-
trying to detect SD Card…
-
Manufacturer: 0×30, OEM "SD"
-
Product name: "SU02G", revision 8.0
-
Serial number: 3489032
-
Manufacturing date: 9/2010
-
CRC: 0×27, b0 = 1
-
READ_BL_LEN=15, C_SIZE_MULT=7, C_SIZE=365
-
size = 1642070016
Con la tarjeta ya detectada, cargamos u-boot.bin en la RAM:
-
MINI2440 # fatload mmc 0:1 0×32000000 u-boot.bin
-
-
233412 bytes read
¿Qué ha pasado? pues que le hemos dicho a u-boot que cargue el archivo binario u-boot.bin desde un sistema de archivos FAT (fatload), ubicado en la SD (mmc), dispositivo 1, primera partición (0:1), a partir de la dirección de memoria 0×32000000.
Una vez que tenemos el archivo en RAM, lo volcamos a la NAND:
-
MINI2440 # nand write.e 0×32000000 0×0 0x38fc4
-
NAND write: device 0 offset 0×0, size 0x38fc4
-
Writing data at 0x38c00 — 100% complete.
-
233412 bytes written: OK
Bueno, en este caso, hemos escrito 0x38fc4 bytes (233412, para que nos entendamos), al comienzo de la NAND. El numerajo hexadecimal, como hemos visto corresponde al peso de u-boot.bin pero ésta vez del que hemos compilado NOSOTROS, no del que cargamos en RAM al principio. Importante no confundir ésto. Un apunte importante es que en ésta parte del proceso, la longitud deberá darse en hexadecimal, no en decimal, ya que ello puede dar lugar a errores.
Por lo que he leído por ahí, el modificador .e del comando write se utiliza para generar códigos de correción de errores y evitar así lo posibles bloques defectuosos que pueda haber en la NAND (recordad el comando createbbt de antes).
Una vez hecho esto, podemos reiniciar tranquilos nuestra mini2440: u-boot la hará arrancar. Aunque no hará mucho mas ya que la NAND está completamente borrada y no hay sistema.
Para finalizar debemos indicar a u-boot donde está la partición dedicada a las variables de entorno. Para ello primero debemos de conocer la tabla de particiones de nuestra memoria NAND, que deberá estar formateada de fábrica (si no es así puede hacerse desde el menú de supervivi). El comando mtdparts nos proporcionará dicha información:
-
MINI2440 # mtdparts
-
-
device nand0 <mini2440-nand>, # parts = 4
-
#: name size offset mask_flags
-
0: u-boot 0×00040000 0×00000000 0
-
1: env 0×00020000 0×00040000 0
-
2: kernel 0×00500000 0×00060000 0
-
3: root 0x07aa0000 0×00560000 0
-
-
active partition: nand0,0 – (u-boot) 0×00040000 @ 0×00000000
-
-
defaults:
-
mtdids : nand0=mini2440-nand
-
mtdparts: <NULL>
Podemos ver que tenemos cuatro particiones cuyos nombres son bastante descriptivos. La partición 1, env será la utilizada para las variables de entorno de u-boot, así que con dynenv lo configuramos:
-
MINI2440 # dynenv set 40000
-
device 0 offset 0×40000, size 0x7fc0000
-
45 4e 56 30 – 00 00 04 00
El comando introducido ha configurado la ubicación de las variables de entorno a partir de la dirección 0×40000, que como se puede ver en la tabla de particiones mostrada anteriormente, es la dirección offset (de comienzo) de la partición asignada a tal efecto.
Una vez configurada la ubicación de las variables de entorno, almacenamos la configuración con el comando saveenv:
-
MINI2440 # saveenv
-
Saving Environment to NAND…
-
Erasing Nand…Writing to Nand… done
Y listo, ya tenemos u-boot instalado.
Para finalizar os contaré por qué antes utilicé dos versiones distintas de uboot. El motivo es que para instalar uboot, primero debe residir en la RAM y poderse ejecutar desde ahí, ya que hay que hacer una limpieza de la NAND antes de llevar a cabo la instalación propiamente dicha. Lo que observé entonces fue que las versiones de uboot que conseguían arrancar desde la RAM, no eran capaces de hacerlo luego una vez que se instalaban en NAND (en efecto, según los manuales que leí, una vez creada la BBT, se escribía el contenido de la RAM a la NAND, ya que allí es donde está uboot) y viceversa, las imágenes que si que eran capaces de arrancar desde la NAND no lo podían hacer desde la RAM. No sé si esto es por algún bug en uboot (que deberían ser entonces bugs distintos en cada una de las versiones) o porque yo hice algo mal (repetí montones de veces lo que vi en tutos, blogs y demás paso por paso). El caso es que después de varios intentos sin mucho éxito, decidí hacerlo tal y como lo he explicado aquí.
En el futuro….
En próximas recetas, explicaré qué comandos básicos utilizar en u-boot para cargar imágenes en RAM o NAND, configurar el arranque automático desde distintas fuentes, particionar la NAND, configurar opciones de arranque para el S.O. que tengamos y alguna cosilla mas. Evito poner esa información aquí para no sobrecargar demasíado esta receta, que se supone que tienen que ser breves y concisas.
Referencias
Muchas y muy variadas, aunque las mas importantes son éstas.
- Wiki sobre mini2440
- Hosting para proyectos sobre mini2440 en GoogleCode
- Blog con algunos artículos y enlaces interesantes
- Buscando en Google puedes encontrar cantidad de información referente a esta tarjeta de desarrollo.
NOTA: Entrada extraída de otra antigua entrada publicada por mi en CrySoL.



2 Comments
Hola, tengo un mini2440 con 256M, y he tenido problemas con el u-boot. Sólo he conseguido correr dos imágenes (fs) desde la NAND con el vboot, pero no he logrado que ninguna imagen arranque desde la SD, desde friendlyarm.net obtuve el archivo u-boot-256M.bin que tiene exactamente el mismo número de bytes que el archivo u-boot.bin obtenido al compilar siguiendo los pasos de este post y ambos presentan los mismos inconvenientes: Las variables que configuro con setenv vuelven a su valor por defecto cada vez que se apaga el dispositivo y se vuelve a encender, entonces si subo una imagen(fs) en la NAND, puedo iniciarla con la opción b desde el menú del NOR, pero no se inicia directamente. Cualquier ayuda es apreciada.
Hola!! Perdona que haya tardado tanto en contestarte, pero he estado liado y además el gestor de correo me filtró el email como spam.
En el blog hay otra entrada sobre como configurar uboot. En ella utilizo el comando saveenv para guardar el contenido de las variables de entorno dentro de la flash, de modo que quedan fijas.
En mi caso, todo funcionó correctamente según lo que explico en las dos recetas sobre u-boot.
Ya me contarás qué tal.
Un saludo
Trackbacks/Pingbacks