Вграден софтуер

19 януари 2023

Административни неща

Общи разсъждения за embedded software

Общи разсъждения за embedded software

Общи разсъждения за embedded software

Общи разсъждения за embedded software

Общи разсъждения за embedded software

Общи разсъждения за embedded software

Общи разсъждения за embedded software

Възможни решения по дизайна на софтуера

Възможни решения по дизайна на софтуера

Често се налага да се правят компромиси, например

Възможни решения по дизайна на софтуера

Често се налага да се правят компромиси, например

Възможни решения по дизайна на софтуера

Често се налага да се правят компромиси, например

Възможни решения по дизайна на софтуера

Често се налага да се правят компромиси, например

Embedded ОС с Rust

Embedded ОС с Rust

Типични ОС с Rust: FreeRTOS, RTIC,ChibiOS, Zephyr, Drone OS, VxWorks

Embedded ОС с Rust

Типични ОС с Rust: FreeRTOS, RTIC,ChibiOS, Zephyr, Drone OS, VxWorks

Preemptive scheduling

Embedded ОС с Rust

Типични ОС с Rust: FreeRTOS, RTIC,ChibiOS, Zephyr, Drone OS, VxWorks

Preemptive scheduling

Non-preemptive (cooperative) scheduling

WatchDog

WatchDog

WatchDog

Алгоритмичен дизайн

Алгоритмичен дизайн

Алгоритмичен дизайн

Алгоритмичен дизайн

Rust в embedded

Rust в embedded

Rust в embedded

Rust в embedded

Някои коментари по отношение на съпътстващите програми

Някои коментари по отношение на съпътстващите програми

Някои коментари по отношение на съпътстващите програми

Необходимо е да сме инсталирали:
cargo install cargo-binutils
rustup component add llvm-tools-preview

Някои коментари по отношение на съпътстващите програми

Необходимо е да сме инсталирали:
cargo install cargo-binutils
rustup component add llvm-tools-preview

Някои коментари по отношение на съпътстващите програми

Необходимо е да сме инсталирали:
cargo install cargo-binutils
rustup component add llvm-tools-preview

Някои коментари по отношение на съпътстващите програми

Необходимо е да сме инсталирали:
cargo install cargo-binutils
rustup component add llvm-tools-preview

Environment

Environment

Има няколко фактора при избора между std (esp-idf-hal) и no_std (тоест esp-hal).
При no_std приложението е отговорно за използването на свой runtime, примерно riscv-rt
Също така не използване стандартната main функция и не подаваме параметри от командния ред.

Supported platforms

ESP32 board

Targets

Имаме 2 таргета за esp32-c3-rust:

За bare-metal (no_std) applications, ползваме riscv32imc-unknown-none-elf.

За std приложения, ползваме riscv32imc-esp-espidf.
Допълнително -Z build-std unstable cargo feature е необходима, може да бъде добавена и към .cargo/config.toml.
Темплейтите създават този файл.
Инсталацията на rust за RISC-V също може да бъде извършена от espup.

rustup toolchain install nightly --component rust-src

rustup target add riscv32imc-unknown-none-elf

Темплейти за embedded

Поддържат се два темплейта:

1 2 3 4 5 6 7
cargo install cargo-generate

cargo generate --git https://github.com/esp-rs/esp-template

cargo add esp-println --features "esp32c3"

cargo run

Bare metal или no_std

Bare metal или no_std

Bare metal или no_std

Bare metal или no_std

Bare metal или no_std

Bare metal или no_std

1 2 3 4
#![no_std]
fn main() {
  let a = Box::new(7);
}
error[E0433]: failed to resolve: use of undeclared type `Box` --> src/bin/main_2027d7438488e4bc0595f7894414ca942a118ce9.rs:3:11 | 3 | let a = Box::new(7); | ^^^ use of undeclared type `Box` For more information about this error, try `rustc --explain E0433`. error: could not compile `rust` due to previous error
#![no_std]
fn main() {
  let a = Box::new(7);
}

