Skip to content

Commit d5c07e9

Browse files
committed
peripherals as scoped singletons
1 parent 47f4ee0 commit d5c07e9

File tree

1 file changed

+57
-45
lines changed

1 file changed

+57
-45
lines changed

src/generate.rs

Lines changed: 57 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub fn device(d: &Device, target: &Target, items: &mut Vec<Tokens>) -> Result<()
3838

3939
items.push(quote! {
4040
#![doc = #doc]
41+
#![allow(private_no_mangle_statics)]
4142
#![deny(missing_docs)]
4243
#![deny(warnings)]
4344
#![allow(non_camel_case_types)]
@@ -69,8 +70,7 @@ pub fn device(d: &Device, target: &Target, items: &mut Vec<Tokens>) -> Result<()
6970
extern crate vcell;
7071

7172
use core::ops::Deref;
72-
73-
use bare_metal::Peripheral;
73+
use core::marker::PhantomData;
7474
});
7575

7676
if let Some(cpu) = d.cpu.as_ref() {
@@ -101,18 +101,16 @@ pub fn device(d: &Device, target: &Target, items: &mut Vec<Tokens>) -> Result<()
101101
let mut fields = vec![];
102102
let mut exprs = vec![];
103103
if *target == Target::CortexM {
104+
items.push(quote! {
105+
pub use cortex_m::peripheral::Peripherals as CorePeripherals;
106+
});
107+
104108
for p in CORE_PERIPHERALS {
105109
let id = Ident::new(*p);
106110

107111
items.push(quote! {
108112
pub use cortex_m::peripheral::#id;
109113
});
110-
111-
fields.push(quote! {
112-
#[doc = #p]
113-
pub #id: &'a #id
114-
});
115-
exprs.push(quote!(#id: &*#id.get()));
116114
}
117115
}
118116

@@ -139,21 +137,39 @@ pub fn device(d: &Device, target: &Target, items: &mut Vec<Tokens>) -> Result<()
139137
let id = Ident::new(&*p);
140138
fields.push(quote! {
141139
#[doc = #p]
142-
pub #id: &'a #id
140+
pub #id: #id
143141
});
144-
exprs.push(quote!(#id: &*#id.get()));
142+
exprs.push(quote!(#id: #id { _marker: PhantomData }));
145143
}
146144

147145
items.push(quote! {
146+
#[no_mangle]
147+
static mut PERIPHERALS: bool = false;
148+
148149
/// All the peripherals
149150
#[allow(non_snake_case)]
150-
pub struct Peripherals<'a> {
151+
pub struct Peripherals {
151152
#(#fields,)*
152153
}
153154

154-
impl<'a> Peripherals<'a> {
155-
/// Grants access to all the peripherals
156-
pub unsafe fn all() -> Self {
155+
impl Peripherals {
156+
/// Returns all the peripherals *once*
157+
pub fn all() -> Option<Self> {
158+
cortex_m::interrupt::free(|_| {
159+
if unsafe { PERIPHERALS } {
160+
None
161+
} else {
162+
Some(unsafe { Peripherals::_all() })
163+
}
164+
})
165+
}
166+
167+
#[doc(hidden)]
168+
pub unsafe fn _all() -> Self {
169+
debug_assert!(!PERIPHERALS);
170+
171+
PERIPHERALS = true;
172+
157173
Peripherals {
158174
#(#exprs,)*
159175
}
@@ -421,36 +437,44 @@ pub fn peripheral(
421437
items: &mut Vec<Tokens>,
422438
defaults: &Defaults,
423439
) -> Result<()> {
424-
let name = Ident::new(&*p.name.to_uppercase());
425440
let name_pc = Ident::new(&*p.name.to_sanitized_upper_case());
426441
let address = util::hex(p.base_address);
427442
let description = util::respace(p.description.as_ref().unwrap_or(&p.name));
428443

444+
let name_sc = Ident::new(&*p.name.to_sanitized_snake_case());
445+
let (base, derived) = if let Some(base) = p.derived_from.as_ref() {
446+
// TODO Verify that base exists
447+
// TODO We don't handle inheritance style `derivedFrom`, we should raise
448+
// an error in that case
449+
(Ident::new(&*base.to_sanitized_snake_case()), true)
450+
} else {
451+
(name_sc.clone(), false)
452+
};
453+
429454
items.push(quote! {
430455
#[doc = #description]
431-
pub const #name: Peripheral<#name_pc> =
432-
unsafe { Peripheral::new(#address) };
433-
});
456+
pub struct #name_pc { _marker: PhantomData<*const ()> }
434457

435-
if let Some(base) = p.derived_from.as_ref() {
436-
// TODO Verify that base exists
437-
let base_sc = Ident::new(&*base.to_sanitized_snake_case());
438-
items.push(quote! {
439-
/// Register block
440-
pub struct #name_pc { register_block: #base_sc::RegisterBlock }
458+
unsafe impl Send for #name_pc {}
441459

442-
impl Deref for #name_pc {
443-
type Target = #base_sc::RegisterBlock;
460+
impl #name_pc {
461+
/// Returns a pointer to the register block
462+
pub fn ptr() -> *const #base::RegisterBlock {
463+
#address as *const _
464+
}
465+
}
444466

445-
fn deref(&self) -> &#base_sc::RegisterBlock {
446-
&self.register_block
447-
}
467+
impl Deref for #name_pc {
468+
type Target = #base::RegisterBlock;
469+
470+
fn deref(&self) -> &#base::RegisterBlock {
471+
unsafe { &*#name_pc::ptr() }
448472
}
449-
});
473+
}
474+
});
450475

451-
// TODO We don't handle inheritance style `derivedFrom`, we should raise
452-
// an error in that case
453-
return Ok(());
476+
if derived {
477+
return Ok(())
454478
}
455479

456480
let registers = p.registers.as_ref().map(|x| x.as_ref()).unwrap_or(&[][..]);
@@ -476,7 +500,6 @@ pub fn peripheral(
476500
)?;
477501
}
478502

479-
let name_sc = Ident::new(&*p.name.to_sanitized_snake_case());
480503
let description = util::respace(p.description.as_ref().unwrap_or(&p.name));
481504
items.push(quote! {
482505
#[doc = #description]
@@ -485,17 +508,6 @@ pub fn peripheral(
485508

486509
#(#mod_items)*
487510
}
488-
489-
#[doc = #description]
490-
pub struct #name_pc { register_block: #name_sc::RegisterBlock }
491-
492-
impl Deref for #name_pc {
493-
type Target = #name_sc::RegisterBlock;
494-
495-
fn deref(&self) -> &#name_sc::RegisterBlock {
496-
&self.register_block
497-
}
498-
}
499511
});
500512

501513
Ok(())

0 commit comments

Comments
 (0)