Skip to content

Instantly share code, notes, and snippets.

@IoTeacher
Last active May 30, 2025 20:57
Show Gist options
  • Save IoTeacher/ff1ced4d425d40e3691b321e08cf06b6 to your computer and use it in GitHub Desktop.
Save IoTeacher/ff1ced4d425d40e3691b321e08cf06b6 to your computer and use it in GitHub Desktop.

Investigación de Pico W con Rust, para prox. semestre emigrar a este lenguaje y dejar C y python

image

Dejar comentarios poniendo encabezado, ponerse de acuerdo para no duplicar.

1.- Marco Teorico en markdown justificando RUST como alternativa para Raspberry Pico W

2.- 10 practicas de RUST para Raspberry PucoW donde la primera es paso a paso, compilar, enlazar y subir a el memoria flash de picow

3- Sobre compilador, liberias, plataformas de desarroolo o extensiones. Linux, mac, windows, AWS. No hay un simulador en linea pero se requiere una apoyo de seguridad del dispositivo. Investigar como depurar la pico W con otras plataformas y cables por ejemplo OPENOCD https://openocd.org debuger por hardware

@jempcito
Copy link

Rust como Alternativa para el Desarrollo en Raspberry Pi Pico W

1. Introducción a los Sistemas Embebidos y Microcontroladores

Los sistemas embebidos son sistemas informáticos diseñados para realizar funciones específicas dentro de un sistema mecánico o eléctrico más grande, a menudo con restricciones de tiempo real. Los microcontroladores (MCUs) son el corazón de muchos de estos sistemas, integrando un procesador, memoria y periféricos de entrada/salida en un solo chip. El Raspberry Pi Pico W, basado en el MCU RP2040 de Raspberry Pi, es un ejemplo prominente y accesible, que destaca por su procesador ARM Cortex-M0+ de doble núcleo y su conectividad Wi-Fi integrada.

La programación de MCUs tradicionalmente ha estado dominada por lenguajes como C y C++, debido a su capacidad para operar cerca del hardware, su eficiencia en el uso de recursos y su madurez en el ecosistema embebido. Sin embargo, estos lenguajes presentan desafíos significativos, especialmente en términos de seguridad de memoria y gestión de la concurrencia.

2. Panorama Actual del Desarrollo en Raspberry Pi Pico W

Actualmente, el desarrollo para el Raspberry Pi Pico W se centra principalmente en dos enfoques:

2.1. C/C++

  • Fortalezas:
    • Rendimiento óptimo y control directo del hardware.
    • Acceso a todas las funcionalidades del SDK oficial de Raspberry Pi (Pico SDK).
    • Amplia base de código existente y bibliotecas para periféricos.
  • Debilidades:
    • Gestión manual de memoria: Propensa a errores como desbordamientos de búfer, punteros colgantes y fugas de memoria, que pueden llevar a comportamientos indefinidos y vulnerabilidades de seguridad.
    • Complejidad: Puede ser verboso y requerir una comprensión profunda de la arquitectura subyacente.
    • Seguridad en concurrencia: La gestión de la concurrencia (aprovechando los dos núcleos del RP2040) recae enteramente en el programador, lo que incrementa el riesgo de condiciones de carrera (race conditions) y deadlocks.

2.2. MicroPython

  • Fortalezas:
    • Facilidad de uso y rápida prototipación gracias a la sintaxis de Python.
    • Gran comunidad y abundancia de módulos.
    • Interpretado, lo que simplifica el ciclo de desarrollo para tareas sencillas.
  • Debilidades:
    • Rendimiento: Significativamente más lento que el código compilado (C/C++ o Rust) debido a la naturaleza interpretada y la sobrecarga del recolector de basura.
    • Consumo de memoria: Generalmente mayor que en lenguajes compilados, una consideración importante en MCUs con RAM limitada.
    • Control de bajo nivel: Menos directo y, a veces, más limitado que con C/C++.
    • Global Interpreter Lock (GIL): Limita el paralelismo real en implementaciones estándar de Python, aunque MicroPython puede tener estrategias diferentes para la concurrencia en MCUs.

3. Rust como Alternativa Emergente y Prometedora

Rust es un lenguaje de programación de sistemas moderno que se enfoca en la seguridad, la velocidad y la concurrencia. Fue diseñado para resolver muchos de los problemas inherentes a lenguajes como C y C++.

