Skip to content

Commit a5a2743

Browse files
committed
cortex-m: generate code that compiles on stable
1 parent f271405 commit a5a2743

File tree

3 files changed

+82
-123
lines changed

3 files changed

+82
-123
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ keywords = [
1919
license = "MIT OR Apache-2.0"
2020
name = "svd2rust"
2121
repository = "https://github.com/japaric/svd2rust"
22-
version = "0.12.1"
22+
version = "0.13.0"
2323

2424
[[bin]]
2525
doc = false

src/generate/device.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub fn render(d: &Device, target: &Target, nightly: bool) -> Result<Vec<Tokens>>
2727
});
2828
}
2929

30-
if *target != Target::None {
30+
if *target != Target::None && *target != Target::CortexM {
3131
out.push(quote! {
3232
#![cfg_attr(feature = "rt", feature(global_asm))]
3333
#![cfg_attr(feature = "rt", feature(use_extern_macros))]
@@ -37,12 +37,9 @@ pub fn render(d: &Device, target: &Target, nightly: bool) -> Result<Vec<Tokens>>
3737

3838
out.push(quote! {
3939
#![doc = #doc]
40-
#![allow(private_no_mangle_statics)]
4140
#![deny(missing_docs)]
4241
#![deny(warnings)]
4342
#![allow(non_camel_case_types)]
44-
#![feature(const_fn)]
45-
#![feature(try_from)]
4643
#![no_std]
4744
});
4845

@@ -58,8 +55,6 @@ pub fn render(d: &Device, target: &Target, nightly: bool) -> Result<Vec<Tokens>>
5855
extern crate cortex_m;
5956
#[cfg(feature = "rt")]
6057
extern crate cortex_m_rt;
61-
#[cfg(feature = "rt")]
62-
pub use cortex_m_rt::{default_handler, exception};
6358
});
6459
}
6560
Target::Msp430 => {
@@ -98,7 +93,7 @@ pub fn render(d: &Device, target: &Target, nightly: bool) -> Result<Vec<Tokens>>
9893
});
9994
}
10095

101-
out.extend(interrupt::render(d, target, &d.peripherals)?);
96+
out.extend(interrupt::render(target, &d.peripherals)?);
10297

