mirror of
https://github.com/ferrous-systems/embedded-trainings-2020.git
synced 2024-09-27 14:00:04 +00:00
Renamed a file and removed a topic
This commit is contained in:
parent
4ffeb468df
commit
b6aaf36f30
3 changed files with 98 additions and 100 deletions
|
@ -4,7 +4,6 @@
|
||||||
- [The Peripheral Access Crate](./the_pac.md)
|
- [The Peripheral Access Crate](./the_pac.md)
|
||||||
- [The Hardware Abstraction Layer](./the_hal.md)
|
- [The Hardware Abstraction Layer](./the_hal.md)
|
||||||
- [Building Common Abstractions](./building_common_abstractions.md)
|
- [Building Common Abstractions](./building_common_abstractions.md)
|
||||||
- [Creating Portable Drivers](./creating_portable_drivers.md)
|
|
||||||
- [Supporting your particular board](./supporting_your_particular_board.md)
|
- [Supporting your particular board](./supporting_your_particular_board.md)
|
||||||
- [Writing an Application](./writing_an_application.md)
|
- [Writing an Application](./writing_an_application.md)
|
||||||
|
|
||||||
|
|
|
@ -1 +1,99 @@
|
||||||
# Building Common Abstractions
|
# 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<usize, Error>;
|
||||||
|
fn write(&mut self, buffer: &[u8]) -> Result<usize, Error>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## My Library...
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct AtCommandParser<T> {
|
||||||
|
uart: T,
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> AtCommandParser<T> where T: GenericSerial {
|
||||||
|
fn new(uart: T) -> AtCommandParser<T> { ... }
|
||||||
|
fn get_command(&mut self) -> Result<Option<AtCommand>, 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
|
||||||
|
|
|
@ -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<usize, Error>;
|
|
||||||
fn write(&mut self, buffer: &[u8]) -> Result<usize, Error>;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## My Library...
|
|
||||||
|
|
||||||
```rust
|
|
||||||
struct AtCommandParser<T> {
|
|
||||||
uart: T,
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> AtCommandParser<T> where T: GenericSerial {
|
|
||||||
fn new(uart: T) -> AtCommandParser<T> { ... }
|
|
||||||
fn get_command(&mut self) -> Result<Option<AtCommand>, 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
|
|
Loading…
Reference in a new issue