aboutsummaryrefslogtreecommitdiff
path: root/book/en/src/internals/interrupt-configuration.md
diff options
context:
space:
mode:
authorJorge Aparicio <jorge@japaric.io>2019-04-21 20:45:24 +0200
committerJorge Aparicio <jorge@japaric.io>2019-05-01 22:36:54 +0200
commit09ec5a7a41d951ad7a1ef61391896df4a1f5fc18 (patch)
tree0ab3172a9f2fd42d7236b4e989726ce312e363ce /book/en/src/internals/interrupt-configuration.md
parentbc024f197929be1ce7dac9e6cbf6672c3980437e (diff)
document internals
note that this assumes that RFC #155 has been implemented
Diffstat (limited to 'book/en/src/internals/interrupt-configuration.md')
-rw-r--r--book/en/src/internals/interrupt-configuration.md74
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(/* .. */)
+}
+```