diff --git a/README.md b/README.md index bbe8d24fd6ef386cb72e54c58dc69748d987e62f..9644279ac8d7d1720a26122dd102466272ca5378 100644 --- a/README.md +++ b/README.md @@ -311,6 +311,70 @@ the `read` is a method on the `rx`, --- +### RTFM Blinky + +No example suit is complete without the mandatory `blinky` demo, so here we go! The exampe `rtfm_blinky.rs` showcase the simplicity of using the RTFM framework. + +An application using RTFM is defined using the `app` attribute, specifying the target PAC. + +- The `static mut` section defines the shared resources. In this example we need to access the `GPIOA` in the `SysTick` exception handler. Initially all resources are delegated to the `init` task (running before the system goes live). + +- In `init` we: + - configure the `SysTick` exception/task to be triggered periodically (each second),- configure the `RCC` (enabling the `GPIOA` peripheral), + - configure the `PA5` pin (connected to the Green LED on the Nucleo) as an output, and finally + - delegate access to `GPIO` as a "late" resource. + +- The `#[exception (resources = [GPIOA])]` attribute enables access to the `GPIOA` peripheral for the `SysTick` exception/task. (Resource access goes through `resources.<RESOURCE>`.) + +- In `SysTick` we define a task local resource `TOGGLE` to hold the current state, and we set/clear the `PA5` pin correspondingly. (The `bs5` field sets the `PA5` high, while `br5` clears the corresponding bit controlling the led.) Finnally the `TOGGLE` state is inverted. + +Notice here, under the hood the RTFM framework analyses the `app` and concludes that `TOGGLE` and `GPIOA` are accessible (in scope) for `SysTick` exclusively, so we safely (without running any risk of race conditions) access the resources directly. + +Side note: Accessing a resource shared with a higher priority task, requires the user to lock the resource in order to guarantee race-free access. For further information, see the RTFM API documentation and book, cf. `cortex-m-rtfm`. + +``` rust +use rtfm::app; + +#[app(device = stm32f4::stm32f413)] +const APP: () = { + // late resorce binding + static mut GPIOA: GPIOA = (); + + // init runs in an interrupt free section + #[init] + fn init() { + // configures the system timer to trigger a SysTick exception every second + core.SYST.set_clock_source(SystClkSource::Core); + core.SYST.set_reload(16_000_000); // period = 1s + core.SYST.enable_counter(); + core.SYST.enable_interrupt(); + + // power on GPIOA, RM0368 6.3.11 + device.RCC.ahb1enr.modify(|_, w| w.gpioaen().set_bit()); + // configure PA5 as output, RM0368 8.4.1 + device.GPIOA.moder.modify(|_, w| w.moder5().bits(1)); + + // pass on late resources + GPIOA = device.GPIOA; + } + + #[exception (resources = [GPIOA])] + fn SysTick() { + static mut TOGGLE: bool = false; + + if *TOGGLE { + resources.GPIOA.bsrr.write(|w| w.bs5().set_bit()); + } else { + resources.GPIOA.bsrr.write(|w| w.br5().set_bit()); + } + + *TOGGLE = !*TOGGLE; + } +}; +``` + + + # Trouble Shooting Working with embedded targets involves a lot of tooling, and many things can go wrong.