10398
const CORE_PERIPHERALS: &[&str] = &[
10499
"CBP", "CPUID", "DCB", "DWT", "FPB", "FPU", "ITM", "MPU", "NVIC", "SCB", "SYST", "TPIU"
@@ -180,6 +175,7 @@ pub fn render(d: &Device, target: &Target, nightly: bool) -> Result<Vec<Tokens>>
180175
// NOTE `no_mangle` is used here to prevent linking different minor versions of the device
181176
// crate as that would let you `take` the device peripherals more than once (one per minor
182177
// version)
178+
#[allow(private_no_mangle_statics)]
183179
#[no_mangle]
184180
static mut DEVICE_PERIPHERALS: bool = false;
185181

src/generate/interrupt.rs

Lines changed: 78 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ use std::collections::HashMap;
22

33
use cast::u64;
44
use quote::Tokens;
5-
use svd::{Device, Peripheral};
5+
use svd::Peripheral;
66
use syn::Ident;
77

88
use errors::*;
99
use util::{self, ToSanitizedUpperCase};
1010
use Target;
1111

1212
/// Generates code for `src/interrupt.rs`
13-
pub fn render(device: &Device, target: &Target, peripherals: &[Peripheral]) -> Result<Vec<Tokens>> {
13+
pub fn render(target: &Target, peripherals: &[Peripheral]) -> Result<Vec<Tokens>> {
1414
let interrupts = peripherals
1515
.iter()
1616
.flat_map(|p| p.interrupt.iter())
@@ -20,6 +20,7 @@ pub fn render(device: &Device, target: &Target, peripherals: &[Peripheral]) -> R
2020
let mut interrupts = interrupts.into_iter().map(|(_, v)| v).collect::<Vec<_>>();
2121
interrupts.sort_by_key(|i| i.value);
2222

23+
let mut root = vec![];
2324
let mut arms = vec![];
2425
let mut from_arms = vec![];
2526
let mut elements = vec![];
@@ -29,9 +30,6 @@ pub fn render(device: &Device, target: &Target, peripherals: &[Peripheral]) -> R
2930
// Current position in the vector table
3031
let mut pos = 0;
3132
let mut mod_items = vec![];
32-
mod_items.push(quote! {
33-
use bare_metal::Nr;
34-
});
3533
for interrupt in &interrupts {
3634
while pos < interrupt.value {
3735
elements.push(quote!(None));
@@ -85,63 +83,17 @@ pub fn render(device: &Device, target: &Target, peripherals: &[Peripheral]) -> R
8583
let n = util::unsuffixed(u64(pos));
8684
match *target {
8785
Target::CortexM => {
88-
let is_armv6 = match device.cpu {
89-
Some(ref cpu) => cpu.name.starts_with("CM0"),
90-
None => true, // default to armv6 when the <cpu> section is missing
91-
};
92-
93-
if is_armv6 {
94-
// Cortex-M0(+) are ARMv6 and don't have `b.w` (branch with 16 MB range). This
95-
// can cause linker errors when the handler is too far away. Instead of a small
96-
// inline assembly shim, we generate a function for those targets and let the
97-
// compiler do the work (sacrificing a few bytes of code).
98-
mod_items.push(quote! {
99-
#[cfg(feature = "rt")]
100-
extern "C" {
101-
fn DEFAULT_HANDLER();
102-
}
103-
104-
#[cfg(feature = "rt")]
105-
#[allow(non_snake_case)]
106-
#[no_mangle]
107-
pub unsafe extern "C" fn DH_TRAMPOLINE() {
108-
DEFAULT_HANDLER();
109-
}
110-
});
111-
} else {
112-
mod_items.push(quote! {
113-
#[cfg(all(target_arch = "arm", feature = "rt"))]
114-
global_asm!("
115-
.thumb_func
116-
DH_TRAMPOLINE:
117-
b DEFAULT_HANDLER
118-
");
119-
120-
/// Hack to compile on x86
121-
#[cfg(all(target_arch = "x86_64", feature = "rt"))]
122-
global_asm!("
123-
DH_TRAMPOLINE:
124-
jmp DEFAULT_HANDLER
125-
");
126-
})
127-
}
128-
129-
mod_items.push(quote! {
130-
#[cfg(feature = "rt")]
131-
global_asm!(#aliases);
132-
86+
root.push(quote! {
13387
#[cfg(feature = "rt")]
13488
extern "C" {
13589
#(fn #names();)*
13690
}
13791

138-
#[allow(private_no_mangle_statics)]
13992
#[cfg(feature = "rt")]
14093
#[doc(hidden)]
14194
#[link_section = ".vector_table.interrupts"]
14295
#[no_mangle]
143-
#[used]
144-
pub static INTERRUPTS: [Option<unsafe extern "C" fn()>; #n] = [
96+
pub static __INTERRUPTS: [Option<unsafe extern "C" fn()>; #n] = [
14597
#(#elements,)*
14698
];
14799
});
@@ -178,106 +130,117 @@ pub fn render(device: &Device, target: &Target, peripherals: &[Peripheral]) -> R
178130
Target::None => {}
179131
}
180132

181-
mod_items.push(quote! {
133+
let interrupt_enum = quote! {
182134
/// Enumeration of all the interrupts
183135
pub enum Interrupt {
184136
#(#variants)*
185137
}
186138

187-
unsafe impl Nr for Interrupt {
139+
unsafe impl ::bare_metal::Nr for Interrupt {
188140
#[inline]
189141
fn nr(&self) -> u8 {
190142
match *self {
191143
#(#arms)*
192144
}
193145
}
194146
}
147+
};
195148

196-
use core::convert::TryFrom;
149+
if *target == Target::CortexM {
150+
root.push(interrupt_enum);
151+
} else {
152+
mod_items.push(quote! {
153+
use core::convert::TryFrom;
197154

198-
#[derive(Debug, Copy, Clone)]
199-
pub struct TryFromInterruptError(());
155+
#[derive(Debug, Copy, Clone)]
156+
pub struct TryFromInterruptError(());
200157

201-
impl TryFrom<u8> for Interrupt {
202-
type Error = TryFromInterruptError;
158+
impl TryFrom<u8> for Interrupt {
159+
type Error = TryFromInterruptError;
203160

204-
#[inline]
205-
fn try_from(value: u8) -> Result<Self, Self::Error> {
206-
match value {
207-
#(#from_arms)*
208-
_ => Err(TryFromInterruptError(())),
161+
#[inline]
162+
fn try_from(value: u8) -> Result<Self, Self::Error> {
163+
match value {
164+
#(#from_arms)*
165+
_ => Err(TryFromInterruptError(())),
166+
}
209167
}
210168
}
211-
}
212-
});
169+
});
170+
}
213171

214172
if *target != Target::None {
215173
let abi = match *target {
216174
Target::Msp430 => "msp430-interrupt",
217175
_ => "C",
218176
};
219-
mod_items.push(quote! {
220-
#[cfg(feature = "rt")]
221-
#[macro_export]
222-
macro_rules! interrupt {
223-
($NAME:ident, $path:path, locals: {
224-
$($lvar:ident:$lty:ty = $lval:expr;)*
225-
}) => {
226-
#[allow(non_snake_case)]
227-
mod $NAME {
228-
pub struct Locals {
229-
$(
230-
pub $lvar: $lty,
231-
)*
232-
}
233-
}
234-
235-
#[allow(non_snake_case)]
236-
#[no_mangle]
237-
pub extern #abi fn $NAME() {
238-
// check that the handler exists
239-
let _ = $crate::interrupt::Interrupt::$NAME;
240177

241-
static mut LOCALS: self::$NAME::Locals =
242-
self::$NAME::Locals {
178+
if *target != Target::CortexM {
179+
mod_items.push(quote! {
180+
#[cfg(feature = "rt")]
181+
#[macro_export]
182+
macro_rules! interrupt {
183+
($NAME:ident, $path:path, locals: {
184+
$($lvar:ident:$lty:ty = $lval:expr;)*
185+
}) => {
186+
#[allow(non_snake_case)]
187+
mod $NAME {
188+
pub struct Locals {
243189
$(
244-
$lvar: $lval,
190+
pub $lvar: $lty,
245191
)*
246-
};
192+
}
193+
}
247194

248-
// type checking
249-
let f: fn(&mut self::$NAME::Locals) = $path;
250-
f(unsafe { &mut LOCALS });
251-
}
252-
};
253-
($NAME:ident, $path:path) => {
254-
#[allow(non_snake_case)]
255-
#[no_mangle]
256-
pub extern #abi fn $NAME() {
257-
// check that the handler exists
258-
let _ = $crate::interrupt::Interrupt::$NAME;
259-
260-
// type checking
261-
let f: fn() = $path;
262-
f();
195+
#[allow(non_snake_case)]
196+
#[no_mangle]
197+
pub extern #abi fn $NAME() {
198+
// check that the handler exists
199+
let _ = $crate::interrupt::Interrupt::$NAME;
200+
201+
static mut LOCALS: self::$NAME::Locals =
202+
self::$NAME::Locals {
203+
$(
204+
$lvar: $lval,
205+
)*
206+
};
207+
208+
// type checking
209+
let f: fn(&mut self::$NAME::Locals) = $path;
210+
f(unsafe { &mut LOCALS });
211+
}
212+
};
213+
($NAME:ident, $path:path) => {
214+
#[allow(non_snake_case)]
215+
#[no_mangle]
216+
pub extern #abi fn $NAME() {
217+
// check that the handler exists
218+
let _ = $crate::interrupt::Interrupt::$NAME;
219+
220+
// type checking
221+
let f: fn() = $path;
222+
f();
223+
}
263224
}
264225
}
265-
}
266-
});
226+
});
227+
}
267228
}
268229

269-
let mut out = vec![];
270-
271230
if interrupts.len() > 0 {
272-
out.push(quote! {
273-
pub use interrupt::Interrupt;
274-
231+
root.push(quote! {
275232
#[doc(hidden)]
276233
pub mod interrupt {
277234
#(#mod_items)*
278235
}
279236
});
237+
238+
if *target != Target::CortexM {
239+
root.push(quote! {
240+
pub use interrupt::Interrupt;
241+
});
242+
}
280243
}
281244

282-
Ok(out)
245+
Ok(root)
283246
}

0 commit comments

Comments
 (0)