3.1. Principios Fundamentales de Rust Aplicados a Embebidos

  • Seguridad de Memoria sin Recolector de Basura (Garbage Collector):

    • El sistema de propiedad (ownership), préstamos (borrowing) y tiempos de vida (lifetimes) de Rust garantiza la seguridad de la memoria en tiempo de compilación. Esto previene errores comunes como desbordamientos de búfer, punteros nulos y fugas de memoria sin la sobrecarga de un recolector de basura, lo cual es crucial para sistemas con recursos limitados y requisitos de tiempo real.
    • Para el Pico W, esto significa mayor fiabilidad y menor probabilidad de fallos catastróficos en aplicaciones críticas.
  • Rendimiento comparable a C/C++:

    • Rust compila a código máquina nativo y ofrece abstracciones de costo cero, lo que significa que las abstracciones de alto nivel no introducen sobrecarga en tiempo de ejecución.
    • Esto permite desarrollar código de alto nivel y expresivo sin sacrificar el rendimiento, vital para el Pico W donde la eficiencia es clave.
  • Concurrencia Segura (Fearless Concurrency):

    • El compilador de Rust previene las condiciones de carrera (data races) en tiempo de compilación. Esto es especialmente relevante para el RP2040 del Pico W, que cuenta con dos núcleos Cortex-M0+.
    • Características como async/await para programación asíncrona permiten un manejo eficiente de operaciones de E/S (como las comunicaciones Wi-Fi del Pico W) sin bloquear hilos.
  • Ecosistema y Herramientas Modernas:

    • Cargo: El gestor de paquetes y sistema de compilación de Rust simplifica la gestión de dependencias y la compilación cruzada para arquitecturas embebidas.
    • Comunidad de Embebidos en Crecimiento: Proyectos como embedded-hal, rp-hal (HAL para la familia RP2040), y embassy (framework asíncrono para embebidos) proporcionan abstracciones de hardware robustas y seguras.
    • Excelente Soporte de Herramientas (LSP): rust-analyzer ofrece autocompletado, detección de errores en tiempo real y refactorización, mejorando la productividad del desarrollador.
  • Interoperabilidad con C (FFI - Foreign Function Interface):

    • Rust puede interactuar fácilmente con código C existente. Esto es útil para reutilizar bibliotecas C o partes del Pico SDK oficial si fuera necesario, aunque el objetivo a largo plazo suele ser tener implementaciones puras en Rust.

3.2. Justificación de Rust para el Raspberry Pi Pico W

  • Aprovechamiento de Recursos Limitados: La ausencia de un recolector de basura y las abstracciones de costo cero hacen que Rust sea ideal para los 264KB de SRAM y 2MB de Flash del Pico. El control granular sobre la memoria permite optimizar su uso.

  • Fiabilidad y Robustez: La seguridad de memoria garantizada por el compilador reduce drásticamente la probabilidad de errores difíciles de depurar en tiempo de ejecución, lo que es crucial para dispositivos que pueden operar de forma desatendida o en entornos críticos.

  • Explotación del Dual-Core: Las capacidades de concurrencia segura de Rust facilitan el desarrollo de aplicaciones que utilicen eficientemente ambos núcleos del RP2040, mejorando el rendimiento general del sistema.

  • Desarrollo de Controladores de Periféricos Seguros: El sistema de tipos de Rust y el uso de HALs (Hardware Abstraction Layers) permiten crear interfaces seguras y expresivas para los periféricos del Pico W (GPIO, SPI, I2C, ADC, PWM, Wi-Fi). Por ejemplo, el crate cyw43 permite interactuar con el chip Wi-Fi del Pico W de forma segura.

  • Productividad y Mantenibilidad: Aunque la curva de aprendizaje de Rust puede ser más pronunciada inicialmente, sus fuertes garantías en tiempo de compilación y su expresividad conducen a un código más mantenible y menos propenso a errores a largo plazo.

4. Desafíos y Consideraciones

A pesar de sus ventajas, la adopción de Rust en el Pico W también presenta desafíos:

  • Curva de Aprendizaje: El sistema de propiedad y tiempos de vida puede ser complejo para programadores no familiarizados con estos conceptos.
  • Madurez del Ecosistema: Aunque crece rápidamente, el ecosistema de Rust para embebidos es más joven que el de C/C++. Algunas bibliotecas o soporte para periféricos específicos pueden ser menos maduros o estar ausentes.
  • Tiempos de Compilación: Pueden ser más largos en comparación con C, especialmente en proyectos grandes.
  • Configuración Inicial: El "bare-metal setup" puede requerir un poco más de esfuerzo inicial comparado con el entorno C/C++ del Pico SDK o MicroPython.

