Monthly Archives: Diciembre 2009

ARM mini2440: Configurando uBoot para arranque desde SD para FriendlyArm

0
Filed under ARM, Embedded, mini2440
Tagged as , ,

Introducción

Después de haber compilado e instalado uBoot en nuestra tarjeta de desarrollo mini2440 y de haberle compilado una imágen Linux ahora nos proponemos configurar uBoot para el arranque de dicho kernel.
uBoot permite mucha flexibilidad a la hora de instalar y arrancar imágenes desde la memoria. Aún así, aquí sólo explicaré el procedimiento que he utilizado yo para poder cargar y ejecutar Linux desde una tarjeta SD, ya que además de parecerme los mas fácil y cómodo a la hora de actualizar (tan solo hay que copiar la nueva imagen a la SD), mantendremos intacta la NAND interna de nuestra tarjeta, que sabemos que tiene vida limitada, y aunque muy larga, no deja de ser eso, limitada.

Qué necesitamos

Pues como dije antes, se supone que debemos de haber leído, comprendido y ejecutado las dos recetas que se mencionan mas arriba.
De la segunda receta obtenemos la imagen del núcleo que vamos a utilizar en nuestra tarjeta, uImage.
A continuación, hay que preparar la tarjeta de memoria. Yo en mi caso tengo una partición ext3 de unos 128MB que utilizo para tal fin. Lo del tamaño no importa mucho (ejem), pero nunca por mucho trigo fue mal año (ejem, ejem), así que si nos sobra espacio, podremos utilizarlo para guardar ahí backups y cosas de esas (es lo que yo hago).
También es aconsejable que dicha partición se la primera particion de la unidad (primaria, claro está), ésto no es muy crítico, pero mi configuración tiene ésto en cuenta, con lo cual si situas la partición en otro sitio, deberás especificarlo en la configuración.
Evidentemente no me voy a poner a explicar cómo hacer dicha partición, ya somos todos muy grandecitos para hacerlo solitos, así que cuando termines, te espero mas abajo…

Configurando uBoot

Una vez que tienes la partición hecha, copias la imagen uImage que compilaste en su día a dicha partición e insertas la tarjeta en el lector de tu mini2440. Conectas el puerto serie, abres minicom con la configuración que usaste para instalar uBoot y arrancas. Cuando salga el mensaje de que pulses una tecla para cancelar el arranque procedes:

  1. U-Boot 1.3.2-mini2440 (Oct 15 200919:42:55)                                                      
  2. I2C:   ready
  3. DRAM:  64 MB
  4. Flash:  2 MB
  5. NAND:  128 MiB
  6. Found Environment offset in OOB..
  7. USB:   S3C2410 USB Deviced
  8. In:    serial
  9. Out:   serial
  10. Err:   serial
  11. MAC: 08:08:11:18:12:27
  12. Hit any key to stop autoboot:  0
  13. MINI2440 #

Lo primero que vamos a hacer, para asegurarnos de que todo va sobre ruedas, es hacer el arranque “a mano”, de modo que sepamos exactamente qué parámetros tenemos que dar a uBoot para que cargue correctamente nuestro núcleo. Una vez que ya sepamos estos parámetros, configuraremos uBoot correctamente para que se haga todo de forma automática cada vez que encendamos nuestra tarjeta. Algunos de los comandos que se mostrarán ahora ya nos sonarán de la receta en la que instalamos uBoot, aún así los volveré a explicar ahora.
Lo primero es inicializar la tarjeta SD:

  1. MINI2440 # mmcinit
  2. trying to detect SD Card…
  3. Manufacturer:       0x1b, OEM "SM"
  4. Product name:       "UD   ", revision 1.0
  5. Serial number:      2697000253
  6. Manufacturing date: 12/2006
  7. CRC:                0×78, b0 = 1
  8. READ_BL_LEN=15, C_SIZE_MULT=7, C_SIZE=3453
  9. size = 2329935872
  10. MINI2440 #

Una vez que la tarjeta ha sido detectada e inicializada correctamente, se carga la imagen:

  1. MINI2440 # ext2load mmc 0:1 0×32000000 uImage
  2. 2148500 bytes read
  3. MINI2440 #

