Skip to content

Commit 24b76d5

Browse files
committed
Break a couple more out
1 parent 60b9ed0 commit 24b76d5

File tree

5 files changed

+558
-526
lines changed

5 files changed

+558
-526
lines changed

src/generate/device.rs

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
use quote::{Tokens};
2+
use svd::Device;
3+
use syn::Ident;
4+
5+
use errors::*;
6+
use util::{self, ToSanitizedUpperCase};
7+
use Target;
8+
9+
use generate::{interrupt, peripheral};
10+
11+
/// Whole device generation
12+
pub fn render(d: &Device, target: &Target) -> Result<Vec<Tokens>> {
13+
let mut out = vec![];
14+
15+
let doc = format!(
16+
"Peripheral access API for {0} microcontrollers \
17+
(generated using svd2rust v{1})\n\n\
18+
You can find an overview of the API [here].\n\n\
19+
[here]: https://docs.rs/svd2rust/{1}/svd2rust/#peripheral-api",
20+
d.name.to_uppercase(),
21+
env!("CARGO_PKG_VERSION")
22+
);
23+
24+
if *target == Target::Msp430 {
25+
out.push(quote! {
26+
#![feature(abi_msp430_interrupt)]
27+
});
28+
}
29+
30+
if *target != Target::None {
31+
out.push(quote! {
32+
#![cfg_attr(feature = "rt", feature(global_asm))]
33+
#![cfg_attr(feature = "rt", feature(macro_reexport))]
34+
#![cfg_attr(feature = "rt", feature(used))]
35+
});
36+
}
37+
38+
out.push(quote! {
39+
#![doc = #doc]
40+
#![allow(private_no_mangle_statics)]
41+
#![deny(missing_docs)]
42+
#![deny(warnings)]
43+
#![allow(non_camel_case_types)]
44+
#![feature(const_fn)]
45+
#![no_std]
46+
});
47+
48+
match *target {
49+
Target::CortexM => {
50+
out.push(quote! {
51+
extern crate cortex_m;
52+
#[macro_reexport(default_handler, exception)]
53+
#[cfg(feature = "rt")]
54+
extern crate cortex_m_rt;
55+
});
56+
}
57+
Target::Msp430 => {
58+
out.push(quote! {
59+
extern crate msp430;
60+
#[macro_reexport(default_handler)]
61+
#[cfg(feature = "rt")]
62+
extern crate msp430_rt;
63+
});
64+
}
65+
Target::None => {}
66+
}
67+
68+
out.push(quote! {
69+
extern crate bare_metal;
70+
extern crate vcell;
71+
72+
use core::ops::Deref;
73+
use core::marker::PhantomData;
74+
});
75+
76+
if let Some(cpu) = d.cpu.as_ref() {
77+
let bits = util::unsuffixed(cpu.nvic_priority_bits as u64);
78+
79+
out.push(quote! {
80+
/// Number available in the NVIC for configuring priority
81+
pub const NVIC_PRIO_BITS: u8 = #bits;
82+
});
83+
}
84+
85+
out.extend(interrupt::render(d, target, &d.peripherals)?);
86+
87+
const CORE_PERIPHERALS: &[&str] = &[
88+
"CBP",
89+
"CPUID",
90+
"DCB",
91+
"DWT",
92+
"FPB",
93+
"FPU",
94+
"ITM",
95+
"MPU",
96+
"NVIC",
97+
"SCB",
98+
"SYST",
99+
"TPIU",
100+
];
101+
102+
let mut fields = vec![];
103+
let mut exprs = vec![];
104+
if *target == Target::CortexM {
105+
out.push(quote! {
106+
pub use cortex_m::peripheral::Peripherals as CorePeripherals;
107+
});
108+
109+
// NOTE re-export only core peripherals available on *all* Cortex-M devices
110+
// (if we want to re-export all core peripherals available for the target then we are going
111+
// to need to replicate the `#[cfg]` stuff that cortex-m uses and that would require all
112+
// device crates to define the custom `#[cfg]`s that cortex-m uses in their build.rs ...)
113+
out.push(quote! {
114+
pub use cortex_m::peripheral::CPUID;
115+
pub use cortex_m::peripheral::DCB;
116+
pub use cortex_m::peripheral::DWT;
117+
pub use cortex_m::peripheral::MPU;
118+
pub use cortex_m::peripheral::NVIC;
119+
pub use cortex_m::peripheral::SCB;
120+
pub use cortex_m::peripheral::SYST;
121+
});
122+
}
123+
124+
for p in &d.peripherals {
125+
if *target == Target::CortexM && CORE_PERIPHERALS.contains(&&*p.name.to_uppercase()) {
126+
// Core peripherals are handled above
127+
continue;
128+
}
129+
130+
out.extend(peripheral::render(p, &d.peripherals, &d.defaults)?);
131+
132+
if p.registers
133+
.as_ref()
134+
.map(|v| &v[..])
135+
.unwrap_or(&[])
136+
.is_empty() && p.derived_from.is_none()
137+
{
138+
// No register block will be generated so don't put this peripheral
139+
// in the `Peripherals` struct
140+
continue;
141+
}
142+
143+
let p = p.name.to_sanitized_upper_case();
144+
let id = Ident::new(&*p);
145+
fields.push(quote! {
146+
#[doc = #p]
147+
pub #id: #id
148+
});
149+
exprs.push(quote!(#id: #id { _marker: PhantomData }));
150+
}
151+
152+
let take = match *target {
153+
Target::CortexM => Some(Ident::new("cortex_m")),
154+
Target::Msp430 => Some(Ident::new("msp430")),
155+
Target::None => None,
156+
}.map(|krate| quote! {
157+
/// Returns all the peripherals *once*
158+
#[inline]
159+
pub fn take() -> Option<Self> {
160+
#krate::interrupt::free(|_| {
161+
if unsafe { DEVICE_PERIPHERALS } {
162+
None
163+
} else {
164+
Some(unsafe { Peripherals::steal() })
165+
}
166+
})
167+
}
168+
});
169+
170+
out.push(quote! {
171+
// NOTE `no_mangle` is used here to prevent linking different minor versions of the device
172+
// crate as that would let you `take` the device peripherals more than once (one per minor
173+
// version)
174+
#[no_mangle]
175+
static mut DEVICE_PERIPHERALS: bool = false;
176+
177+
/// All the peripherals
178+
#[allow(non_snake_case)]
179+
pub struct Peripherals {
180+
#(#fields,)*
181+
}
182+
183+
impl Peripherals {
184+
#take
185+
186+
/// Unchecked version of `Peripherals::take`
187+
pub unsafe fn steal() -> Self {
188+
debug_assert!(!DEVICE_PERIPHERALS);
189+
190+
DEVICE_PERIPHERALS = true;
191+
192+
Peripherals {
193+
#(#exprs,)*
194+
}
195+
}
196+
}
197+
});
198+
199+
Ok(out)
200+
}

0 commit comments

Comments
 (0)