Yocto en el ODROID-C2: Usando Yocto con el Kernel 5.0

El Proyecto Yocto (YP) es un proyecto colaborativo de código abierto que ayuda a los desarrolladores a crear sistemas personalizados basados en Linux, independientemente de la arquitectura del hardware. Yocto no es una distribución de Linux integrada, sino que más bien crea una personalizada para ti. El proyecto proporciona un conjunto flexible de herramientas y un espacio donde los desarrolladores de todo el mundo pueden compartir tecnologías, pilas de software, configuraciones y mejores prácticas que se pueden usar para crear imágenes Linux a medida para dispositivos integrados y IOT, o donde quiera que se necesite un sistema operativo Linux personalizado. Este artículo describe los pasos y procedimientos básicos para crear una imagen personalizada de Linux para ODROID-C2 utilizando Linux-5.0.

Requisitos previos para la configuración del sistema host

Es necesario un sistema de compilación basado en Linux para el proyecto Yocto, que admita la mayoría de las principales distribuciones de servidores y escritorios de Linux. Puedes encontrar una lista de todas las distribuciones de Linux compatibles en: https://www.yoctoproject.org/docs/current/ref-manual/ref-manual.html#detailed-supported-distros. El proyecto Yocto necesita que se instalen ciertos paquetes en la máquina host antes de iniciar una compilación personalizada del sistema Linux para un determinado dispositivo. La lista de paquetes de host y herramientas necesarias para una compilación de yocto la puedes encontrar en: https://www.yoctoproject.org/docs/current/brief-yoctoprojectqs/brief-yoctoprojectqs.html#brief-compatible-distro. Para los sistemas basados en Debian, son necesarios instalar los siguientes paquetes:

$ sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib build-essential chrpath socat cpio python python3 python3-pip python3-pexpect xz-utils debianutils iputils-ping

Pasos para crear una imagen de Linux personalizada para Odroid-C2

Nota: Los pasos que se detallan a continuación han sido probados en un sistema host Ubuntu 16.04. Después de realizar la configuración del sistema host (es decir, instalar todos los paquetes necesarios), el siguiente paso es hacerse con la fuente del sistema de compilación del proyecto yocto. Como vamos a utilizar yocto para compilar nuestra imagen personalizada, necesitamos la distribución de referencia de yocto. Poky es una distribución de referencia del Proyecto Yocto. Contiene el sistema de compilación OpenEmbedded, BitBake y OpenEmbedded Core, así como un conjunto de metadatos para que puedas empezar a crear tu propia distro. La capa central proporciona todos los componentes comunes y las capas adicionales cambian la pila de software según sea necesario.

Obteniendo las fuentes

Las siguientes instrucciones se basan en la rama warrior upstream. La rama de Warrior tiene soporte para compilar Linux Kernel 5.0. Descarga la distribución de referencia poky para yocto.

$ mkdir yocto-odroid
$ cd yocto-odroid
$ git clone -b warrior git://git.yoctoproject.org/poky.git
Descarga la capa BSP ODROID :
$ git clone -b warrior git://github.com/akuster/meta-odroid
Descarga la capa openembedded:
$ git clone -b warrior https://github.com/openembedded/meta-openembedded.git
Una vez que hayas descargado todas las fuentes en el directorio de yocto-odroid, asegúrate de que la estructura del directorio sea como la de la Figura 1.

Figura 1 - Estructura de directorios de la configuración de compilación de Yocto

Iniciando una compilación

Una vez que tenga todas las fuentes y la estructura de directorios como la que se muestra en la Figura 1, puedes iniciar la compilación con los siguientes pasos: Inicia la configuración de compilación:

$ source poky/oe-init-build-env
El comando anterior creará un directorio de compilación y la moverá a ese directorio. Ahora tenemos un espacio de trabajo donde podemos compilar un emulador y las imágenes basadas en placas de referencia, por ejemplo qemuarm. Para hacer que una imagen sea compatible con nuestra máquina (es decir, ODROID-C2) necesitamos agregar la capa BSP ODROID-C2 y la capa meta-openembedded en el espacio de trabajo.
$ bitbake-layers add-layer ../meta-odroid/
$ bitbake-layers add-layer ../meta-openembedded/meta-oe/
$ bitbake-layers add-layer ../meta-openembedded/meta-python/
$ bitbake-layers add-layer ../meta-openembedded/meta-networking/
Después, necesitamos modificar el archivo de configuración ubicado en el directorio conf dentro del directorio de compilación. Abre el archivo local.conf ubicado en conf/local.conf usando tu editor de texto favorito.
$vi conf/local.conf
Realice las siguientes modificaciones en el archivo local.conf: Busca
MACHINE ?? = “qemux86”
Coméntalo colocando una # antes o sustitúyelo por
MACHINE ?? = “odroid-c2”
Encuentra y comenta las siguientes líneas poniendo una # delante:
PACKAGECONFIG_append_pn-qemu-system-native = " sdl"
PACKAGECONFIG_append_pn-nativesdk-qemu = " sdl"
Buscar la línea
EXTRA_IMAGE_FEATURES ?= "debug-tweaks"
Añade lo siguiente después de "debug-tweaks"
ssh-server-openssh
de modo que la línea quede así:
EXTRA_IMAGE_FEATURES ?= "debug-tweaks ssh-server-openssh"
Ahora, copia las siguientes líneas y pégalas al final de local.conf:
PACKAGECONFIG_remove_pn-xserver-xorg = "glamor"
IMAGE_FEATURES_append = " x11 "
DISTRO_FEATURES_append = " opengl x11"
DISTRO_FEATURES_remove = "wayland"

