Módulo 0.4

Capas de abstracción en firmware moderno

¿Cómo se organiza el firmware moderno?

Santi Scagliusi, PhD

Comenzar arrow_downward
layers
Capas
Del hardware a la app
swap_vert
Flujo
Cómo fluye el código
account_tree
DeviceTree
Descripción hardware
tune
Kconfig
Configuración build

¿Por qué existen las capas de abstracción?

El hardware es complejo y cambia constantemente. Las capas de abstracción permiten escribir código portable y mantenible.

error Sin abstracción

memory

Acceso directo a registros

Código atado a direcciones de memoria específicas del chip. Imposible de portar.

lock

Vendor lock-in

Todo el código debe reescribirse si cambias de fabricante o de modelo de chip.

bug_report

Difícil de probar

Sin capas, es imposible hacer tests unitarios o simular el hardware.

check_circle Con abstracción

api

APIs unificadas

Una función como gpio_pin_toggle() funciona igual en cualquier chip soportado.

swap_horiz

Portabilidad

Cambiar de Nordic a STM32 solo requiere cambiar la configuración, no el código.

science

Testable

Las capas permiten crear mocks y ejecutar tests en el ordenador sin hardware.

Comparación de código

Sin abstracción (nRF52)
// Direcciones específicas del nRF52840
#define GPIO_BASE 0x50000000
#define OUT_SET 0x508
void led_on(void) {
*(uint32_t*)(GPIO_BASE + OUT_SET) = (1 << 13);
}
Con abstracción (Zephyr)
// Funciona en cualquier chip
#include <zephyr/drivers/gpio.h>
void led_on(void) {
gpio_pin_set_dt(&led, 1);
}

Las capas del firmware moderno

Haz clic en cada capa para ver qué contiene y su función en el sistema.

apps
Aplicación
Tu código - threads de usuario
extension
Subsistemas
BLE, WiFi, USB, Filesystem
hub
RTOS Kernel
Scheduler, threads, IPC, sincronización
settings_input_component
Drivers
Interfaces de alto nivel para periféricos
developer_board
HAL
Hardware Abstraction Layer - registros
memory
Hardware
MCU, periféricos, GPIO, ADC, timers
apps

Capa de Aplicación

Aquí escribes la lógica de tu aplicación. Son los threads que defines tú: leer sensores, procesar datos, controlar actuadores.

Ejemplos
  • check Thread de lectura de sensores
  • check Lógica de control de dispositivo
  • check Máquina de estados de la aplicación

¿Cómo fluye el código?

Veamos qué sucede cuando llamas a gpio_pin_toggle() desde tu aplicación.

Flujo de gpio_pin_toggle()
// 1. Tu código (Aplicación)
gpio_pin_toggle_dt(&led);
// 2. Driver GPIO (zephyr/drivers/gpio)
int gpio_pin_toggle(...) {
  return api->pin_toggle(port, pin);
}
// 3. HAL Nordic (hal_nordic)
nrf_gpio_pin_toggle(pin);
// 4. Acceso a registro (Hardware)
NRF_P0->OUT ^= (1 << pin);
Paso 1/4

Capas involucradas

1
Aplicación
gpio_pin_toggle_dt(&led)
2
Driver
Zephyr GPIO driver API
3
HAL
nrf_gpio_pin_toggle()
4
Hardware
Registro NRF_P0->OUT
info
Importante: Tú solo escribes código en la capa 1. Las demás capas las proporciona Zephyr y el SDK de Nordic.

DeviceTree: describe tu hardware

DeviceTree separa la descripción del hardware del código. Así tu código C no tiene direcciones ni configuraciones específicas.

account_tree

¿Qué es DeviceTree?

Un formato de datos que describe el hardware de tu sistema: qué periféricos tiene, en qué direcciones están, cómo están conectados.

  • check_circle Originado en Linux, adaptado para sistemas embebidos
  • check_circle Archivos .dts (source) y .dtsi (includes)
  • check_circle Se compila en tiempo de build, no en runtime

lightbulb Ventaja clave

Tu código C usa nombres simbólicos como &led0 en lugar de direcciones como 0x50000508. Si cambias de placa, solo cambias el DeviceTree.

