# Late resources Some resources are initialized at runtime after the `init` function returns. It's important that these resources (static variables) are fully initialized before tasks are allowed to run, that is they must be initialized while interrupts are disabled. The example below shows the kind of code that the framework generates to initialize late resources. ``` rust #[rtic::app(device = ..)] mod app { struct Resources { x: Thing, } #[init] fn init() -> init::LateResources { // .. init::LateResources { x: Thing::new(..), } } #[task(binds = UART0, resources = [x])] fn foo(c: foo::Context) { let x: &mut Thing = c.resources.x; x.frob(); // .. } // .. } ``` The code generated by the framework looks like this: ``` rust fn init(c: init::Context) -> init::LateResources { // .. user code .. } fn foo(c: foo::Context) { // .. user code .. } // Public API pub mod init { pub struct LateResources { pub x: Thing, } // .. } pub mod foo { pub struct Resources<'a> { pub x: &'a mut Thing, } pub struct Context<'a> { pub resources: Resources<'a>, // .. } } /// Implementation details mod app { // uninitialized static static mut x: MaybeUninit = MaybeUninit::uninit(); #[no_mangle] unsafe fn main() -> ! { cortex_m::interrupt::disable(); // .. let late = init(..); // initialization of late resources x.as_mut_ptr().write(late.x); cortex_m::interrupt::enable(); //~ compiler fence // exceptions, interrupts and tasks can preempt `main` at this point idle(..) } #[no_mangle] unsafe fn UART0() { foo(foo::Context { resources: foo::Resources { // `x` has been initialized at this point x: &mut *x.as_mut_ptr(), }, // .. }) } } ``` An important detail here is that `interrupt::enable` behaves like a *compiler fence*, which prevents the compiler from reordering the write to `X` to *after* `interrupt::enable`. If the compiler were to do that kind of reordering there would be a data race between that write and whatever operation `foo` performs on `X`. Architectures with more complex instruction pipelines may need a memory barrier (`atomic::fence`) instead of a compiler fence to fully flush the write operation before interrupts are re-enabled. The ARM Cortex-M architecture doesn't need a memory barrier in single-core context.