Skip to content

Commit 231d24e

Browse files
authored
Merge pull request #180 from jamesmunns/reorg
Reorganize svd2rust
2 parents 65482c2 + ed5f17e commit 231d24e

File tree

7 files changed

+1029
-1012
lines changed

7 files changed

+1029
-1012
lines changed

src/generate/device.rs

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
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", "CPUID", "DCB", "DWT", "FPB", "FPU", "ITM", "MPU", "NVIC", "SCB", "SYST", "TPIU"
89+
];
90+
91+
let mut fields = vec![];
92+
let mut exprs = vec![];
93+
if *target == Target::CortexM {
94+
out.push(quote! {
95+
pub use cortex_m::peripheral::Peripherals as CorePeripherals;
96+
});
97+
98+
// NOTE re-export only core peripherals available on *all* Cortex-M devices
99+
// (if we want to re-export all core peripherals available for the target then we are going
100+
// to need to replicate the `#[cfg]` stuff that cortex-m uses and that would require all
101+
// device crates to define the custom `#[cfg]`s that cortex-m uses in their build.rs ...)
102+
out.push(quote! {
103+
pub use cortex_m::peripheral::CPUID;
104+
pub use cortex_m::peripheral::DCB;
105+
pub use cortex_m::peripheral::DWT;
106+
pub use cortex_m::peripheral::MPU;
107+
pub use cortex_m::peripheral::NVIC;
108+
pub use cortex_m::peripheral::SCB;
109+
pub use cortex_m::peripheral::SYST;
110+
});
111+
}
112+
113+
for p in &d.peripherals {
114+
if *target == Target::CortexM && CORE_PERIPHERALS.contains(&&*p.name.to_uppercase()) {
115+
// Core peripherals are handled above
116+
continue;
117+
}
118+
119+
out.extend(peripheral::render(p, &d.peripherals, &d.defaults)?);
120+
121+
if p.registers
122+
.as_ref()
123+
.map(|v| &v[..])
124+
.unwrap_or(&[])
125+
.is_empty() && p.derived_from.is_none()
126+
{
127+
// No register block will be generated so don't put this peripheral
128+
// in the `Peripherals` struct
129+
continue;
130+
}
131+
132+
let p = p.name.to_sanitized_upper_case();
133+
let id = Ident::new(&*p);
134+
fields.push(quote! {
135+
#[doc = #p]
136+
pub #id: #id
137+
});
138+
exprs.push(quote!(#id: #id { _marker: PhantomData }));
139+
}
140+
141+
let take = match *target {
142+
Target::CortexM => Some(Ident::new("cortex_m")),
143+
Target::Msp430 => Some(Ident::new("msp430")),
144+
Target::None => None,
145+
}.map(|krate| {
146+
quote! {
147+
/// Returns all the peripherals *once*
148+
#[inline]
149+
pub fn take() -> Option<Self> {
150+
#krate::interrupt::free(|_| {
151+
if unsafe { DEVICE_PERIPHERALS } {
152+
None
153+
} else {
154+
Some(unsafe { Peripherals::steal() })
155+
}
156+
})
157+
}
158+
}
159+
});
160+
161+
out.push(quote! {
162+
// NOTE `no_mangle` is used here to prevent linking different minor versions of the device
163+
// crate as that would let you `take` the device peripherals more than once (one per minor
164+
// version)
165+
#[no_mangle]
166+
static mut DEVICE_PERIPHERALS: bool = false;
167+
168+
/// All the peripherals
169+
#[allow(non_snake_case)]
170+
pub struct Peripherals {
171+
#(#fields,)*
172+
}
173+
174+
impl Peripherals {
175+
#take
176+
177+
/// Unchecked version of `Peripherals::take`
178+
pub unsafe fn steal() -> Self {
179+
debug_assert!(!DEVICE_PERIPHERALS);
180+
181+
DEVICE_PERIPHERALS = true;
182+
183+
Peripherals {
184+
#(#exprs,)*
185+
}
186+
}
187+
}
188+
});
189+
190+
Ok(out)
191+
}

0 commit comments

Comments
 (0)