add explanations

This commit is contained in:
Mirabellensaft 2023-03-13 17:26:47 +01:00
parent 53a7c72c19
commit bb86aedeaf

View file

@ -7,7 +7,8 @@ In this exercise you will generate a PAC (Peripheral Access Crate) from an svd f
* Two ways to write into a register to enable and disable it
## Prerequisites
[todo!]
* basic use of closures
* read/write/modify api
## Tasks
@ -22,7 +23,7 @@ cargo install svd2rust
✅ Download https://github.com/NordicSemiconductor/nrfx/blob/master/mdk/nrf52.svd (This version has an error: writeonce needs to be changed to writeOnce)
Place the file into `down-the-stack/dk-pac`. Note how we provide a `Cargo.toml` file, as it will not be generated by svd2rust.
✅ In the terminal, go to the file's location. Run svd2rust with the SVD file to generate a PAC using the `cortex-m` flag.
✅ In the terminal, go to the file's location. Run `svd2rust` with the SVD file to generate a PAC using the `cortex-m` flag.
```
svd2rust --target cortex-m -i nrf52.svd
@ -60,41 +61,90 @@ form -i src/lib.rs -o src/
Write a simple program which uses the PAC to enable the UART. See how writing arbitrary values to the ENABLE field in the ENABLE register is unsafe, because only values 0 or 8 should be used.
✅ Finding your way through the docs:
(This better be a lecture)
* In the `Structs` section look for the `struct Peripherals`. Taking ownerhip of it will be the first step later on. Note that only the method `steal()` is documented. It is an unsafe method, and to be avoided. `Peripherals` has a field named `UARTE0`
* In the `modules` section, look for the `uarte0` module. It is divided into submodules. `enable` is important for us. Clicking on it shows the associated type definitions.
* `W` - the register ENABLE writer with the following methods:
* `enable()` returns the field ENABLE writer `ENABLE_W`.
* `unsafe bits()` writes raw bits into the register.
* `R` - the register ENABLE reader writer with the following methods:
* `enable()` returns the field ENABLE reader `ENABLE_R`.
* `bits()` reads raw bits from the register.
The types `ENABLE_R` and `ENABLE_W` have useful methods themselves, check them out.
Usage: if you want to write or read something from the uarte register and you want to avoid dealing with raw bits, you first have to call a method that gives you access to the respective reader or writer, and then call the method that does what you want.
Example:
uarte.enable.read().
Note the difference between the struct field `UARTE0` in `Peripherals` and the module `uarte0`.
✅ Finding your way through the PAC
find the "board" struct in docs und take()
* `dk_pac/src/lib.rs` defines the single peripherals with their register block addresses and contains a struct defintion for the `struct Peripherals`. There are two methods for this struct: `take()` and `steal()`. `take()` assures, that only one instance of this can exist. Hence, it's safe. Note that `take()` is only available with the `critical-section` feature enabled.
take() assures, that only one instance of this can exist. hence, it's safe.
* `dk_pac/src/uarte0.rs` defines a struct that contains all the registers of the `UARTE0` register block. The `enable` field represents the register of the same name.
Find the definition of the ENABLE register for UARTE0, in the PDF datasheet and in the SVD file, and in the svd2rust generated code.
* `dk_pac/src/uarte0/enable.rs` defines the types associated with this register that you already saw in the docs.
✅ uarte0.rs/enable
read().bits
write(closure)
* Find the definition of the ENABLE register for UARTE0, in the PDF datasheet and in the SVD file
*
✅ Import the PAC
cargo.toml
down-the-stack/apps/Cargo.toml
```
dk_pac = { path = "../dk_pac", features = ["critical-section"]}
```
uarte_enable.rs
apps/bin/uarte_enable.rs
```rust
use dk_pac::UARTE0;
```
✅ Take ownership of the peripherals with `take()` and bind the UARTE0 peripheral to it's own variable
✅ Take ownership of the peripherals with `take()` and bind the `UARTE0` peripheral to it's own variable
✅ Write a helper function that prints the status of the uarte peripheral. Check if the enable is not 0
```rust
let periph = dk_pac::Peripherals::take().unwrap();
let uarte = periph.UARTE0;
```
✅ Write a helper function that reads the bits of the enable register. It prints "Uarte0 is enabled", when the value is not 0. If it is 0, it prints "Uarte0 is disabled". Add a function call to `fn main()`
base address Uarte0 0x40002000
enable UARTE 0x500
✅ Enable the peripheral
✅ Disable the peropheral with an unsafe write
Run the code. The terminal output should read: "Uarte0 is disabled".
```rust
fn is_uarte_enabled(uarte: &UARTE0) {
if uarte.enable.read().enable().is_enabled() {
defmt::println!("Uarte0 is enabled");
} else {
defmt::println!("Uarte0 is disabled");
}
}
```
✅ Enable the peripheral safely by passing `w.enable().enabled()` in the closure. Call the helper function after this new line and run your code.
It should print:
"Uarte0 is disabled"
"Uarte0 is ensabled"
```
uarte.enable.write(|w| w.enable().enabled());
```
✅ Disable the peripheral with unsafely by writing raw bits into the register.
```rust
unsafe {
uarte.enable.write(|w| w.bits(0x00 as u32));
}
```