PREFERRED_PROVIDER_virtual/libgl = "mesa-gl"
PREFERRED_PROVIDER_virtual/libgles2 = "mali"
PREFERRED_PROVIDER_virtual/libgles1 = "mali"
PREFERRED_PROVIDER_virtual/egl = "mali"
PREFERRED_PROVIDER_virtual/mesa = "mesa"

IMAGE_INSTALL_append = "libgcc libgcc-dev libstdc++ libstdc++-dev libstdc++-staticdev \
        autoconf automake ccache chkconfig glib-networking \
        packagegroup-core-buildessential pkgconfig  \
        boost cmake zlib glib-2.0 \
        rng-tools \
        logrotate \
        lrzsz \
        watchdog \
        util-linux \
        pciutils \
        usbutils \
"
IMAGE_ROOTFS_EXTRA_SPACE ="2097152"
INHERIT += "extrausers"
EXTRA_USERS_PARAMS = "usermod -P root root; "
Ahora guarda y cierra el archivo local.conf. El espacio de trabajo ya está listo para iniciar una compilación. Existen varios tipos de imágenes de destino que pueden compilarse usando yocto para diferentes usos Aquí, se compila una imagen gráfica basada en X11 y matchbox. Ejecuta el siguiente comando para iniciar una compilación:
$ bitbake core-image-sato
La compilación tardará un tiempo dependiendo de la potencia de procesamiento de la máquina host y la velocidad de tu conexión a Internet. Puede necesitar de 30 minutos a varias horas.

Los pasos para acelerar el proceso de compilación los puedes encontrar en: https://www.yoctoproject.org/docs/2.7/dev-manual/dev-manual.html#speeding-up-a-build Si, durante la compilación, aparece algún error relacionado con "Timer Expired ", por ejemplo:

aclocal: error: cannot open /home/gaurav/Downloads/yocto-odroid/build/tmp/work/aarch64-poky-linux/alsa-plugins/1.1.8-r0/recipe-sysroot/usr/share/aclocal/ax_check_mysqlr.m4: Timer expired
autoreconf: aclocal failed with exit status: 1
ERROR: autoreconf execution failed.
WARNING: exit code 1 from a shell command.
ERROR: Function failed: do_configure (log file is located at /home/gaurav/Downloads/yocto-odroid/build/tmp/work/aarch64-poky-linux/alsa-plugins/1.1.8-r0/temp/log.do_configure.9191)
ERROR: Logfile of failure stored in: /home/gaurav/Downloads/yocto-odroid/build/tmp/work/aarch64-poky-linux/mpg123/1.25.10-r0/temp/log.do_configure.9296
Luego simplemente limpia el caché de estado y vuelve a iniciar la compilación desde la imagen de destino usando:
$ bitbake core-image-sato -c cleansstate
$ bitbake core-image-sato

Creando una tarjeta SD de arranque

Si la compilación ha tenido éxito, las imágenes de destino las pueden encontrar en el directorio "tmp/deploy/images/odroid-c2". Se puede usar herramientas de línea de comandos como dd para crear una tarjeta SD de arranque. El usuario debe tener cuidado al utilizar esta herramienta. Si se elige el dispositivo incorrecto, puede sobrescribir un disco duro que pertenezca al host de compilación. Ejecuta el siguiente comando para escribir el archivo de imagen en su tarjeta SD.

$ cd tmp/deploy/images/odroid-c2
$ xzcat core-image-sato-odroid-c2.wic.xz | sudo dd of=/dev/sdX bs=4M iflag=fullblock oflag=direct conv=fsync status=progress
Asegúrese de que sdX apunte al dispositivo correcto (es decir, la tarjeta SD montada). Puede confirmar y buscar la tarjeta SD de destino ejecutando este comando:
$ dmesg|tail
[19001.706817] mmc0: new high speed SDHC card at address e624
[19001.707251] mmcblk0: mmc0:e624 SU08G 7.40 GiB 
[19001.718156] mmcblk0:
En el caso anterior, la tarjeta SD montada es "mmcblk0", en algunas máquinas host también puede aparecer como "sdb" o "sdc".

Figura 2 - Imagen Sato del proyecto Yocto de ODROID-C2

Activando y desactivando GPIO en El Espacio del Kernel

