aboutsummaryrefslogtreecommitdiff
path: root/book/en/src/internals/interrupt-configuration.md
diff options
context:
space:
mode:
Diffstat (limited to 'book/en/src/internals/interrupt-configuration.md')
-rw-r--r--book/en/src/internals/interrupt-configuration.md73
1 files changed, 73 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 00000000..7aec9c9f
--- /dev/null
+++ b/book/en/src/internals/interrupt-configuration.md
@@ -0,0 +1,73 @@
+# Interrupt configuration
+
+Interrupts are core to the operation of RTIC applications. Correctly setting
+interrupt priorities and ensuring they remain fixed at runtime is a requisite
+for the memory safety of the application.
+
+The RTIC 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 RTIC framework runs:
+
+``` rust
+#[rtic::app(device = lm3s6965)]
+mod 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 {
+ use lm3s6965::NVIC_PRIO_BITS;
+
+ // 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(/* .. */)
+}
+```