Lo que hemos hecho ha sido decirle a uBoot que cargue el archivo uImage que se encuentra en la partición 1 de la tarjeta 0 (0:1) cuyo tipo es extX (ext2load) a partir de la dirección de memoria 0×32000000. Recordemos que en ésta imagen ya definimos el entrypoint, entre otras cosas, por lo que no necesitaremos definirlo mas.
Ahora ya solo queda arrancar:

  1. MINI2440 # bootm
  2. ## Booting kernel from Legacy Image at 32000000
  3.    Image Name:   Angstrom/2.6.31+git/mini2440
  4.    Created:      2009-12-10   4:50:52 UTC
  5.    Image Type:   ARM Linux Kernel Image (uncompressed)
  6.    Data Size:    2148436 Bytes =  2 MB
  7.    Load Address: 30008000
  8.    Entry Point:  30008000
  9.    Verifying Checksum … OK
  10.    Loading Kernel Image … OK
  11. OK
  12. Starting kernel …
  13. <Lots and lots of logs….>
  14. Failed to execute /sbin/init.  Attempting defaults…
  15. Kernel panic – not syncing: No init found.  Try passing init= option to kernel.
  16. [<c002b4c8>] (unwind_backtrace+0×0/0xdc) from [<c0301dd0>] (panic+0×34/0×118)
  17. [<c0301dd0>] (panic+0×34/0×118) from [<c0026544>] (init_post+0×134/0x16c)
  18. [<c0026544>] (init_post+0×134/0x16c) from [<c00085c4>] (kernel_init+0xd8/0x10c)
  19. [<c00085c4>] (kernel_init+0xd8/0x10c) from [<c00277d8>] (kernel_thread_exit+0×0/0×8)

Como podemos observar, el núcleo ha arrancado correctamente aunque veamos un nunca bienvenido kernel panic. Éste es debido a que no tenemos sistema alguno instalado, con lo cual, cuando el kernel termina de cargar e inicializar el sistema no es capaz de lanzar el proceso Init, con lo que se detiene.
De momento no lo necesitamos, éso será el contenido de una próxima receta. Con que arranque el núcleo nos daremos por satisfechos :-P .
Puesto que ya hemos visto que nuestra configuración funciona, la guardamos:

  1. MINI2440 # setenv bootcmd ‘mmcinit; fat2load mmc 0:1 0×32000000 uImage; bootm’
  2. MINI2440 # saveenv
  3. Saving Environment to NAND…
  4. Erasing Nand…Writing to Nand… done

El comando setenv sirve para asignar valores a las variables de entorno de uBoot. En éste caso configuramos la variable bootcmd que es la que contiene los comandos que se ejecutarán en el arranque. Dichas instrucciones son las que probamos anteriormente para la carga del núcleo.
saveenv como su nombre indica, sirve para hacer persistente el contenido de las variables de entorno, de forma que esten ahí cada vez que arranquemos la tarjeta.
Con ésto ya debería ser suficiente para que tu núcleo arranque correctamente, pero ya que estamos metidos con uBoot vamos a hacer algo mas: Vamos a configurarlo para decirle en qué partición de la tarjeta tenemos instalado el sistema, así como con qué parámetros debe de arrancar el núcleo, ya que con los que arranca por defecto probablemente no tengamos acceso a un terminal desde el puerto serie (cosa que a veces puede ser muy útil).
Para esto deberemos tocar otra variable de entorno, en éste caso bootargs que contiene los parámetros que son pasados al kernel:

  1. MINI2440 # setenv bootargs ‘root=/dev/mmcblk0p2 rootwait=4 rw init=/sbin/init noinitrd console=ttySAC0,115200′
  2. MINI2440 # saveenv
  3. Saving Environment to NAND…
  4. Erasing Nand…Writing to Nand… done

Lo que hemos hecho ha sido decirle que tenemos el sistema instalado en la partición 2 de la tarjeta SD (boot=/dev/mmcblk0p2), la ruta de init, y desde donde se puede acceder a la consola y a qué velocidad.
La partición que se ha indicado como partición del sistema deberá ser forzosamente ext3, así que recomiendo que el espacio que te sobró en tu SD lo dediques a una partición para el sistema (cuando haga la preceptiva receta :-P ).
Ahora podemos ver el contenido de nuestras variables de entorno:

  1. MINI2440 # printenv
  2. bootdelay=3
  3. baudrate=115200
  4. ethaddr=08:08:11:18:12:27
  5. ipaddr=10.0.0.111
  6. serverip=10.0.0.4
  7. netmask=255.255.255.0
  8. usbtty=cdc_acm
  9. mini2440=mini2440=0tb
  10. bootargs_base=console=ttySAC0,115200 noinitrd
  11. bootargs_init=init=/sbin/init
  12. root_nand=root=/dev/mtdblock3 rootfstype=jffs2
  13. root_mmc=root=/dev/mmcblk0p2 rootdelay=2
  14. root_nfs=/mnt/nfs
  15. set_root_nfs=setenv root_nfs root=/dev/nfs rw nfsroot=${serverip}:${root_nfs}
  16. ifconfig_static=run setenv ifconfig ip=${ipaddr}:${serverip}::${netmask}:mini2440:eth0
  17. ifconfig_dhcp=run setenv ifconfig ip=dhcp
  18. ifconfig=ip=dhcp
  19. set_bootargs_mmc=setenv bootargs ${bootargs_base} ${bootargs_init} ${mini2440} ${root_mmc}
  20. set_bootargs_nand=setenv bootargs ${bootargs_base} ${bootargs_init} ${mini2440} ${root_nand}
  21. set_bootargs_nfs=run set_root_nfs; setenv bootargs ${bootargs_base} ${bootargs_init} ${mini2440} ${root_nfs} ${ifconfig}
  22. mtdids=nand0=mini2440-nand
  23. mtdparts=mtdparts=mini2440-nand:256k(u-boot),128k(u-boot_env),5m(kernel),125568k(rootfs)
  24. bootargs=root=/dev/mmcblk0p2 rootwait=4 rw init=/sbin/init noinitrd console=ttySAC0,115200
  25. "ootcmd="mmcinit
  26. filesize=20C8EC
  27. partition=nand0,0
  28. mtddevnum=0
  29. mtddevname=u-boot
  30. bootcmd=mmcinit; fat2load mmc 0:1 0×32000000 uImage; bootm
  31. Environment size: 1209/131068 bytes
  32. MINI2440 #