@Joc193
Copy link

Joc193 commented May 30, 2025

10 Prácticas Rust para Raspberry Pi Pico W.

Practicas Rust, Autor: CHATGPT

1. Parpadeo del LED integrado (paso a paso)

#![no_std]
#![no_main]

use rp_pico::entry;
use rp_pico::hal::{pac, watchdog::Watchdog, clocks::init_clocks_and_plls, sio::Sio, Timer, gpio::Pins};
use embedded_hal::digital::v2::OutputPin;
use panic_halt as _;

#[entry]
fn main() -> ! {
    let mut pac = pac::Peripherals::take().unwrap();
    let core = pac::CorePeripherals::take().unwrap();
    let mut watchdog = Watchdog::new(pac.WATCHDOG);
    let clocks = init_clocks_and_plls(
        rp_pico::XOSC_CRYSTAL_FREQ,
        pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB,
        &mut pac.RESETS, &mut watchdog
    ).unwrap();

    let sio = Sio::new(pac.SIO);
    let pins = Pins::new(pac.IO_BANK0, pac.PADS_BANK0, sio.gpio_bank0, &mut pac.RESETS);
    let mut led_pin = pins.led.into_push_pull_output();
    let mut timer = Timer::new(pac.TIMER, &mut pac.RESETS);

    loop {
        led_pin.set_high().unwrap();
        timer.delay_ms(500);
        led_pin.set_low().unwrap();
        timer.delay_ms(500);
    }
}

2. Imprimir un mensaje por UART

#![no_std]
#![no_main]

use core::fmt::Write;
use panic_halt as _;
use rp_pico::entry;
use rp_pico::hal::{pac, sio::Sio, clocks::init_clocks_and_plls, watchdog::Watchdog, uart::UartPeripheral, gpio::Pins};

#[entry]
fn main() -> ! {
    let mut pac = pac::Peripherals::take().unwrap();
    let mut watchdog = Watchdog::new(pac.WATCHDOG);
    let clocks = init_clocks_and_plls(
        rp_pico::XOSC_CRYSTAL_FREQ,
        pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB,
        &mut pac.RESETS, &mut watchdog,
    ).unwrap();

    let sio = Sio::new(pac.SIO);
    let pins = Pins::new(pac.IO_BANK0, pac.PADS_BANK0, sio.gpio_bank0, &mut pac.RESETS);

    let uart_pins = (
        pins.gpio0.into_mode::<rp_pico::hal::gpio::FunctionUart>(),
        pins.gpio1.into_mode::<rp_pico::hal::gpio::FunctionUart>(),
    );

    let mut uart = UartPeripheral::new(pac.UART0, uart_pins, &mut pac.RESETS)
        .enable(rp_pico::hal::uart::common_configs::_115200_8_N_1, clocks.peripheral_clock.freq())
        .unwrap();

    writeln!(uart, "Hola desde Rust y Pico W\r").unwrap();

    loop {}
}

3. Imprimir una suma simple

let a = 5;
let b = 3;
let suma = a + b;
writeln!(uart, "La suma de {} + {} es {}\r", a, b, suma).unwrap();

4. Mostrar números del 1 al 10

for i in 1..=10 {
    writeln!(uart, "Número: {}\r", i).unwrap();
}

5. Multiplicación simple

let x = 6;
let y = 9;
let producto = x * y;
writeln!(uart, "{} x {} = {}\r", x, y, producto).unwrap();

6. Conversión de libras a kilogramos

let libras = 180.0;
let kg = libras * 0.453592;
writeln!(uart, "{} lb = {:.2} kg\r", libras, kg).unwrap();

7. Mostrar tabla de cuadrados del 1 al 10

for i in 1..=10 {
    writeln!(uart, "{}^2 = {}\r", i, i * i).unwrap();
}

8. Tabla de multiplicar del 7

for i in 1..=10 {
    writeln!(uart, "7 x {} = {}\r", i, 7 * i).unwrap();
}

9. Sumar enteros del 1 al 100

let mut suma = 0;
for i in 1..=100 {
    suma += i;
}
writeln!(uart, "Suma de 1 a 100 = {}\r", suma).unwrap();

10. Promedio de tres números

