aboutsummaryrefslogtreecommitdiff
path: root/book/en/src/internals/access.md
diff options
context:
space:
mode:
Diffstat (limited to 'book/en/src/internals/access.md')
-rw-r--r--book/en/src/internals/access.md158
1 files changed, 158 insertions, 0 deletions
diff --git a/book/en/src/internals/access.md b/book/en/src/internals/access.md
new file mode 100644
index 00000000..3894470c
--- /dev/null
+++ b/book/en/src/internals/access.md
@@ -0,0 +1,158 @@
+# Access control
+
+One of the core foundations of RTIC is access control. Controlling which parts
+of the program can access which static variables is instrumental to enforcing
+memory safety.
+
+Static variables are used to share state between interrupt handlers, or between
+interrupts handlers and the bottom execution context, `main`. In normal Rust
+code it's hard to have fine grained control over which functions can access a
+static variable because static variables can be accessed from any function that
+resides in the same scope in which they are declared. Modules give some control
+over how a static variable can be accessed by they are not flexible enough.
+
+To achieve the fine-grained access control where tasks can only access the
+static variables (resources) that they have specified in their RTIC attribute
+the RTIC framework performs a source code level transformation. This
+transformation consists of placing the resources (static variables) specified by
+the user *inside* a module and the user code *outside* the module.
+This makes it impossible for the user code to refer to these static variables.
+
+Access to the resources is then given to each task using a `Resources` struct
+whose fields correspond to the resources the task has access to. There's one
+such struct per task and the `Resources` struct is initialized with either a
+unique reference (`&mut-`) to the static variables or with a resource proxy (see
+section on [critical sections](critical-sections.html)).
+
+The code below is an example of the kind of source level transformation that
+happens behind the scenes:
+
+``` rust
+#[rtic::app(device = ..)]
+mod app {
+ static mut X: u64: 0;
+ static mut Y: bool: 0;
+
+ #[init(resources = [Y])]
+ fn init(c: init::Context) {
+ // .. user code ..
+ }
+
+ #[interrupt(binds = UART0, resources = [X])]
+ fn foo(c: foo::Context) {
+ // .. user code ..
+ }
+
+ #[interrupt(binds = UART1, resources = [X, Y])]
+ fn bar(c: bar::Context) {
+ // .. user code ..
+ }
+
+ // ..
+}
+```
+
+The framework produces codes like this:
+
+``` rust
+fn init(c: init::Context) {
+ // .. user code ..
+}
+
+fn foo(c: foo::Context) {
+ // .. user code ..
+}
+
+fn bar(c: bar::Context) {
+ // .. user code ..
+}
+
+// Public API
+pub mod init {
+ pub struct Context<'a> {
+ pub resources: Resources<'a>,
+ // ..
+ }
+
+ pub struct Resources<'a> {
+ pub Y: &'a mut bool,
+ }
+}
+
+pub mod foo {
+ pub struct Context<'a> {
+ pub resources: Resources<'a>,
+ // ..
+ }
+
+ pub struct Resources<'a> {
+ pub X: &'a mut u64,
+ }
+}
+
+pub mod bar {
+ pub struct Context<'a> {
+ pub resources: Resources<'a>,
+ // ..
+ }
+
+ pub struct Resources<'a> {
+ pub X: &'a mut u64,
+ pub Y: &'a mut bool,
+ }
+}
+
+/// Implementation details
+mod app {
+ // everything inside this module is hidden from user code
+
+ static mut X: u64 = 0;
+ static mut Y: bool = 0;
+
+ // the real entry point of the program
+ unsafe fn main() -> ! {
+ interrupt::disable();
+
+ // ..
+
+ // call into user code; pass references to the static variables
+ init(init::Context {
+ resources: init::Resources {
+ X: &mut X,
+ },
+ // ..
+ });
+
+ // ..
+
+ interrupt::enable();
+
+ // ..
+ }
+
+ // interrupt handler that `foo` binds to
+ #[no_mangle]
+ unsafe fn UART0() {
+ // call into user code; pass references to the static variables
+ foo(foo::Context {
+ resources: foo::Resources {
+ X: &mut X,
+ },
+ // ..
+ });
+ }
+
+ // interrupt handler that `bar` binds to
+ #[no_mangle]
+ unsafe fn UART1() {
+ // call into user code; pass references to the static variables
+ bar(bar::Context {
+ resources: bar::Resources {
+ X: &mut X,
+ Y: &mut Y,
+ },
+ // ..
+ });
+ }
+}
+```