nrf52840dk_nrf52840.overlay
/* Definición de un LED */
/ {
leds {
compatible = "gpio-leds";
led0: led_0 {
gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
label = "Green LED 0";
};
};
/* Alias para acceso fácil */
aliases {
led0 = &led0;
};
};
main.c - Uso en código
// Obtener referencia del DeviceTree
#define LED0_NODE DT_ALIAS(led0)
static const struct gpio_dt_spec led =
GPIO_DT_SPEC_GET(LED0_NODE, gpios);
// Usar sin conocer direcciones
gpio_pin_toggle_dt(&led);

Kconfig: configura tu build

Kconfig permite activar o desactivar funcionalidades en tiempo de compilación. Solo se incluye lo que necesitas.

prj.conf
# Configuración general
CONFIG_GPIO=y
CONFIG_LOG=y
# Activar Bluetooth
CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="MiDispositivo"
# Desactivar funciones no usadas
CONFIG_BT_CENTRAL=n
# Configuración numérica
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_BT_MAX_CONN=1
tune

¿Qué es Kconfig?

Sistema heredado del kernel Linux que permite configurar opciones de compilación de forma estructurada y con dependencias.

  • check_circle Archivo prj.conf en tu proyecto
  • check_circle Genera autoconf.h con #define
  • check_circle Valida dependencias automáticamente
Build-time

La configuración se resuelve al compilar. El binario solo incluye código necesario.

Optimización

Menos código = menos Flash y RAM. Ideal para microcontroladores con recursos limitados.

warning
DeviceTree vs Kconfig: DeviceTree describe el hardware físico. Kconfig configura el software y qué funcionalidades activar.

¿Por qué todo esto importa?

Las capas de abstracción no son complejidad innecesaria. Son la base del desarrollo profesional de firmware.

swap_horiz

Portabilidad

Tu aplicación funciona en Nordic, STM32, ESP32 u otros con cambios mínimos. Solo cambias la configuración de placa.

science

Testabilidad

Puedes crear mocks de las capas inferiores y ejecutar tests unitarios en tu ordenador sin hardware físico.

build

Mantenibilidad

Cada capa tiene una responsabilidad clara. Los cambios en una capa no afectan a las demás si la interfaz se mantiene.

group

Trabajo en equipo

Diferentes desarrolladores pueden trabajar en distintas capas simultáneamente sin pisarse el código.

security

Seguridad

Las capas de abstracción permiten aislar código seguro del no seguro (TrustZone, secure boot).

code

Código profesional

Es la forma en que se desarrolla firmware en la industria. Este conocimiento es directamente aplicable en empresas.

Resumen de herramientas

Las herramientas clave del ecosistema Zephyr y cuándo se utilizan.

Herramienta Propósito Archivo típico Cuándo se procesa
DeviceTree Describe el hardware .dts, .dtsi, .overlay Tiempo de compilación
Kconfig Configura el software prj.conf, Kconfig Tiempo de compilación
CMake Sistema de build CMakeLists.txt Tiempo de compilación
Código C Lógica de aplicación main.c, *.c, *.h Tiempo de ejecución
lightbulb
Recuerda: DeviceTree describe QUÉ hardware tienes. Kconfig configura CÓMO se comporta el software. Ambos se resuelven antes de ejecutar.
check_circle

Lo que aprendiste hoy

Concepto 1

Capas de abstracción

El firmware moderno se organiza en capas: Hardware, HAL, Drivers, Kernel, Subsistemas y Aplicación.

Concepto 2

DeviceTree y Kconfig

DeviceTree describe el hardware, Kconfig configura el software. Ambos se procesan en tiempo de compilación.

Concepto 3

Beneficios profesionales

Portabilidad, testabilidad, mantenibilidad y código profesional. Es como se trabaja en la industria.

tips_and_updates

"Escribe código para la capa de aplicación, deja que Zephyr gestione el resto"

Las capas de abstracción te permiten concentrarte en la lógica de tu aplicación sin preocuparte por los detalles del hardware.

celebration Parte 0 completada

Siguiente: Ecosistema nRF Connect SDK

Has completado los fundamentos. En la Parte 1 comenzaremos a trabajar con el SDK de Nordic: instalación, estructura de proyectos y tu primer programa.