Ahí podremos ver el contenido de todas las variables de entorno de uBoot. Aparte de las explicadas hay algunas interesantes como por ejemplo ifconfig que sirve para configurar si queremos que ejecute un cliente dhcp al arranque o si queremos darle una ip estática, bootdelay , que sirve para configurar el retardo en el arranque o baudrate, que como podemos imaginar, sirve para configurar la velocidad del puerto serie.
Si reiniciamos ahora nuestra mini2440, podremos ver que arranca el núcleo perfectamente, aunque sin sistema poco podemos hacer… Paciencia…. :-D

Referencias

NOTA: Entrada extraída de otra antigua entrada publicada por mi en CrySoL.

ARM mini2440: Compilando Linux para FriendlyArm

0
Filed under ARM, Embedded, mini2440
Tagged as , ,

Introducción

En una entrada anterior escribí sobre cómo compilar e instalar u-boot en una tarjeta mini2440. Ahora voy a explicar cómo compilar un núcleo Linux para ésta misma plataforma. En una próxima receta tengo intención de explicar los pasos para configurar u-boot y hacer arrancable éste núcleo en nuestra amada tarjeta. De momento, vamos lo que interesa: El núcleo.

Descargando los fuentes

Los fuentes del núcleo ya parcheados para su uso en nuestra arquitectura los descargamos de su repositorio git:

  1. javieralso@rigoberto:~$ mkdir kernel ; cd kernel
  2. javieralso@rigoberto:~$ git clone git://repo.or.cz/linux-2.6/mini2440.git
  3. javieralso@rigoberto:~$ mkdir kernel-bin
  4. javieralso@rigoberto:~$ cd mini2440

Con ésto ya tendremos creada la jerarquía de directorios necesaria y los fuentes descargados.
Para la compilación, usaré la misma toolchain que utilicé en la receta sobre u-boot, así que después de leerla y configurar la toolchain contiuaremos.

Lo primero que necesitaremos es crear el archivo de configuración (.config) con las opciones del núcleo. Suponiendo que estamos en el directorio mini2440 creado anteriormente, ejecutamos

  1. javieralso@rigoberto:~$ CROSS_COMPILE=arm-none-linux-gnueabi- ARCH=arm make O=../kernel-bin/ mini2440_defconfig

Ésto generará la configuración a partir de una template existente en los propios fuentes y prácticamente no tendremos que tocar nada mas.

Configuración del display

En el código descargado existe un bug que hace que la imagen mostrada en el display aparezca desplazada 13 pixeles hacia la derecha. Preguntándo a Google encontré cómo arreglarlo. La solución pasa por editar en uno de los fuentes los parámetros de configuración del display. Sé que hubiese resultado mas cómodo generar el parche y ponerlo aquí sin mas para que se aplique, pero así explico con un poco mas de detalle que es lo que hay que hacer, no sea que alguien utilice otro tipo de display y tenga que editar de forma distinta los fuentes.

El archivo a editar es mini2440/arch/arm/mach-s3c2440/mach-mini2440.c. Aquí, entre otras cosas, se inicializan muchas de las estructuras utilizadas por el núcleo con parámetros específicos de nuestra arquitectura. En nuestro caso habrá que modificar los parámetros del display TFT de 3’5″ con touchscreen, que es el que tengo yo. En otro caso y dependiendo del display que tengas tu, puede que tengas que modificar o no dicho archivo con distintos parámetros.

