Skip to content

New static mutable storage for the entry function #616

Description

@jonathanpallant

We carefully ensure the #[entry] function cannot be called other than after a reset (and after the start-up code has initialised everything).

Currently we use this knowledge to 'safely' replace static mut FOO: T = T::new() with code that uses an unsafe block to create &mut T reference to the static, which is passed in as an argument.

That is:

#[cortex_m_rt::entry]
fn main() -> ! {
    static mut FOO: u32 = 123;

    loop {}
}

becomes:

#[doc(hidden)]
#[export_name = "main"]
pub unsafe extern "C" fn __cortex_m_rt_main_trampoline() {
    #[allow(static_mut_refs)]
    __cortex_m_rt_main({
        static mut FOO: u32 = 123;
        unsafe { &mut FOO }
    })
}
fn __cortex_m_rt_main(#[allow(non_snake_case)] FOO: &'static mut u32) -> ! {
    loop {}
}

It is widely accepted that this kind of sleight of hand is not good. However, RTIC shows us a syntax that could work:

#[task(local = [state: u32 = 0])]
async fn foo(c: foo::Context) {
    let old_state: u32 = *c.local.state;
    *c.local.state += 1;
}

So, what if we wrote a new macro, called entry_with_context:

#[cortex_m_rt::entry_with_context(context = [state: u32 = 0])]
fn main(c: main::Context) -> ! {
    let old_state: u32 = *c.state;
    *c.state += 1;

    loop {}
}

The advantage here is that is clear some 'magic' is happening to create a static resource and pass it to the main function.

It would expand to something like:

mod main {
    pub(crate) struct Context {
        state: &mut u32
    }
}

#[doc(hidden)]
#[export_name = "main"]
pub unsafe extern "C" fn __cortex_m_rt_main_trampoline() {
    static STATE: RacyCell<u32> = RacyCell::new(123);
    __cortex_m_rt_main(main::Context {
        state: unsafe { STATE.get_mut_ref() },
    })
}

fn main(c: main::Context) -> ! {
    let old_state: u32 = *c.state;
    *c.state += 1;

    loop {}
}

We don't even need to hide the actual fn main() function anymore, because you cannot call it without creating the context object.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions