mirror of
https://github.com/ferrous-systems/embedded-trainings-2020.git
synced 2024-05-19 00:38:10 +00:00
b7fca7dc70
Co-authored-by: Tanks Transfeld <Mirabellensaft@users.noreply.github.com>
98 lines
2.3 KiB
Markdown
98 lines
2.3 KiB
Markdown
# The Hardware Abstraction Layer
|
|
|
|
---
|
|
|
|
## Building a driver
|
|
|
|
* Writing to all those registers is tedious
|
|
* You have to get the values right, and the order right
|
|
* Can we wrap it up into a nicer, easier-to-use object?
|
|
|
|
---
|
|
|
|
## Typical driver interface
|
|
|
|
```rust
|
|
let p = pac::Peripherals.take().unwrap();
|
|
let mut uarte0 = hal::uarte::Uarte::new(
|
|
// Our singleton representing exclusive access to
|
|
// the peripheral IP block
|
|
p.UARTE0,
|
|
// Some other settings we might need
|
|
115200,
|
|
hal::uarte::Parity::None,
|
|
hal::uarte::Handshaking::None,
|
|
);
|
|
// Using the `uarte0` object:
|
|
uarte0.write_all(b"Hey, I'm using a UART!").unwrap();
|
|
```
|
|
|
|
---
|
|
|
|
## The Hardware Abstraction Layer
|
|
|
|
* Contains all the drivers for a chip
|
|
* Often common/shared across chip families
|
|
* e.g. nRF52 HAL for 52832, 52840, etc
|
|
* Usually community developed
|
|
* Often quite different between MCU vendors
|
|
* Different teams came up with different designs!
|
|
|
|
---
|
|
|
|
## Kinds of driver
|
|
|
|
* PLL / Clock Configuration
|
|
* Reset / Power Control of Peripherals
|
|
* GPIO pins
|
|
* UART
|
|
* SPI
|
|
* I²C
|
|
* ADC
|
|
* Timer/Counters
|
|
* and more!
|
|
|
|
---
|
|
|
|
## Handling GPIO pins with code
|
|
|
|
```rust
|
|
// Get the singletons
|
|
let p = pac::Peripherals.take().unwrap();
|
|
// Make a driver for GPIO port P0
|
|
let pins = hal::gpio::p0::Parts::new(p.P0);
|
|
// Get Pin 13 on port P0 and make it an output
|
|
let mut led_pin = pins.p0_13.into_push_pull_output(Level::High);
|
|
// Now set the output low
|
|
led_pin.set_low();
|
|
```
|
|
|
|
This differs widely across MCUs (ST, Nordic, Espressif, Atmel, etc). Some MCUs (e.g. Nordic) let you put any function on any pin, and some are much more restrictive!
|
|
|
|
---
|
|
|
|
## Correctness by design
|
|
|
|
* HALs want to make it hard to do the wrong thing
|
|
* Is a UART driver of any use, if you haven't configured at least one TX pin and one RX pin?
|
|
* Should the UART driver check you've done that?
|
|
|
|
---
|
|
|
|
## Giving the pins to the driver
|
|
|
|
```rust
|
|
// 'degrade()' converts a P0_08 type into a generic Pin type.
|
|
let pins = hal::uarte::Pins {
|
|
rxd: pins.p0_08.degrade().into_floating_input(),
|
|
txd: pins.p0_06.degrade().into_push_pull_output(Level::High),
|
|
cts: None,
|
|
rts: None,
|
|
};
|
|
|
|
let uarte = hal::uarte::Uarte::new(periph.UARTE1, pins, Parity::EXCLUDED, Baudrate::BAUD115200);
|
|
```
|
|
|
|
This is an example for the nRF52. We'll use it later in the example.
|
|
|