Existen varios tutoriales y códigos de muestra para acceder a GPIO. Casi todos ellos se apoyan en el acceso gpio basado en legacy. El siguiente código muestra cómo activar y desactivar gpio usando un nuevo acceso a gpio basado en descriptor. Es posible que el código que se muestra a continuación no sea una forma adecuada de acceder a gpio en el espacio del kernel, ya que simplemente es un ejemplo. Basándonos en el siguiente código, se puede programar un driver para crear una entrada de nodo en /dev como es /dev/gpio-test y luego ese nodo se puede usar para enviar comandos desde el espacio del usuario para activar y desactivar el gpio usando el código de espacio del kernel.

/*File: gpio-toggle.c*/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/printk.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/gpio/driver.h>
#include <dt-bindings/gpio/meson-gxbb-gpio.h>

struct gpio_chip *chip;

static int chip_match_name(struct gpio_chip *chip, void *data)
{
  printk(KERN_INFO "Label: %s", chip->label);
  printk(KERN_INFO "Name: %s", chip->parent->init_name);
  printk(KERN_INFO "OF Node Full Name: %s", chip->of_node->full_name);
  return !strcmp(chip->label, data);
}

int gpio_test_init(void)
{
  int err = 0;

  printk(KERN_DEBUG "Init Called\n");
  chip = gpiochip_find("periphs-banks", chip_match_name);
  if (!chip) {
    printk(KERN_ERR "Cannot Find A GPIO Chip");
    return -ENODEV;
  }
  printk(KERN_DEBUG "Got valid GPIO Chip Total num gpios %d\n",
      chip->ngpio);

  err = chip->get(chip, GPIOX_11);
  printk(KERN_INFO "Before Setting Value %d\n", err);

  err = chip->direction_output(chip, GPIOX_11, 1);
  if (err < 0) { printk(KERN_DEBUG "Error Setting GPIO Direction %d", err); } chip->set(chip, GPIOX_11, 1);

  err = chip->get(chip, GPIOX_11);
  printk(KERN_INFO "After Setting Value %d\n", err);

  mdelay(2000);

  chip->set(chip, GPIOX_11, 0);

  err = chip->get(chip, GPIOX_11);
  printk(KERN_INFO "After Clearing Value %d\n", err);
  return 0;
}

void gpio_test_exit(void)
{
  printk(KERN_DEBUG "Exiting....\n");
}
module_init( gpio_test_init);
module_exit( gpio_test_exit);
MODULE_LICENSE("GPL");
Below is the Makefile to compile the above Kernel Module:
obj-m += gpio-toggle.o

KSRC = </path/to/pre-compiled/kernel-source>

EXTRA_CFLAGS = -I$(KSRC)/drivers/pinctrl/meson
EXTRA_CFLAGS += -I$(KSRC)/drivers/

CFLAGS_gpio-toggle.o := -DDEBUG

all:
  make -C $(KSRC) M=$(PWD) modules
clean:
  make -C $(KSRC) M=$(PWD) clean
Ten en cuenta que en el Makefile anterior, la variable KSRC debe configurarse para que apunte a la ubicación/directorio donde se encuentra el kernel Linux 5.0 precompilado. El sistema de compilación de yocto coloca el kernel de Linux compilado en:
build/tmp/work/odroid_c2-poky-linux/linux-stable/5.0.6+gitAUTOINC+172634f02e_machine-r0/linux-odroid_c2-standard-build/
La ruta absoluta del Linux Kernel 5.0 precompilado en nuestro caso es:
/home/gaurav/Downloads/yocto-odroid/build/tmp/work/odroid_c2-poky-linux/linux-stable/5.0.6+gitAUTOINC+172634f02e_machine-r0/linux-odroid_c2-standard-build
Entonces, la variable KSRC se convertiría en:
KSRC = /home/gaurav/Downloads/yocto-odroid/build/tmp/work/odroid_c2-poky-linux/linux-stable/5.0.6+gitAUTOINC+172634f02e_machine-r0/linux-odroid_c2-standard-build
Comando para compilar y limpiar el módulo del kernel anterior:
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- clean
Una vez que el módulo del kernel anterior se haya compilado correctamente, debe generar un archivo .ko. En nuestro caso, será gpio-test.ko.

Si la placa ODROID está conectada a una red, transfiere el archivo usando "scp". De lo contrario, si la placa no está conectada, puedes usar la utilidad de transferencia de archivos Xmodem de minicom para transferir un archivo a la máquina de destino. NOTA: el paquete de utilidad de recepción Xmode se compila e instala en nuestra máquina de destino como parte de la compilación de Yocto. Conecta un LED al pin 13 del cabezal J2 de 40 pines, como se muestra a continuación:

Figura 3 - Conexión Led en la placa OdroidC2

Luego inserta el módulo ejecutando:

$ insmod gpio-toggle.ko
El LED conectado a GPIOX_11, es decir, el pin 13 del cabezal J2 en Odroid C2 debería encenderse y apagarse una vez.

Be the first to comment

Leave a Reply