Introducción: La era del «hardware» cambia de idioma
\n\nSi alguna vez has escrito un firmware para un microcontrolador en C, conoces esa sensación. Esa sensación cuando, después de tres horas de depuración, encuentras un cuelgue: el puntero voló al cielo y el watchdog lo soportó todo. El desarrollo embedded durante muchos años fue territorio de C y ensamblador. Pero en los últimos años, un nuevo jugador ha entrado en escena: Rust. Y no es solo «un lenguaje más», sino un verdadero avance para los sistemas embebidos.
\n\nEn este artículo, analizaremos por qué el desarrollo embedded en Rust no es una moda, sino una necesidad. Veremos ejemplos reales de código, lo compararemos con C y entenderemos por dónde empezar. Si programas para STM32, ESP32 o ARM Cortex-M, esto es para ti.
\n\nPor qué Rust para embedded es la combinación perfecta
\n\nLos sistemas embebidos son un mundo de limitaciones. Poca memoria, sin SO, sin heap, sin excepciones. Un error en compilación es bueno, un error en tiempo de ejecución es malo. Rust fue diseñado precisamente para estas condiciones.
\n\nSeguridad de memoria sin recolector de basura
\n\nEl principal dolor de cabeza del desarrollador embedded en C es el use-after-free, la doble liberación de memoria y el desbordamiento de búfer. Rust resuelve esto a nivel de tipos. El modelo de propiedad (ownership) y préstamo (borrowing) funciona incluso en entornos no_std — sin asignador, sin SO, sin GC.
Imagina que estás escribiendo un controlador para un LED. En C escribirías:
\n\n// C code\nvoid led_on(GPIO_TypeDef *gpio, uint16_t pin) {\n gpio->BSRR = pin;\n}\n\nTodo está bien, hasta que alguien pasa un puntero nulo. Rust no te permitirá hacer eso:
\n\n// Rust code\nfn led_on(gpio: &mut GpioRegisters, pin: u16) {\n gpio.bsrr.write(|w| w.bits(pin.into()));\n}\n\nAquí, &mut GpioRegisters es una garantía de que la referencia es válida y el acceso a los registros es exclusivo. El compilador simplemente no dejará pasar código peligroso.
Abstracciones de costo cero
\n\nUno de los mayores miedos de los desarrolladores embedded es que un lenguaje de alto nivel «consuma» ciclos de procesador. Rust sigue el principio de zero-cost abstractions: solo pagas por lo que usas. Iteradores, closures, traits: todo se compila en código máquina tan eficiente como el desenrollado manual de bucles en C.
\n\nAdemás, en el ecosistema embedded de Rust hay crates que funcionan a nivel de instrucciones individuales. Por ejemplo, cortex-m-rt genera el vector de interrupciones y el código de inicio sin una sola instrucción extra.
Proyecto real: parpadeo de un LED en Rust (STM32)
\n\nEscribamos un programa simple para la placa STM32F3Discovery. Usaremos cortex-m-quickstart y el HAL de la comunidad embedded rust.
Paso 1: Configuración del proyecto
\n\nAsegúrate de tener instalados Rust y la cadena de herramientas para ARM Cortex-M:
\n\nrustup target add thumbv7em-none-eabihf\ncargo install cargo-generate\n\nCreamos el proyecto a partir de la plantilla:
\n\ncargo generate --git https://github.com/rust-embedded/cortex-m-quickstart\n\nPaso 2: Escribimos el código
\n\nAbrimos src/main.rs y escribimos el clásico Blinky:
#![no_std]\n#![no_main]\n\nuse cortex_m_rt::entry;\nuse panic_halt as _;\nuse stm32f3xx_hal::{pac, prelude::*};\n\n#[entry]\nfn main() -> ! {\n // Obtenemos acceso a la periferia\n let dp = pac::Peripherals::take().unwrap();\n let mut rcc = dp.RCC.constrain();\n let mut gpioe = dp.GPIOE.split(&mut rcc.ahb);\n\n // Configuramos el pin PE9 como salida (LED LD1)\n let mut led = gpioe\n .pe9\n .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper);\n\n loop {\n led.set_high().unwrap();\n cortex_m::asm::delay(8_000_000);\n led.set_low().unwrap();\n cortex_m::asm::delay(8_000_000);\n }\n}\n\n¿Qué sucede aquí?
\n- \n
#![no_std]— estamos en un entorno sin biblioteca estándar. \n #![no_main]— no usamos la función main convencional, sino el punto de entrada de cortex-m. \n use stm32f3xx_hal::...— importamos el HAL específico para nuestra placa. \n - Dentro del bucle, encendemos y apagamos el LED con retardos. \n
Este código es seguro, eficiente y no puede fallar por punteros nulos o violaciones de memoria. El compilador de Rust garantiza que no haya accesos concurrentes no controlados a los registros.
\n\nRust vs C en embedded: comparativa real
\n\nVeamos una tabla comparativa de aspectos clave para el desarrollo embedded:
\n\n| Característica | \nC | \nRust | \n
|---|---|---|
| Seguridad de memoria | \nManual (propenso a errores) | \nGarantizada en compilación | \n
| Abstracciones de costo cero | \nParcial (depende del programador) | \nSí (garantizado por el compilador) | \n
| Soporte para no_std | \nNativo | \nExcelente (ecosistema creciendo) | \n
| Curva de aprendizaje | \nMedia | \nAlta (ownership, lifetimes) | \n
| Herramientas (IDE, depurador) | \nMaduras (Keil, IAR, GCC) | \nEn crecimiento (VS Code, probe-rs) | \n
| Rendimiento | \nExcelente | \nExcelente (comparable a C) | \n
Como ves, Rust no es perfecto en todo, pero donde gana, lo hace de forma contundente: seguridad de memoria sin sacrificar rendimiento.
\n\n¿Vale la pena aprender Rust para embedded en 2025?
\n\nLa respuesta corta es: sí, definitivamente. Pero con matices.
\n\nRazones para aprenderlo ahora
\n- \n
- Demanda creciente: Empresas como Google (Android), Microsoft (Azure IoT) y Tesla están adoptando Rust para firmware. \n
- Ecosistema madurando: Crates como
embassy,rticyesp-rshacen que el desarrollo sea productivo. \n - Seguridad por defecto: En sistemas críticos (automoción, médico, aeroespacial), Rust reduce drásticamente los errores. \n
- Comunidad activa: El grupo de trabajo embedded rust de Rust publica regularmente guías y herramientas. \n
Cuándo seguir con C
\n- \n
- Si trabajas con microcontroladores muy pequeños (8 bits, poca RAM). \n
- Si tu equipo ya tiene una base de código enorme en C y no hay presupuesto para migrar. \n
- Si necesitas soporte de herramientas muy específicas (compiladores propietarios, depuradores antiguos). \n
Conclusión: Rust no mata a C, pero le quita el trono
\n\nEl desarrollo embedded está en un punto de inflexión. C y C++ han reinado durante décadas, pero sus debilidades en seguridad de memoria son cada vez más difíciles de ignorar. Rust ofrece una alternativa moderna, segura y eficiente que se adapta perfectamente a las restricciones de los sistemas embebidos.
\n\nSi eres desarrollador embedded, aprender Rust en 2025 no es solo una inversión en tu carrera, es prepararte para el futuro de la industria. El «rey» C sigue siendo poderoso, pero el heredero ya está aquí.
\n\n¿Ya has probado Rust para tus proyectos embedded? ¡Cuéntanos tu experiencia en los comentarios!