Вграден софтуер
18 януари 2022
Общи разсъждения за embedded software
Общи разсъждения за embedded software
- Скоростта на изпълнение и размера на паметта са критични фактори за този софтуер. Ако летящия ви дрон блокира за твърде дълго време, правилата на физиката няма да го изчакат.
Общи разсъждения за embedded software
- Скоростта на изпълнение и размера на паметта са критични фактори за този софтуер. Ако летящия ви дрон блокира за твърде дълго време, правилата на физиката няма да го изчакат.
- Скоростта зависи и от тактовата честота, тя е предварително дефинирана
Общи разсъждения за embedded software
- Скоростта на изпълнение и размера на паметта са критични фактори за този софтуер. Ако летящия ви дрон блокира за твърде дълго време, правилата на физиката няма да го изчакат.
- Скоростта зависи и от тактовата честота, тя е предварително дефинирана
- Размера на паметта е пряко свързан с планираната себестойност на продукта
Общи разсъждения за embedded software
- Скоростта на изпълнение и размера на паметта са критични фактори за този софтуер. Ако летящия ви дрон блокира за твърде дълго време, правилата на физиката няма да го изчакат.
- Скоростта зависи и от тактовата честота, тя е предварително дефинирана
- Размера на паметта е пряко свързан с планираната себестойност на продукта
- Често се дефинира опционална функционалност и се решава на по-късен етап дали да бъде включена
Общи разсъждения за embedded software
- Скоростта на изпълнение и размера на паметта са критични фактори за този софтуер. Ако летящия ви дрон блокира за твърде дълго време, правилата на физиката няма да го изчакат.
- Скоростта зависи и от тактовата честота, тя е предварително дефинирана
- Размера на паметта е пряко свързан с планираната себестойност на продукта
- Често се дефинира опционална функционалност и се решава на по-късен етап дали да бъде включена
- Консумацията на енергия също в много случаи е критичен фактор
Общи разсъждения за embedded software
- Скоростта на изпълнение и размера на паметта са критични фактори за този софтуер. Ако летящия ви дрон блокира за твърде дълго време, правилата на физиката няма да го изчакат.
- Скоростта зависи и от тактовата честота, тя е предварително дефинирана
- Размера на паметта е пряко свързан с планираната себестойност на продукта
- Често се дефинира опционална функционалност и се решава на по-късен етап дали да бъде включена
- Консумацията на енергия също в много случаи е критичен фактор
- Често се работи с различни таргет платформи и различни toolchain-ове
Възможни решения по дизайна на софтуера
Възможни решения по дизайна на софтуера
Често се налага да се правят компромиси, например
Възможни решения по дизайна на софтуера
Често се налага да се правят компромиси, например
- Дали да се ползват числа с плаваща запетя или някои математически операции да бъдат извъшени с целочислена аритметика за сметка на точността
Възможни решения по дизайна на софтуера
Често се налага да се правят компромиси, например
- Дали да се ползват числа с плаваща запетя или някои математически операции да бъдат извъшени с целочислена аритметика за сметка на точността
- Дали да се ползва preemptive/non-preemptive OS или да не се ползва OS въобще
Възможни решения по дизайна на софтуера
Често се налага да се правят компромиси, например
- Дали да се ползват числа с плаваща запетя или някои математически операции да бъдат извъшени с целочислена аритметика за сметка на точността
- Дали да се ползва preemptive/non-preemptive OS или да не се ползва OS въобще
Embedded ОС с Rust
Embedded ОС с Rust
Типични ОС с Rust: FreeRTOS, RTIC, Zephyr, Drone OS, VxWorks
Preemptive scheduling
- Нишки: процесора спира таск, кара го да си запази състоянието и сменя на друг.
- Методи: Round Robin, Shortest Remaining Time First
- Предимства на preemptive scheduling: flexible, on demand(interrupt), better response time
- Недостатъци: висок overhead, по-трудна за доказване коректност (препълване на стека)
Embedded ОС с Rust
Типични ОС с Rust: FreeRTOS, RTIC, Zephyr, Drone OS, VxWorks
Preemptive scheduling
- Нишки: процесора спира таск, кара го да си запази състоянието и сменя на друг.
- Методи: Round Robin, Shortest Remaining Time First
- Предимства на preemptive scheduling: flexible, on demand(interrupt), better response time
- Недостатъци: висок overhead, по-трудна за доказване коректност (препълване на стека)
Non-preemptive (cooperative) scheduling
- Всеки таск решава кога да предаде контрол на друг.
- Методи: First Come First Serve, Priority, Shorted Job First
- Предимства на non-preemptive scheduling: нисък overhead, по-малко ресурси, по-лесна за доказване коректност
- Недостатъци: Ограничена функционалност
Embedded ОС с Rust
Типични ОС с Rust: FreeRTOS, RTIC, Zephyr, Drone OS, VxWorks
Preemptive scheduling
- Нишки: процесора спира таск, кара го да си запази състоянието и сменя на друг.
- Методи: Round Robin, Shortest Remaining Time First
- Предимства на preemptive scheduling: flexible, on demand(interrupt), better response time
- Недостатъци: висок overhead, по-трудна за доказване коректност (препълване на стека)
Non-preemptive (cooperative) scheduling
- Всеки таск решава кога да предаде контрол на друг.
- Методи: First Come First Serve, Priority, Shorted Job First
- Предимства на non-preemptive scheduling: нисък overhead, по-малко ресурси, по-лесна за доказване коректност
- Недостатъци: Ограничена функционалност
Алгоритмичен дизайн
Алгоритмичен дизайн
- Алгоритмите се разделят между аналоговата, цифровата и софтуерната част при дизайна
Алгоритмичен дизайн
Алгоритмите се разделят между аналоговата, цифровата и софтуерната част при дизайна
На софтуерната част винаги се пада честта да коригира грешките на първите две, както и определена контролна част
Алгоритмичен дизайн
Алгоритмите се разделят между аналоговата, цифровата и софтуерната част при дизайна
На софтуерната част винаги се пада честта да коригира грешките на първите две, както и определена контролна част
Често се предвижда и fallback сценарий, където софтуера изключва/избягва/имплементира определена функционалност
Rust в embedded
Rust в embedded
- Това което ще се опитаме да покажем е какви предимства дава Rust пред C/C++
(тоест higher-level concepts и safety guarantees)
Rust в embedded
Това което ще се опитаме да покажем е какви предимства дава Rust пред C/C++
(тоест higher-level concepts и safety guarantees)Documentation and links:
Embedded Rust
Awesome Embedded Rust
Embedonomicon
Ferrous Systems GmbH
Some comments on tools
Some comments on tools
Компилатора използва LLVM
Some comments on tools
Компилатора използва LLVM
(Дис)асемблер: cargo objdump --bin app ...
Необходимо е да сме инсталирали:
cargo install cargo-binutils
rustup component add llvm-tools-preview
Some comments on tools
Компилатора използва LLVM
(Дис)асемблер: cargo objdump --bin app ...
Необходимо е да сме инсталирали:
cargo install cargo-binutils
rustup component add llvm-tools-preview
Емулатор (QEMU): for Cortex-M3
qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb ... -kernel hello_world
Emulator crates
Some comments on tools
Компилатора използва LLVM
(Дис)асемблер: cargo objdump --bin app ...
Необходимо е да сме инсталирали:
cargo install cargo-binutils
rustup component add llvm-tools-preview
Емулатор (QEMU): for Cortex-M3
qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb ... -kernel hello_world
Emulator crates
OpenOCD е програма на host-a и превежда от GDB TCP/IP remote debug protocol и USB протокола. Допълнително
комуникира с memory-mapped registers за четене/писане и спиране на CPU-то от debug event.
Environment
Environment
Environment
Supported platforms
A no_std Rust Environment
Environment
Supported platforms
A no_std Rust Environment
- Hosted Environment
- Bare Metal Environment
#![no_std]
Environment
Supported platforms
A no_std Rust Environment
- Hosted Environment
- Bare Metal Environment
#![no_std]
- При no_std липсват multitasking primitives и не само …
Environment
Supported platforms
A no_std Rust Environment
- Hosted Environment
- Bare Metal Environment
#![no_std]
- При no_std липсват multitasking primitives и не само …
- Липсва динамична памет. Някои заместители на стандартните структури има в heapless пакета.
#![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
Hands on
Installation on Ubuntu and installation on other platforms
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
Installation on Ubuntu and installation on other platforms
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
Installation on Ubuntu and installation on other platforms
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
Installation on Ubuntu and installation on other platforms
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
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
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
sudo udevadm control –reload
sudo udevadm trigger
Memory
Memory and all limitations are described in *.x
files. Example memory.x
:
MEMORY
{
FLASH : ORIGIN = 0x00000000, LENGTH = 64K
RAM : ORIGIN = 0x10000000, LENGTH = 16K
}
Code:
Code:
#![no_main]
#![no_std]
extern crate panic_halt;
use lpc8xx_hal::{cortex_m_rt::entry, CorePeripherals, delay::Delay};
use lpc8xx_hal::embedded_hal::blocking::delay::DelayMs;
Защо трябва да се инсталира специален panic handler с panic_halt
? Стандартната паника печата неща на екрана -- на платката, която ползвате, сигурно няма екран, или ако има, не е ясно какво значи "печатане".
#[entry]
fn main() -> ! {
let p = lpc8xx_hal::Peripherals::take().unwrap();
let cp = CorePeripherals::take().unwrap();
let mut syscon = p.SYSCON.split();
let gpio = p.GPIO.enable(&mut syscon.handle);
let mut led = p.pins.pio1_1.into_output_pin(gpio.tokens.pio1_1,
lpc8xx_hal::gpio::Level::High,);
let mut delay = Delay::new(cp.SYST);
loop {
delay.delay_ms(2_000u32);
led.set_high();
delay.delay_ms(2_000u32);
led.set_low();
}
}
#[entry]
fn main() -> ! {
let p = lpc8xx_hal::Peripherals::take().unwrap();
let cp = CorePeripherals::take().unwrap();
let mut syscon = p.SYSCON.split();
let gpio = p.GPIO.enable(&mut syscon.handle);
let mut led = p.pins.pio1_1.into_output_pin(gpio.tokens.pio1_1,
lpc8xx_hal::gpio::Level::High,);
let mut delay = Delay::new(cp.SYST);
loop {
delay.delay_ms(2_000u32);
led.set_high();
delay.delay_ms(2_000u32);
led.set_low();
}
}
cargo flash --chip=LPC845M301JBD48
Few words on panicking
Few words on panicking
panic-abort
: A panic causes the abort instruction to be executed.panic-halt
: A panic causes the program, or the current thread, to halt by entering an infinite loop.panic-itm
: The panicking message is logged using the ITM, an ARM Cortex-M specific peripheral.panic-semihosting
: The panicking message is logged to the host using the semihosting technique.
Процес на develop-ване за embedded
Процес на develop-ване за embedded
Process: Power up the GPIO Peripherals, configure pin as output, set output to high/low
unsafe {
*((GPIOC_START + CHR_OFFSET) as *mut u32) = (OUTPUT_MODE << 20) | (PUSH_PULL << 22);
}
Процес на develop-ване за embedded
Process: Power up the GPIO Peripherals, configure pin as output, set output to high/low
unsafe {
*((GPIOC_START + CHR_OFFSET) as *mut u32) = (OUTPUT_MODE << 20) | (PUSH_PULL << 22);
}
svd files -> svd2rust generates rust crates => PAC(Peripherial Access Crates)
dp.GPIOC.crh.modify(|_r, w| {
w.mode13().output().cnf13().push_pull()
});
dp.GPIOC.odr.modify(|_r, w| {
w.odr13().high()
});
Процес на develop-ване за embedded
Process: Power up the GPIO Peripherals, configure pin as output, set output to high/low
unsafe {
*((GPIOC_START + CHR_OFFSET) as *mut u32) = (OUTPUT_MODE << 20) | (PUSH_PULL << 22);
}
svd files -> svd2rust generates rust crates => PAC(Peripherial Access Crates)
dp.GPIOC.crh.modify(|_r, w| {
w.mode13().output().cnf13().push_pull()
});
dp.GPIOC.odr.modify(|_r, w| {
w.odr13().high()
});
Zero cost abstraction (in release mode), mostly safe
Процес на develop-ване за embedded
Process: Power up the GPIO Peripherals, configure pin as output, set output to high/low
unsafe {
*((GPIOC_START + CHR_OFFSET) as *mut u32) = (OUTPUT_MODE << 20) | (PUSH_PULL << 22);
}
svd files -> svd2rust generates rust crates => PAC(Peripherial Access Crates)
dp.GPIOC.crh.modify(|_r, w| {
w.mode13().output().cnf13().push_pull()
});
dp.GPIOC.odr.modify(|_r, w| {
w.odr13().high()
});
Zero cost abstraction (in release mode), mostly safe
No check for peripheral dependencies and correct initialization
Процес на develop-ване за embedded
Process: Power up the GPIO Peripherals, configure pin as output, set output to high/low
unsafe {
*((GPIOC_START + CHR_OFFSET) as *mut u32) = (OUTPUT_MODE << 20) | (PUSH_PULL << 22);
}
svd files -> svd2rust generates rust crates => PAC(Peripherial Access Crates)
dp.GPIOC.crh.modify(|_r, w| {
w.mode13().output().cnf13().push_pull()
});
dp.GPIOC.odr.modify(|_r, w| {
w.odr13().high()
});
Zero cost abstraction (in release mode), mostly safe
No check for peripheral dependencies and correct initialization
HALs - higher level interface around PAC
Embedded-hal, BSP, Crates
Rust has a common set of traits for building hardware abstraction layers: the embedded-hal crate. Includes GPIO,
timers, I2C, UART, etc…
Embedded-hal, BSP, Crates
Rust has a common set of traits for building hardware abstraction layers: the embedded-hal crate. Includes GPIO,
timers, I2C, UART, etc…
BSC: Board Support Crates
Embedded-hal, BSP, Crates
Rust has a common set of traits for building hardware abstraction layers: the embedded-hal crate. Includes GPIO,
timers, I2C, UART, etc…
BSC: Board Support Crates
RTIC: Real Time Interrupt Driven Concurrency (previoiusly known as RTFM)
Embedded-hal, BSP, Crates
Rust has a common set of traits for building hardware abstraction layers: the embedded-hal crate. Includes GPIO,
timers, I2C, UART, etc…
BSC: Board Support Crates
RTIC: Real Time Interrupt Driven Concurrency (previoiusly known as RTFM)
cortex-x crates: core peripherals, minimal runtime, debugging
Embedded-hal, BSP, Crates
Rust has a common set of traits for building hardware abstraction layers: the embedded-hal crate. Includes GPIO,
timers, I2C, UART, etc…
BSC: Board Support Crates
RTIC: Real Time Interrupt Driven Concurrency (previoiusly known as RTFM)
cortex-x crates: core peripherals, minimal runtime, debugging
Concurrency
Concurrency
- често се налага да дефинираме
static mut
, опирациите към него саunsafe
.
Concurrency
- често се налага да дефинираме
static mut
, опирациите към него саunsafe
. - възможни подходи: забрана на прекъсвания при работа с такава променлива или използване на
atomics
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
Ползи от Rust
Ползи от Rust
- Изграждане на системи от embedded до cloud на един език
Ползи от Rust
- Изграждане на системи от embedded до cloud на един език
- Safety (typesafe, strong types, correct composition)
Ползи от Rust
- Изграждане на системи от embedded до cloud на един език
- Safety (typesafe, strong types, correct composition)
- Peripherals as state machine
Ползи от Rust
- Изграждане на системи от embedded до cloud на един език
- Safety (typesafe, strong types, correct composition)
- Peripherals as state machine
- Design contracts
Ползи от Rust
- Изграждане на системи от embedded до cloud на един език
- Safety (typesafe, strong types, correct composition)
- Peripherals as state machine
- Design contracts
- Zero cost abstraction
Ползи от Rust
- Изграждане на системи от embedded до cloud на един език
- Safety (typesafe, strong types, correct composition)
- Peripherals as state machine
- Design contracts
- Zero cost abstraction
- Async/Await
Ползи от Rust
- Изграждане на системи от embedded до cloud на един език
- Safety (typesafe, strong types, correct composition)
- Peripherals as state machine
- Design contracts
- Zero cost abstraction
- Async/Await
- Cargo could be universal for different targets
Ползи от Rust
- Изграждане на системи от embedded до cloud на един език
- Safety (typesafe, strong types, correct composition)
- Peripherals as state machine
- Design contracts
- Zero cost abstraction
- Async/Await
- Cargo could be universal for different targets
- Много analyzer-и на C/C++ струват доста скъпо за да се постигне сравнимо качество