let a = 80;
let b = 90;
let c = 85;
let promedio = (a + b + c) / 3;
writeln!(uart, "Promedio = {}\r", promedio).unwrap();

@ulisetrejo250
Copy link

ulisetrejo250 commented May 30, 2025

1. Compilador y Librerías
Rust usa rustc como compilador y cargo como gestor de paquetes. Para la Pico W, se requiere la instalación de la cadena de herramientas adecuada:

Instalar Rust: rustup target add thumbv6m-none-eabi.
Librerías clave: rp-hal es una capa de abstracción de hardware para la serie RP2040.

2.Plataformas de Desarrollo
Rust es compatible con múltiples plataformas:

Linux/macOS: Se puede usar cargo junto con probe-rs para flashear el firmware.

Windows: Se recomienda usar WSL2 o instalar cargo-binutils para la conversión de formatos.

AWS: No hay soporte directo, pero se puede usar contenedores para compilar firmware en la nube.

3. Depuración con OpenOCD
Para depurar la Pico W con hardware, se usa OpenOCD:

Instalar OpenOCD: git clone https://github.com/raspberrypi/openocd.git --branch rp2040

Compilar: ./bootstrap && ./configure --enable-picoprobe && make -j4

Conectar hardware: Se usa Picoprobe para conectar dos Picos y depurar con GDB.

  1. Seguridad de Memoria
    Rust: Previene errores de memoria con su sistema de propiedad y verificación en tiempo de compilación.

C: Requiere gestión manual de memoria, lo que puede generar vulnerabilidades como desbordamientos de búfer.

2. Plataformas de Desarrollo
Rust es compatible con múltiples plataformas:

Linux/macOS: Se puede usar cargo junto con probe-rs para flashear el firmware.

Windows: Se recomienda usar WSL2 o instalar cargo-binutils para la conversión de formatos.

AWS: No hay soporte directo, pero se puede usar contenedores para compilar firmware en la nube.

3.Para depurar la Pico W con hardware, se usa OpenOCD:

Instalación de OpenOCD:

git clone https://github.com/raspberrypi/openocd.git --branch rp2040

Compilación:

./bootstrap && ./configure --enable-picoprobe && make -j4

4. Comparativa entre Rust y C

  1. Seguridad de Memoria
    Rust: Previene errores de memoria con su sistema de propiedad y verificación en tiempo de compilación.

C: Requiere gestión manual de memoria, lo que puede generar vulnerabilidades como desbordamientos de búfer.

  1. Concurrencia y Paralelismo
    Rust: Ofrece primitivas seguras para concurrencia, evitando condiciones de carrera.

C: Permite control manual, pero es propenso a errores en programación concurrente.

  1. Velocidad de Ejecución
    Rust: Tiene una ligera sobrecarga por verificaciones de seguridad, pero es comparable a C en rendimiento.

C: Es altamente optimizado y ofrece control total sobre detalles de bajo nivel.

  1. Depuración y Desarrollo
    Rust: Su compilador detecta errores antes de la ejecución, reduciendo fallos en producción.

C: Depuración más difícil, ya que los errores pueden aparecer en tiempo de ejecución.

5. Tendencias Futuras para Rust y C
Rust: Crecimiento y Expansión
Optimización del compilador: Mejoras en SIMD, evaluación de funciones en tiempo de compilación y optimización en tiempo de enlace.

Mayor adopción en la industria: Empresas como Microsoft y Google están migrando partes de su código a Rust debido a su seguridad de memoria.

Expansión en sistemas embebidos: Rust se está volviendo más popular en dispositivos IoT y sistemas embebidos gracias a su eficiencia y seguridad.

Uso en la nube: Se espera que Rust tenga un mayor impacto en el desarrollo de infraestructura en la nube y servicios de alto rendimiento.

C: Persistencia y Especialización
Aunque Rust está creciendo, C sigue siendo fundamental en ciertos sectores:

Optimización extrema: C sigue siendo la mejor opción para sistemas donde cada ciclo de CPU cuenta, como en firmware y sistemas operativos.

Compatibilidad y legado: Muchas aplicaciones críticas aún dependen de C, y su ecosistema es difícil de reemplazar completamente.

Seguridad mejorada: Se están desarrollando herramientas para mejorar la seguridad en C, aunque no igualan el enfoque de Rust

ejemplo:

let a = 5;
let b = 3;
let suma = a + b;
writeln!(uart, "La suma de {} + {} es {}\r", a, b, suma).unwrap();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment