Un sistema operativo en tiempo real se caracteriza por garantizar que los procesos se ejecutarán en bajo el umbral de un tiempo máximo. El planificador debe comportarse de manera que esto sea cierto para cualquier proceso, y se debe de balancear correctamente para garantizar que no habrá inanición. La inanición consiste en que un proceso prioritario no deje a otros con menos importancia acceder a los recursos de la máquina, y es algo a evitar.
En esta entrada podría explicar un poco el concepto de procesos en Linux, de qué es el scheduler, las políticas de planificación, etc. Sin embargo, es tan amplio que de momento sólo voy a contar cómo hacerlo. Quizás en otra entrada le dedique tiempo al apartado de teoría.
Para tener un sistema operativo en tiempo real, se va a aplicar el parche Preempt-RT al Kernel de Linux. “Preemptive” significa que un proceso puede ser interrumpido o “expulsado” cuando tenga que entrar otro de mayor prioridad. Esto implica un “cambio de contexto”, por lo que hay que guardar el estado del proceso que estaba en ejecución para volver a reanudarlo más tarde sin errores.
Antes de empezar
Los pasos previos a la compilación del Kernel es tener Linux funcionando y conocer el Kernel con el que se está trabajando. Para saberlo se recurre al siguiente comando:
uname –a
Además hay que tener el sistema operativo con la lista de repositorios y el software actualizado. El proceso de compilación se podrá hacer desde un ordenador convencional, especificando que se va a trabajar con una arquitectura ARM y para un dispositivo SoC-FPGA o desde la propia placa de desarrollo. En el primer caso, el tiempo de compilación será menor.
Para actualizar los repositorios y el software usamos los siguientes comandos desde la consola de Linux:
opkg update
opkg upgrade
Ahora hay que instalar las herramientas y librerías necesarias para el proceso de compilación, algunas es probable que ya estén instaladas.
opkg install build-essential gcc make libncurses5-dev libssl-dev
opkg install bison flex qt5-default qt5-qmake fakeroot
opkg install qtbase5-dev qtbase5-dev-tools
Obteniendo el Kernel
El kernel se puede obtener de la página kernel.org y descargar también de ahí el parche de Preempt-RT. Ambas versiones deben de coincidir. Se recomienda que, si no hay parche para la misma versión del Kernel que estamos ya utilizando, escoger la siguiente versión en la que ambos coincidan.
Yo he ido a lo más fácil, y es que hay un repositorio en GitHub de Altera (Altera-OpenSource) que tiene ya el Kernel con el parche de Preempt-RT listo para compilar, por lo que en mi caso, he decidido bajarlo directamente de ahí. Hay varios branches, por lo que se puede elegir. Yo he elegido la versión 4.14.73-ltsi-rt. Esta tiene el parche de tiempo real y es de “Long Term Support”.
Compilación del Kernel
Tras la descarga del Kernel, lo descomprimimos en una carpeta. Si en un futuro queremos hacer módulos, que en mi caso así será, recomiendo no borrar la carpeta después de la compilación.
En la consola tenemos que ir a la ruta donde hemos descomprimido el Kernel. En el caso de estar compilándolo en un ordenador convencional, tendremos que especificar la arquitectura para la que queremos compilarlo y la herramienta o “tool-chain”.
export ARCH=arm
export CROSS_COMPILE= arm-linux-gnueabihf-
Si lo estamos haciendo desde la propia placa de desarrollo, se puede omitir este paso, ya que se compilará para esa misma arquitectura.
Los siguientes pasos son establecer la configuración del “make”, que para hacerlo hacia dispositivos SoC-FPGA se puede solicitar de forma automática, y por último, compilar el Kernel generando una imagen comprimida del mismo. Esta imagen se pasará a la tarjeta microSD y se cargará al inicio del sistema.
make socfpga_defconfig
make –j12 zImage 2>&1 | tee ../linux-rt-log.txt
El pipeline con el commando “tee” y el fichero de texto como destino es para guardar un registro de lo que hace la compilación, para poder ver donde falla en caso de que haya problemas.
La compilación ha terminado con éxito y nos indica en qué directorio se ha generado la imagen del Kernel, lo comprobamos.
A continuación, copiamos esa imagen en la tarjeta micro SD. Antes de hacerlo, recomiendo hacer una copia de seguridad del Kernel anterior. Tras copiarlo, iniciamos el sistema.
Si volvemos a introducir el comando “uname –a”, ahora nos aparece una nueva versión del Kernel, y nos indica que tiene el parche Preempt-RT.
Resultados obtenidos
Podemos hacer unas pruebas para ver su funcionamiento con la herramienta cyclictest, es de código abierto y se puede encontrar en el siguiente repositorio. Yo he hecho las pruebas con los dos Kernels, el original y el de RT y se notan las diferencias en la latencia máxima. El Kernel Preempt-RT las reduce notablemente y aporta mayor estabilidad.