mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-12-01 16:04:33 +01:00
goodby static mut, welcome back to UnsafeCell
This commit is contained in:
parent
3c86d713a6
commit
db1574bf6b
5 changed files with 108 additions and 12 deletions
25
examples/minimal_early_resource.rs
Normal file
25
examples/minimal_early_resource.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
//! examples/idle.rs
|
||||||
|
|
||||||
|
#![deny(unsafe_code)]
|
||||||
|
#![deny(warnings)]
|
||||||
|
#![no_main]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
use panic_semihosting as _;
|
||||||
|
|
||||||
|
#[rtic::app(device = lm3s6965)]
|
||||||
|
mod app {
|
||||||
|
|
||||||
|
#[resources]
|
||||||
|
struct Resources {
|
||||||
|
#[init(0)]
|
||||||
|
resource_x: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[idle(resources = [resource_x])]
|
||||||
|
fn idle(_: idle::Context) -> ! {
|
||||||
|
loop {
|
||||||
|
cortex_m::asm::nop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
examples/minimal_late_resource.rs
Normal file
29
examples/minimal_late_resource.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
//! examples/minimal_late_resource.rs
|
||||||
|
|
||||||
|
#![deny(unsafe_code)]
|
||||||
|
#![deny(warnings)]
|
||||||
|
#![no_main]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
use panic_semihosting as _;
|
||||||
|
|
||||||
|
#[rtic::app(device = lm3s6965)]
|
||||||
|
mod app {
|
||||||
|
|
||||||
|
#[resources]
|
||||||
|
struct Resources {
|
||||||
|
resource_x: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[init]
|
||||||
|
fn init(_: init::Context) -> (init::LateResources, init::Monotonics) {
|
||||||
|
(init::LateResources { resource_x: 0 }, init::Monotonics {})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[idle(resources = [resource_x])]
|
||||||
|
fn idle(_: idle::Context) -> ! {
|
||||||
|
loop {
|
||||||
|
cortex_m::asm::nop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,10 +17,14 @@ pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> {
|
||||||
// If it's live
|
// If it's live
|
||||||
let cfgs = app.late_resources[name].cfgs.clone();
|
let cfgs = app.late_resources[name].cfgs.clone();
|
||||||
if analysis.locations.get(name).is_some() {
|
if analysis.locations.get(name).is_some() {
|
||||||
// Need to also include the cfgs
|
|
||||||
stmts.push(quote!(
|
stmts.push(quote!(
|
||||||
#(#cfgs)*
|
// We include the cfgs
|
||||||
#mangled_name.as_mut_ptr().write(late.#name);
|
#(#cfgs)*
|
||||||
|
// Late resource is a RacyCell<MaybeUninit<T>>
|
||||||
|
// - `get_mut_unchecked` to obtain `MaybeUninit<T>`
|
||||||
|
// - `as_mut_ptr` to obtain a raw pointer to `MaybeUninit<T>`
|
||||||
|
// - `write` the defined value for the late resource T
|
||||||
|
#mangled_name.get_mut_unchecked().as_mut_ptr().write(late.#name);
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,20 @@ use rtic_syntax::{analyze::Ownership, ast::App};
|
||||||
|
|
||||||
use crate::{analyze::Analysis, check::Extra, codegen::util};
|
use crate::{analyze::Analysis, check::Extra, codegen::util};
|
||||||
|
|
||||||
/// Generates `static [mut]` variables and resource proxies
|
/// Generates `static` variables and resource proxies
|
||||||
|
/// Early resources are stored in `RacyCell<T>`
|
||||||
|
/// Late resource are stored in `RacyCell<MaybeUninit<T>>`
|
||||||
|
///
|
||||||
|
/// Safety:
|
||||||
|
/// - RacyCell<T> access is `unsafe`.
|
||||||
|
/// - RacyCell<MaybeUninit> is always written to before user access, thus
|
||||||
|
// the generated code for user access can safely `assume_init`.
|
||||||
pub fn codegen(
|
pub fn codegen(
|
||||||
app: &App,
|
app: &App,
|
||||||
analysis: &Analysis,
|
analysis: &Analysis,
|
||||||
extra: &Extra,
|
extra: &Extra,
|
||||||
) -> (
|
) -> (
|
||||||
// mod_app -- the `static [mut]` variables behind the proxies
|
// mod_app -- the `static` variables behind the proxies
|
||||||
Vec<TokenStream2>,
|
Vec<TokenStream2>,
|
||||||
// mod_resources -- the `resources` module
|
// mod_resources -- the `resources` module
|
||||||
TokenStream2,
|
TokenStream2,
|
||||||
|
@ -24,18 +31,26 @@ pub fn codegen(
|
||||||
let mangled_name = util::mark_internal_ident(&name);
|
let mangled_name = util::mark_internal_ident(&name);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
// TODO: do we really need this in the single core case
|
||||||
|
// late resources in `util::link_section_uninit`
|
||||||
let section = if expr.is_none() {
|
let section = if expr.is_none() {
|
||||||
util::link_section_uninit(true)
|
util::link_section_uninit(true)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// resource type and assigned value
|
||||||
let (ty, expr) = if let Some(expr) = expr {
|
let (ty, expr) = if let Some(expr) = expr {
|
||||||
(quote!(#ty), quote!(#expr))
|
// early resource
|
||||||
} else {
|
|
||||||
(
|
(
|
||||||
quote!(core::mem::MaybeUninit<#ty>),
|
quote!(rtic::RacyCell<#ty>),
|
||||||
quote!(core::mem::MaybeUninit::uninit()),
|
quote!(rtic::RacyCell::new(#expr)),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// late resource
|
||||||
|
(
|
||||||
|
quote!(rtic::RacyCell<core::mem::MaybeUninit<#ty>>),
|
||||||
|
quote!(rtic::RacyCell::new(core::mem::MaybeUninit::uninit())),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -46,7 +61,7 @@ pub fn codegen(
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
#section
|
#section
|
||||||
static mut #mangled_name: #ty = #expr;
|
static #mangled_name: #ty = #expr;
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,14 +89,16 @@ pub fn codegen(
|
||||||
));
|
));
|
||||||
|
|
||||||
let ptr = if expr.is_none() {
|
let ptr = if expr.is_none() {
|
||||||
|
// late resource
|
||||||
quote!(
|
quote!(
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
#mangled_name.as_mut_ptr()
|
&mut #mangled_name.get_mut_unchecked().assume_init()
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
// early resource
|
||||||
quote!(
|
quote!(
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
&mut #mangled_name
|
unsafe { #mangled_name.get_mut_unchecked() }
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
21
src/lib.rs
21
src/lib.rs
|
@ -55,3 +55,24 @@ where
|
||||||
{
|
{
|
||||||
NVIC::pend(interrupt)
|
NVIC::pend(interrupt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use core::cell::UnsafeCell;
|
||||||
|
|
||||||
|
/// Internal replacement for `static mut T`
|
||||||
|
// TODO: Decide name and location.
|
||||||
|
pub struct RacyCell<T>(UnsafeCell<T>);
|
||||||
|
|
||||||
|
impl<T> RacyCell<T> {
|
||||||
|
/// Create a RacyCell
|
||||||
|
pub const fn new(value: T) -> Self {
|
||||||
|
RacyCell(UnsafeCell::new(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get &mut T
|
||||||
|
pub unsafe fn get_mut_unchecked(&self) -> &mut T {
|
||||||
|
&mut *self.0.get()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The type wrapped need to be Sync for RacyCell<T> to be Sync
|
||||||
|
unsafe impl<T> Sync for RacyCell<T> where T: Sync {}
|
||||||
|
|
Loading…
Reference in a new issue