Buscamos el siguiente código (a partir de la línea 227):

  1. …………………………………
  2. …………………………………
  3. static struct s3c2410fb_display mini2440_lcd_cfg[] __initdata = {
  4.         [0] = { /* mini2440 + 3.5" TFT + touchscreen – old model "N35" */
  5.                 _LCD_DECLARE(
  6.                         7,                      /* The 3.5 is quite fast */
  7.                         240, 21, 38, 6,         /* x timing */
  8.                         320, 4, 4, 2,           /* y timing */
  9.                         60),                    /* refresh rate */
  10. ………………………………..
  11. ………………………………..

Cómo podemos observar, este fragmento corresponde al display de 3’5″ con touchscreen del mini2440 (seleccionado por defecto en la configuración que creamos anteriormente). Dentro de los parámetros x timing, cambiamos el valor 38 por 25, restando así el offset de 13 pixels que hay en el eje X del display.
El código entonces deberá quedar tal que así:

  1. …………………………………
  2. …………………………………
  3. static struct s3c2410fb_display mini2440_lcd_cfg[] __initdata = {
  4.         [0] = { /* mini2440 + 3.5" TFT + touchscreen – old model "N35" */
  5.                 _LCD_DECLARE(
  6.                         7,                      /* The 3.5 is quite fast */
  7.                         240, 21, 25, 6,         /* x timing */
  8.                         320, 4, 4, 2,           /* y timing */
  9.                         60),                    /* refresh rate */
  10. ………………………………..
  11. ………………………………..

Repito, ésto está probado para mi display, si tu display es distinto, deberás buscar la sección correspondiente en el archivo y “ajustarlo” según tus necesidades.

Una vez editado, proseguimos con la compilación.

Compilando

Después de generada la configuración y arreglado el pequeño bug del que hablé antes, ya podemos compilar:

  1. javieralso@rigoberto:~$ CROSS_COMPILE=arm-none-linux-gnueabi- ARCH=arm make O=../kernel-bin/

Y a esperar (no mucho, un café mientras ves el youtube :D ).

Suponiendo que ya has terminado de compilar y todo ha ido a las mil maravillas, ahora toca crear la imagen que u-boot cargará y arrancará. Para ello utilizamos la herramienta mkimage que podemos encontrar en el directorio tools de la distribución u-boot que compilamos en su momento.

el comando a introducir será el siguiente:

  1. avieralso@rigoberto:~$ mkimage -A arm -O linux -T kernel -C none -a 0×30008000 -e 0×30008000 -d ../kernel-bin/arch/arm/boot/zImage ./uImage

Deberemos usar el path completo a mkimage si no lo tenemos en nuestro path.

Éste comando crea una imagen para arm (-A arm), sistema operativo linux y tipo de imagen un núcleo. Además, no se usará compresión (-O linux -T kernel -C none). La imagen creada será cargada por u-boot a partir de la dirección 0×30008000 y el punto de entrada (dirección a partir de la cual arranca la imagen) será la misma dirección (-a 0×30008000 -e 0×30008000).
La imagen se llamará uImage y quedará almacenada en el directorio actual.

Lo próximo…

En una próxima receta explicaré la configuración de u-boot poniendo como ejemplo la instalación de nuestra imagen para que sea cargada desde una tarjeta microSD (o desde donde queramos).
Después explicaré como compilar desde cero una imagen de opie utilizando la toolchain de openembedded e instalarla, junto con las librerías generadas durante la compilación de éste núcleo.
Finalmente hablaré sobre como compilar una aplicación para opie utilizando bitbake, el script de compilación automatizado de openembedded.

Referencias

Como siempre muchísimas, pero la principal, de la que lo he seguido todo, ha sido el siguiente enlace:

Un saludo

NOTA: Entrada extraída de otra antigua entrada publicada por mi en CrySoL.

Errores en la post instalación de paquetes en entornos Debian

0
Filed under GNU, General
Tagged as , ,

Muchas veces me ha pasado que instalando paquetes se han producido fallos debidos a que la “post instalación” no se ha efectuado correctamente. En estos casos, dpkg falla, dejando cualquier paquete que quede pendiente sin terminar. Ésto hace que además cualquier intento tanto de instalar como de desinstalar paquetes falle.

Una forma bastante tosca pero efectiva de solucionar ésto es acceder al script de postinstalación correspondiente y editarlo para que devuelva el valor esperado (generalmente 0). Como ya estoy harto de que siempre se me olvide donde están guardados esos archivos, aquí pongo la ruta.

  1. /var/lib/dpkg/info/paquetito.postinst

Éste archivo corresponde al script de postinstalación del paquete paquetito. Lo único que hay que hacer es que éste paquete devuelva el valor 0 y con ello la instalación podrá finalizar correctamente.