From b6aaf36f30bd9b49a597feadc3b550e118a6074c Mon Sep 17 00:00:00 2001 From: "Jonathan Pallant (Ferrous Systems)" Date: Thu, 23 Mar 2023 09:20:02 +0000 Subject: [PATCH] Renamed a file and removed a topic --- down-the-stack-book/src/SUMMARY.md | 1 - .../src/building_common_abstractions.md | 98 ++++++++++++++++++ .../src/creating_portable_drivers.md | 99 ------------------- 3 files changed, 98 insertions(+), 100 deletions(-) delete mode 100644 down-the-stack-book/src/creating_portable_drivers.md diff --git a/down-the-stack-book/src/SUMMARY.md b/down-the-stack-book/src/SUMMARY.md index 968e927..8d155ae 100644 --- a/down-the-stack-book/src/SUMMARY.md +++ b/down-the-stack-book/src/SUMMARY.md @@ -4,7 +4,6 @@ - [The Peripheral Access Crate](./the_pac.md) - [The Hardware Abstraction Layer](./the_hal.md) - [Building Common Abstractions](./building_common_abstractions.md) -- [Creating Portable Drivers](./creating_portable_drivers.md) - [Supporting your particular board](./supporting_your_particular_board.md) - [Writing an Application](./writing_an_application.md) diff --git a/down-the-stack-book/src/building_common_abstractions.md b/down-the-stack-book/src/building_common_abstractions.md index 737b8a2..0b76033 100644 --- a/down-the-stack-book/src/building_common_abstractions.md +++ b/down-the-stack-book/src/building_common_abstractions.md @@ -1 +1,99 @@ # Building Common Abstractions + +--- + +## These things are different + +* STM32F030 UART Driver +* nRF52840 UART Driver +* But I want to write a library which is generic! + * e.g. an AT Command Parser + +--- + +## How does Rust allow generic behaviour? + +* Generics! +* `where T: SomeTrait` + +--- + +## Traits + +```rust +trait GenericSerial { + type Error; + fn read(&mut self, buffer: &mut [u8]) -> Result; + fn write(&mut self, buffer: &[u8]) -> Result; +} +``` + +--- + +## My Library... + +```rust +struct AtCommandParser { + uart: T, + ... +} + +impl AtCommandParser where T: GenericSerial { + fn new(uart: T) -> AtCommandParser { ... } + fn get_command(&mut self) -> Result, Error> { ... } +} +``` + +Note how `AtCommandParser` *owns* the object which meets the `GenericSerial` trait. + +--- + +## My Application + +```rust +let uart = stm32_hal::Uart::new(...); +let at_parser = at_library::AtCommandParser::new(uart); +while let Some(cmd) = at_parser.get_command().unwrap() { + ... +} +``` + +--- + +## My Application (2) + +```rust +let uart = nrf52_hal::Uart::new(...); +let at_parser = at_library::AtCommandParser::new(uart); +while let Some(cmd) = at_parser.get_command().unwrap() { + ... +} +``` + +--- + +## How do we agree on the traits? + +* The Rust Embedded Working Group has developed some traits +* They are called the *Embedded HAL* +* See https://docs.rs/embedded-hal/ +* All HAL implementations should implement these traits + +--- + +## Blocking vs Non-blocking + +* Should a trait API stall your CPU until the data is ready? +* Or should it return early, saying "not yet ready" + * So you can go an do something else in the mean time? + * Or sleep? +* `embedded_hal::blocking::serial::Write`, vs +* `embedded_hal::serial::Write` + +--- + +## Trade-offs + +* Some MCUs have more features than others +* The trait design has an inherent trade-off + * Flexibility/Performance vs Portability diff --git a/down-the-stack-book/src/creating_portable_drivers.md b/down-the-stack-book/src/creating_portable_drivers.md deleted file mode 100644 index 08ef839..0000000 --- a/down-the-stack-book/src/creating_portable_drivers.md +++ /dev/null @@ -1,99 +0,0 @@ -# Creating Portable Drivers - ---- - -## These things are different - -* STM32F030 UART Driver -* nRF52840 UART Driver -* But I want to write a library which is generic! - * e.g. an AT Command Parser - ---- - -## How does Rust allow generic behaviour? - -* Generics! -* `where T: SomeTrait` - ---- - -## Traits - -```rust -trait GenericSerial { - type Error; - fn read(&mut self, buffer: &mut [u8]) -> Result; - fn write(&mut self, buffer: &[u8]) -> Result; -} -``` - ---- - -## My Library... - -```rust -struct AtCommandParser { - uart: T, - ... -} - -impl AtCommandParser where T: GenericSerial { - fn new(uart: T) -> AtCommandParser { ... } - fn get_command(&mut self) -> Result, Error> { ... } -} -``` - -Note how `AtCommandParser` *owns* the object which meets the `GenericSerial` trait. - ---- - -## My Application - -```rust -let uart = stm32_hal::Uart::new(...); -let at_parser = at_library::AtCommandParser::new(uart); -while let Some(cmd) = at_parser.get_command().unwrap() { - ... -} -``` - ---- - -## My Application (2) - -```rust -let uart = nrf52_hal::Uart::new(...); -let at_parser = at_library::AtCommandParser::new(uart); -while let Some(cmd) = at_parser.get_command().unwrap() { - ... -} -``` - ---- - -## How do we agree on the traits? - -* The Rust Embedded Working Group has developed some traits -* They are called the *Embedded HAL* -* See https://docs.rs/embedded-hal/ -* All HAL implementations should implement these traits - ---- - -## Blocking vs Non-blocking - -* Should a trait API stall your CPU until the data is ready? -* Or should it return early, saying "not yet ready" - * So you can go an do something else in the mean time? - * Or sleep? -* `embedded_hal::blocking::serial::Write`, vs -* `embedded_hal::serial::Write` - ---- - -## Trade-offs - -* Some MCUs have more features than others -* The trait design has an inherent trade-off - * Flexibility/Performance vs Portability