Hands on 2022

Based on RustFest 2019

Hands on 2022

Based on RustFest 2019
Installation on Ubuntu and installation on other platforms

1 2 3 4 5
sudo apt install -y pkg-config libusb-1.0-0-dev libftdi1-dev libudev-dev
cargo install cargo-flash
rustup target add thumbv6m-none-eabi

cargo flash --chip=LPC845M301JBD48

Hands on 2022

Based on RustFest 2019
Installation on Ubuntu and installation on other platforms

1 2 3 4 5
sudo apt install -y pkg-config libusb-1.0-0-dev libftdi1-dev libudev-dev
cargo install cargo-flash
rustup target add thumbv6m-none-eabi

cargo flash --chip=LPC845M301JBD48

Error Failed to open the debug probe.

Hands on 2022

Based on RustFest 2019
Installation on Ubuntu and installation on other platforms

1 2 3 4 5
sudo apt install -y pkg-config libusb-1.0-0-dev libftdi1-dev libudev-dev
cargo install cargo-flash
rustup target add thumbv6m-none-eabi

cargo flash --chip=LPC845M301JBD48

Error Failed to open the debug probe.
https://github.com/knurling-rs/probe-run

Hands on 2022

Based on RustFest 2019
Installation on Ubuntu and installation on other platforms

1 2 3 4 5
sudo apt install -y pkg-config libusb-1.0-0-dev libftdi1-dev libudev-dev
cargo install cargo-flash
rustup target add thumbv6m-none-eabi

cargo flash --chip=LPC845M301JBD48

Error Failed to open the debug probe.
https://github.com/knurling-rs/probe-run

1 2
sudo apt-get install openocd
sudo cp /usr/lib/udev/rules.d/60-openocd.rules /etc/udev/rules.d/

Remove GROUP="plugdev" in /etc/udev/rules.d/60-openocd.rules

Hands on 2022

Based on RustFest 2019
Installation on Ubuntu and installation on other platforms

1 2 3 4 5
sudo apt install -y pkg-config libusb-1.0-0-dev libftdi1-dev libudev-dev
cargo install cargo-flash
rustup target add thumbv6m-none-eabi

cargo flash --chip=LPC845M301JBD48

Error Failed to open the debug probe.
https://github.com/knurling-rs/probe-run

1 2
sudo apt-get install openocd
sudo cp /usr/lib/udev/rules.d/60-openocd.rules /etc/udev/rules.d/

Remove GROUP="plugdev" in /etc/udev/rules.d/60-openocd.rules

1 2
sudo udevadm control –reload
sudo udevadm trigger

Hands on 2023

Based on ESP Community and ESP book no_std application

Hands on 2023

Based on ESP Community and ESP book no_std application

Примери:

Memory

Memory and all limitations are described in *.x files. Example memory.x:

1 2 3 4 5
MEMORY
{
    FLASH : ORIGIN = 0x00000000, LENGTH = 64K
    RAM   : ORIGIN = 0x10000000, LENGTH = 16K
}

Code - setup:

GitHub проект

cargo generate --git https://github.com/esp-rs/esp-template

1 2 3 4 5 6 7 8 9 10 11
#![no_std]
#![no_main]

use esp32c3_hal::{clock::ClockControl, pac::Peripherals, prelude::*,
                  timer::TimerGroup, Rtc};
use esp_backtrace as _;

#[riscv_rt::entry]
fn main() -> ! {
  //...
}

Code 1 - Message + panic:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
let peripherals = Peripherals::take().unwrap();
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();

// Disable the RTC and TIMG watchdog timers
let mut rtc = Rtc::new(peripherals.RTC_CNTL);
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let mut wdt0 = timer_group0.wdt;
let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks);
let mut wdt1 = timer_group1.wdt;

rtc.swd.disable();
rtc.rwdt.disable();
wdt0.disable();
wdt1.disable();

esp_println::println!("Hello World");

panic!("This is a panic");

Code 2 - Blinking:

1 2 3 4 5 6 7 8 9 10
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
let mut led = io.pins.gpio7.into_push_pull_output();

led.set_high().unwrap();
let mut delay = Delay::new(&clocks);

loop {
    led.toggle().unwrap();
    delay.delay_ms(500u32);
}

Code 3 - Button pressed:

1 2 3 4 5 6 7 8 9
let button = io.pins.gpio9.into_pull_up_input();

loop {
    if button.is_high().unwrap() {
        led.set_high().unwrap();
    } else {
        led.set_low().unwrap();
    }
}

Code 4 - Interrupts и Counter:

Добавяме critical_sections в Cargo.toml

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
static BUTTON: Mutex<RefCell<Option<Gpio9<Input<PullUp>>>>> = Mutex::new(RefCell::new(None));
static COUNTER: AtomicUsize = AtomicUsize::new(0);

//...

    let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
    let mut button = io.pins.gpio9.into_pull_up_input();
    button.listen(Event::FallingEdge); // raise interrupt on falling edge

    critical_section::with(|cs| BUTTON.borrow_ref_mut(cs).replace(button));

    interrupt::enable(pac::Interrupt::GPIO, interrupt::Priority::Priority3).unwrap();

    loop {
        COUNTER.fetch_add(1, Ordering::SeqCst);
    }
}

#[interrupt]
fn GPIO() {
  critical_section::with(|cs| {
    esp_println::println!("GPIO interrupt, counter = {:}", COUNTER.load(Ordering::SeqCst));
    COUNTER.store(0, Ordering::SeqCst);
    BUTTON
      .borrow_ref_mut(cs)
      .as_mut()
      .unwrap()
      .clear_interrupt();
  });
}

Процес на develop-ване за embedded

Embedded Rust Ecosystem

Процес на develop-ване за embedded

Embedded Rust Ecosystem

Process: Power up the GPIO Peripherals, configure pin as output, set output to high/low

1 2 3
unsafe {
    *((GPIOC_START + CHR_OFFSET) as *mut u32) = (OUTPUT_MODE << 20) | (PUSH_PULL << 22);
}

Процес на develop-ване за embedded

Embedded Rust Ecosystem

Process: Power up the GPIO Peripherals, configure pin as output, set output to high/low

1 2 3
unsafe {
    *((GPIOC_START + CHR_OFFSET) as *mut u32) = (OUTPUT_MODE << 20) | (PUSH_PULL << 22);
}
1 2 3 4 5 6
dp.GPIOC.crh.modify(|_r, w| {
        w.mode13().output().cnf13().push_pull()
});
dp.GPIOC.odr.modify(|_r, w| {
        w.odr13().high()
});

Процес на develop-ване за embedded - продължение

Процес на develop-ване за embedded - продължение

Процес на develop-ване за embedded - продължение

Процес на develop-ване за embedded - продължение

1 2
#[no_mangle]
pub extern "C" fn rust_function() {}

Обобщение за Embedded-hal, BSP, Crates

Concurrency

Concurrency

Concurrency

Concurrency

1 2 3 4 5 6 7
cortex_m::interrupt::free(|_| {
    unsafe { COUNTER += 1 };
});

static COUNTER: AtomicUsize = AtomicUsize::new(0);
//...
COUNTER.fetch_add(1, Ordering::Relaxed);

Async/await

Async/await

Async/await

Async/await

Async/await

I2C

Популярен комуникационен интерфейс за embedded устройства с минимално натоварване

Definition, Master-Slave, 2 lines, developed by Philips

I2C diagram

I2C

Популярен комуникационен интерфейс за embedded устройства с минимално натоварване

Definition, Master-Slave, 2 lines, developed by Philips

I2C diagram
Ferrous Systems

Ползи от Rust

Ползи от Rust

Ползи от Rust

Ползи от Rust

Ползи от Rust

Ползи от Rust

Ползи от Rust

Ползи от Rust

Ползи от Rust

Въпроси