Si habéis seguido el curso, ya tenéis vuestro primer “Blinky” funcionando. Pero Zephyr no es solo encender un LED. La verdadera potencia de este sistema operativo reside en su modularidad.
Imaginad que queréis añadir Bluetooth a vuestro proyecto. En otros entornos, tendríais que buscar la librería, incluir los .h, añadir los .c al makefile… un lío. En Zephyr, a menudo es tan sencillo como escribir una línea: CONFIG_BT=y.
Hoy vamos a hablar del corazón de la personalización de Zephyr: el sistema Kconfig.
¿Qué es Kconfig?
Kconfig (Kernel Configuration) es el mismo sistema de configuración que utiliza el Kernel de Linux.
Zephyr es un sistema operativo enorme con miles de características (drivers, pilas de red, sistemas de archivos, shells, logs…). Si compilásemos todo a la vez, el binario ocuparía gigabytes y no cabría en ningún microcontrolador.
Kconfig nos permite definir qué partes del sistema operativo queremos compilar y cómo deben comportarse.
Diferencia clave:
- Devicetree (.dts): Describe el Hardware (qué placa tengo, qué pines uso).
- Kconfig (.conf): Describe el Software (qué funcionalidades del OS quiero activar).
El archivo prj.conf
En tu proyecto, la configuración se define principalmente en el archivo prj.conf. Es un archivo de texto simple donde asignamos valores a variables de configuración.
La sintaxis es muy sencilla: CONFIG_VARIABLE=valor.
Tipos de valores:
- Booleanos (
y/n): Activan o desactivan una característica. - Enteros: Definen tamaños de buffer, prioridades, tamaños de pila, etc.
- Strings: Nombres de dispositivos, textos por defecto.
Ejemplo práctico
Supongamos que queremos usar la consola para imprimir mensajes (printk), pero también queremos usar el sistema de Logging avanzado de Zephyr y aumentar el tamaño de la pila (Stack) del hilo principal.
Nuestro prj.conf se vería así:
# Activar el soporte para consola
CONFIG_PRINTK=y
# Activar el subsistema de Logging
CONFIG_LOG=y
# Configurar el tamaño del stack del hilo principal a 2048 bytes
CONFIG_MAIN_STACK_SIZE=2048
Cuando ejecutamos west build, el sistema lee este archivo, resuelve las dependencias y genera un archivo de cabecera C (autoconf.h) con todos estos #define.
Las dependencias automáticas
Kconfig evalúa dependencias y valores predeterminados antes de aceptar una opción. Activar CONFIG_BT=y habilita el núcleo del subsistema, pero el rol, el controlador y otras capacidades siguen dependiendo de la placa y de las opciones seleccionadas.
A veces esto puede ser confuso. Si una asignación se ignora, revisa sus dependencias en menuconfig. Si una opción aparece activa sin haberla pedido, otra puede haberla seleccionado o puede tener ese valor por defecto.
Herramientas interactivas: menuconfig y guiconfig
Nadie (ni siquiera los mantenedores de Zephyr) se sabe de memoria las miles de opciones de configuración (CONFIG_...). Por suerte, tenemos herramientas visuales para explorar qué podemos activar.
Desde la terminal, dentro de la carpeta del proyecto, ejecutamos:
west build -t menuconfigEsto abre una interfaz basada en texto dentro de la terminal. Permite navegar por los menús, buscar opciones con / y consultar su ayuda con ?.
Para abrir la interfaz gráfica, usamos:
west build -t guiconfig¡Cuidado! Los cambios que hagas en menuconfig son temporales para esa compilación. Si haces un west build -p always se perderán.
Usa estas herramientas para descubrir el símbolo, por ejemplo CONFIG_I2C, y después escríbelo en prj.conf para conservarlo en futuras compilaciones.
¿Cómo afecta esto a mi código C?
Todo lo que defines en Kconfig se traduce en macros disponibles en tu código C. El prefijo siempre es CONFIG_.
Si en prj.conf tienes:
CONFIG_MY_FEATURE=yEn tu main.c puedes hacer:
#include <zephyr/kernel.h>
int main(void) {
#ifdef CONFIG_MY_FEATURE
printk("¡La funcionalidad está activa!\n");
#endif
return 0;
}Esto es muy potente para hacer código portable que se adapta según la configuración del proyecto.