zephyr-overlays-modificar-hardware

Uso de overlays en Zephyr para modificar el hardware

  • 5 min

Overlay es un fragmento de Devicetree que añade o modifica nodos de la placa base sin editar los archivos originales de Zephyr.

Seguramente conectarás un sensor I2C, una pantalla SPI o quizá necesites reasignar la consola UART porque interfiere con tu diseño.

Aquí surge la duda: ¿Tengo que editar el archivo .dts original de la placa que está en la carpeta de instalación de Zephyr?

¡Rotundamente NO!

Si editas los archivos originales de Zephyr (zephyr/boards/...), perderás los cambios al actualizar y ensuciarás la instalación. Para evitarlo utilizamos los overlays o superposiciones.

¿Qué es un overlay?

Podemos pensar en el Devicetree de la placa como un plano base. Un overlay sería una hoja transparente colocada encima para añadir o corregir elementos sin alterar el original.

  • Puedes añadir muebles nuevos (sensores).
  • Puedes tachar una pared (desactivar un periférico).
  • Puedes cambiar el color de una habitación (cambiar una propiedad, como el baudrate).

Cuando compilamos con west build, el sistema coge el plano base, le pega nuestro papel cebolla encima, y genera el plano definitivo.

Crear nuestro primer overlay

Por defecto, el sistema de construcción de Zephyr busca un archivo llamado app.overlay en la carpeta raíz de tu proyecto (al mismo nivel que prj.conf y CMakeLists.txt).

Cualquier cosa que escribas ahí se sumará a la definición de la placa seleccionada.

Sintaxis: referenciar nodos

Siempre que exista una etiqueta de nodo estable, es preferible referenciarla con &etiqueta en lugar de repetir la ruta completa.

No intentes navegar por toda la ruta del árbol (/soc/peripheral@4000/i2c@...), porque es frágil. En su lugar, usamos el operador & seguido de la etiqueta del nodo que queremos modificar.

Supongamos que queremos cambiar la velocidad de la consola UART por defecto a 9600 baudios (por defecto suele ser 115200).

En tu archivo app.overlay:

/* Referenciamos al nodo que tiene la etiqueta 'uart0' */
&uart0 {
    current-speed = <9600>;
};
Copied!

¡Ya está! Al compilar, Zephyr verá que quieres modificar &uart0 y sobrescribirá la propiedad current-speed.

¿Cómo sé qué etiqueta usar? Tienes que mirar el archivo .dts original de tu placa (en zephyr/boards/...) o buscar en la documentación de la placa. Lo más común es &uart0, &i2c0, &spi1, &gpio0, etc.

Añadir un sensor I2C

Este es el caso de uso más habitual. Tienes una placa (ej. nRF52DK o ESP32) y le conectas un sensor de temperatura BME280 en los pines I2C.

El bus I2C ya existe en la placa, pero el sensor no. Tenemos que:

  1. Activar el bus I2C (a veces viene desactivado por defecto).
  2. Añadir el nodo del sensor como “hijo” del bus.

Tu app.overlay quedaría así:

/* 1. Referenciamos el controlador I2C0 */
&i2c0 {
    /* Activamos el periférico */
    status = "okay";

    /* 2. Añadimos nuestro sensor dentro del bus */
    bme280@76 {
        compatible = "bosch,bme280";
        reg = <0x76>; /* Dirección I2C del sensor */
    };
};
Copied!

Fíjate en lo limpio que es. No nos importan los pines SDA/SCL (esos ya están definidos en el nodo &i2c0 de la placa base). Solo decimos: “En el bus i2c0, hay un dispositivo bme280 en la dirección 0x76”.

El status = "okay" es fundamental. Muchos periféricos vienen definidos en el hardware (status = "disabled") para ahorrar energía. Si no lo pones a “okay” en tu overlay, el driver nunca se iniciará.

Reasignar un GPIO

A veces el diseño de la placa base usa el pin 5 para el LED, pero tú quieres usar el pin 5 para un botón y mover el LED al pin 10.

Aquí sobrescribimos las propiedades del nodo.

/* Un alias no crea una etiqueta de nodo. Referenciamos la ruta real. */

/* Opción A: Modificar el nodo existente */
&{/leds/led_0} {
    /* Cambiamos al puerto gpio0, pin 10 */
    gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>;
};

/* Opción B: Crear nuestro propio alias */
/ {
    aliases {
        mi-led-personalizado = &my_new_led;
    };

    leds {
        compatible = "gpio-leds";
        my_new_led: led_custom {
            gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
        };
    };
};
Copied!

¿Cómo verificar que ha funcionado?

A veces cometemos errores de sintaxis o nos equivocamos de etiqueta. La forma definitiva de saber qué está viendo Zephyr es inspeccionar el Devicetree final compilado.

Después de ejecutar west build, abre el archivo:

build/zephyr/zephyr.dts

Este archivo es la suma de: DTS del procesador + DTS de la placa + Tu app.overlay.

Si el cambio aparece ahí, el overlay se ha aplicado. Un error de sintaxis detiene la configuración; si no hay error pero falta el cambio, revisa en la salida de CMake la línea Found devicetree overlay para confirmar qué archivo se cargó.

Overlays específicos por placa

Si tu proyecto tiene que funcionar en dos placas distintas (ej. una versión para Arduino Nano 33 BLE y otra para ESP32), y cada una requiere una configuración diferente, puedes crear archivos específicos.

En lugar de app.overlay, crea una carpeta boards/ en tu proyecto y dentro poned:

  • boards/<BOARD>.overlay
  • socs/<SOC>_<BOARD_QUALIFIERS>.overlay

El sistema de compilación selecciona estos archivos según el board target. También puedes indicar uno de forma explícita con -DDTC_OVERLAY_FILE=ruta/al/archivo.overlay.