Rust irrumpe en el mundo embedded: por qué C ya no es el rey

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: La era del «hardware» cambia de idioma

\n\n

Si 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\n

En 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\n

Por qué Rust para embedded es la combinación perfecta

\n\n

Los 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\n

Seguridad de memoria sin recolector de basura

\n\n

El 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.

\n\n

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\n

Todo 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\n

Aquí, &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.

\n\n

Abstracciones de costo cero

\n\n

Uno 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\n

Ademá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.

\n\n

Proyecto real: parpadeo de un LED en Rust (STM32)

\n\n

Escribamos un programa simple para la placa STM32F3Discovery. Usaremos cortex-m-quickstart y el HAL de la comunidad embedded rust.

\n\n

Paso 1: Configuración del proyecto

\n\n

Asegúrate de tener instalados Rust y la cadena de herramientas para ARM Cortex-M:

\n\n
rustup target add thumbv7em-none-eabihf\ncargo install cargo-generate
\n\n

Creamos el proyecto a partir de la plantilla:

\n\n
cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart
\n\n

Paso 2: Escribimos el código

\n\n

Abrimos src/main.rs y escribimos el clásico Blinky:

\n\n
#![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
\n\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\n

Rust vs C en embedded: comparativa real

\n\n

Veamos una tabla comparativa de aspectos clave para el desarrollo embedded:

\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
CaracterísticaCRust
Seguridad de memoriaManual (propenso a errores)Garantizada en compilación
Abstracciones de costo ceroParcial (depende del programador)Sí (garantizado por el compilador)
Soporte para no_stdNativoExcelente (ecosistema creciendo)
Curva de aprendizajeMediaAlta (ownership, lifetimes)
Herramientas (IDE, depurador)Maduras (Keil, IAR, GCC)En crecimiento (VS Code, probe-rs)
RendimientoExcelenteExcelente (comparable a C)
\n\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\n

La respuesta corta es: sí, definitivamente. Pero con matices.

\n\n

Razones 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, rtic y esp-rs hacen 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
\n\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
\n\n

Conclusión: Rust no mata a C, pero le quita el trono

\n\n

El 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\n

Si 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!

Blogs

Book Recommendations