diff options
| author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-05-09 19:33:42 +0000 |
|---|---|---|
| committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-05-09 19:33:42 +0000 |
| commit | 2596ea0e46bec73d090d9e51d41e6c2f481b8e15 (patch) | |
| tree | 9d148e9ef2d922c710a41b991f21d14cb2fe7bc4 /book/en/src/internals/interrupt-configuration.md | |
| parent | bc024f197929be1ce7dac9e6cbf6672c3980437e (diff) | |
| parent | ea02405ef0cea368707b723054b699fa423d4823 (diff) | |
Merge #175
175: document internals r=japaric a=japaric
note that this assumes that RFC #155 has been implemented
[Rendered text](https://japaric.github.io/rtfm5/book/en/internals.html)
Do not merge this before PR #176
Co-authored-by: Jorge Aparicio <jorge@japaric.io>
Diffstat (limited to 'book/en/src/internals/interrupt-configuration.md')
| -rw-r--r-- | book/en/src/internals/interrupt-configuration.md | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/book/en/src/internals/interrupt-configuration.md b/book/en/src/internals/interrupt-configuration.md new file mode 100644 index 0000000..b34b308 --- /dev/null +++ b/book/en/src/internals/interrupt-configuration.md @@ -0,0 +1,74 @@ +# Interrupt configuration + +Interrupts are core to the operation of RTFM applications. Correctly setting +interrupt priorities and ensuring they remain fixed at runtime is a requisite +for the memory safety of the application. + +The RTFM framework exposes interrupt priorities as something that is declared at +compile time. However, this static configuration must be programmed into the +relevant registers during the initialization of the application. The interrupt +configuration is done before the `init` function runs. + +This example gives you an idea of the code that the RTFM framework runs: + +``` rust +#[rtfm::app(device = ..)] +const APP: () = { + #[init] + fn init(c: init::Context) { + // .. user code .. + } + + #[idle] + fn idle(c: idle::Context) -> ! { + // .. user code .. + } + + #[interrupt(binds = UART0, priority = 2)] + fn foo(c: foo::Context) { + // .. user code .. + } +}; +``` + +The framework generates an entry point that looks like this: + +``` rust +// the real entry point of the program +#[no_mangle] +unsafe fn main() -> ! { + // transforms a logical priority into a hardware / NVIC priority + fn logical2hw(priority: u8) -> u8 { + // this value comes from the device crate + const NVIC_PRIO_BITS: u8 = ..; + + // the NVIC encodes priority in the higher bits of a bit + // also a bigger numbers means lower priority + ((1 << NVIC_PRIORITY_BITS) - priority) << (8 - NVIC_PRIO_BITS) + } + + cortex_m::interrupt::disable(); + + let mut core = cortex_m::Peripheral::steal(); + + core.NVIC.enable(Interrupt::UART0); + + // value specified by the user + let uart0_prio = 2; + + // check at compile time that the specified priority is within the supported range + let _ = [(); (1 << NVIC_PRIORITY_BITS) - (uart0_prio as usize)]; + + core.NVIC.set_priority(Interrupt::UART0, logical2hw(uart0_prio)); + + // call into user code + init(/* .. */); + + // .. + + cortex_m::interrupt::enable(); + + // call into user code + idle(/* .. */) +} +``` |
