Skip to content

Commit 74173b9

Browse files
committed
unbreak msp430 / riscv; generate 3 files for cortex-m
1 parent a5a2743 commit 74173b9

File tree

3 files changed

+128
-29
lines changed

3 files changed

+128
-29
lines changed

src/generate/device.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use Target;
99
use generate::{interrupt, peripheral};
1010

1111
/// Whole device generation
12-
pub fn render(d: &Device, target: &Target, nightly: bool) -> Result<Vec<Tokens>> {
12+
pub fn render(d: &Device, target: &Target, nightly: bool, device_x: &mut String) -> Result<Vec<Tokens>> {
1313
let mut out = vec![];
1414

1515
let doc = format!(
@@ -43,6 +43,13 @@ pub fn render(d: &Device, target: &Target, nightly: bool) -> Result<Vec<Tokens>>
4343
#![no_std]
4444
});
4545

46+
if *target != Target::CortexM {
47+
out.push(quote! {
48+
#![feature(const_fn)]
49+
#![feature(try_From)]
50+
});
51+
}
52+
4653
if nightly {
4754
out.push(quote! {
4855
#![feature(untagged_unions)]
@@ -93,7 +100,7 @@ pub fn render(d: &Device, target: &Target, nightly: bool) -> Result<Vec<Tokens>>
93100
});
94101
}
95102

96-
out.extend(interrupt::render(target, &d.peripherals)?);
103+
out.extend(interrupt::render(target, &d.peripherals, device_x)?);
97104

98105
const CORE_PERIPHERALS: &[&str] = &[
99106
"CBP", "CPUID", "DCB", "DWT", "FPB", "FPU", "ITM", "MPU", "NVIC", "SCB", "SYST", "TPIU"

src/generate/interrupt.rs

Lines changed: 76 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::collections::HashMap;
2+
use std::fmt::Write;
23

34
use cast::u64;
45
use quote::Tokens;
@@ -10,7 +11,11 @@ use util::{self, ToSanitizedUpperCase};
1011
use Target;
1112

1213
/// Generates code for `src/interrupt.rs`
13-
pub fn render(target: &Target, peripherals: &[Peripheral]) -> Result<Vec<Tokens>> {
14+
pub fn render(
15+
target: &Target,
16+
peripherals: &[Peripheral],
17+
device_x: &mut String,
18+
) -> Result<Vec<Tokens>> {
1419
let interrupts = peripherals
1520
.iter()
1621
.flat_map(|p| p.interrupt.iter())
@@ -32,7 +37,7 @@ pub fn render(target: &Target, peripherals: &[Peripheral]) -> Result<Vec<Tokens>
3237
let mut mod_items = vec![];
3338
for interrupt in &interrupts {
3439
while pos < interrupt.value {
35-
elements.push(quote!(None));
40+
elements.push(quote!(Vector { _reserved: 0 }));
3641
pos += 1;
3742
}
3843
pos += 1;
@@ -63,42 +68,87 @@ pub fn render(target: &Target, peripherals: &[Peripheral]) -> Result<Vec<Tokens>
6368
#value => Ok(Interrupt::#name_uc),
6469
});
6570

66-
elements.push(quote!(Some(#name_uc)));
71+
elements.push(quote!(Vector { _handler: #name_uc }));
6772
names.push(name_uc);
6873
}
6974

70-
let aliases = names
71-
.iter()
72-
.map(|n| {
73-
format!(
74-
"
75-
.weak {0}
76-
{0} = DH_TRAMPOLINE",
77-
n
78-
)
79-
})
80-
.collect::<Vec<_>>()
81-
.concat();
82-
8375
let n = util::unsuffixed(u64(pos));
8476
match *target {
8577
Target::CortexM => {
78+
for name in &names {
79+
writeln!(device_x, "PROVIDE({} = DefaultHandler);" ,name).unwrap();
80+
}
81+
8682
root.push(quote! {
8783
#[cfg(feature = "rt")]
8884
extern "C" {
8985
#(fn #names();)*
9086
}
9187

88+
#[doc(hidden)]
89+
pub union Vector {
90+
_handler: unsafe extern "C" fn(),
91+
_reserved: u32,
92+
}
93+
9294
#[cfg(feature = "rt")]
9395
#[doc(hidden)]
9496
#[link_section = ".vector_table.interrupts"]
9597
#[no_mangle]
96-
pub static __INTERRUPTS: [Option<unsafe extern "C" fn()>; #n] = [
98+
pub static __INTERRUPTS: [Vector; #n] = [
9799
#(#elements,)*
98100
];
101+
102+
/// Macro to override a device specific interrupt handler
103+
#[cfg(feature = "rt")]
104+
#[macro_export]
105+
macro_rules! interrupt {
106+
($Name:ident, $handler:path,state: $State:ty = $initial_state:expr) => {
107+
#[allow(unsafe_code)]
108+
#[no_mangle]
109+
pub unsafe extern "C" fn $Name() {
110+
static mut STATE: $State = $initial_state;
111+
112+
// check that this interrupt exists
113+
let _ = $crate::Interrupt::$Name;
114+
115+
// validate the signature of the user provided handler
116+
let f: fn(&mut $State) = $handler;
117+
118+
f(&mut STATE)
119+
}
120+
};
121+
122+
($Name:ident, $handler:path) => {
123+
#[allow(unsafe_code)]
124+
#[no_mangle]
125+
pub unsafe extern "C" fn $Name() {
126+
// check that this interrupt exists
127+
let _ = $crate::Interrupt::$Name;
128+
129+
// validate the signature of the user provided handler
130+
let f: fn() = $handler;
131+
132+
f()
133+
}
134+
};
135+
}
99136
});
100137
}
101138
Target::Msp430 => {
139+
let aliases = names
140+
.iter()
141+
.map(|n| {
142+
format!(
143+
"
144+
.weak {0}
145+
{0} = DH_TRAMPOLINE",
146+
n
147+
)
148+
})
149+
.collect::<Vec<_>>()
150+
.concat();
151+
102152
mod_items.push(quote! {
103153
#[cfg(feature = "rt")]
104154
global_asm!("
@@ -114,14 +164,20 @@ pub fn render(target: &Target, peripherals: &[Peripheral]) -> Result<Vec<Tokens>
114164
#(fn #names();)*
115165
}
116166

167+
#[doc(hidden)]
168+
pub union Vector {
169+
_handler: unsafe extern "msp430-interrupt" fn(),
170+
_reserved: u32,
171+
}
172+
117173
#[allow(private_no_mangle_statics)]
118174
#[cfg(feature = "rt")]
119175
#[doc(hidden)]
120176
#[link_section = ".vector_table.interrupts"]
121177
#[no_mangle]
122178
#[used]
123179
pub static INTERRUPTS:
124-
[Option<unsafe extern "msp430-interrupt" fn()>; #n] = [
180+
[Vector; #n] = [
125181
#(#elements,)*
126182
];
127183
});
@@ -152,6 +208,8 @@ pub fn render(target: &Target, peripherals: &[Peripheral]) -> Result<Vec<Tokens>
152208
mod_items.push(quote! {
153209
use core::convert::TryFrom;
154210

211+
#interrupt_enum
212+
155213
#[derive(Debug, Copy, Clone)]
156214
pub struct TryFromInterruptError(());
157215

src/main.rs

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ mod generate;
1616
mod util;
1717

1818
use std::fs::File;
19-
use std::{io, process};
19+
use std::process;
20+
use std::io::{self, Write};
2021

22+
use quote::Tokens;
2123
use clap::{App, Arg};
2224

2325
use errors::*;
@@ -98,14 +100,21 @@ fn run() -> Result<()> {
98100

99101
let nightly = matches.is_present("nightly_features");
100102

101-
let items = generate::device::render(&device, &target, nightly)?;
102-
103-
println!(
104-
"{}",
105-
quote! {
106-
#(#items)*
107-
}
108-
);
103+
let mut device_x = String::new();
104+
let items = generate::device::render(&device, &target, nightly, &mut device_x)?;
105+
106+
if target == Target::CortexM {
107+
writeln!(File::create("lib.rs").unwrap(), "{}", quote!(#(#items)*)).unwrap();
108+
writeln!(File::create("device.x").unwrap(), "{}", device_x).unwrap();
109+
writeln!(File::create("build.rs").unwrap(), "{}", build_rs()).unwrap();
110+
} else {
111+
println!(
112+
"{}",
113+
quote! {
114+
#(#items)*
115+
}
116+
);
117+
}
109118

110119
Ok(())
111120
}
@@ -132,3 +141,28 @@ fn main() {
132141
process::exit(1);
133142
}
134143
}
144+
145+
fn build_rs() -> Tokens {
146+
quote! {
147+
use std::env;
148+
use std::fs::File;
149+
use std::io::Write;
150+
use std::path::PathBuf;
151+
152+
fn main() {
153+
if env::var_os("CARGO_FEATURE_RT").is_some() {
154+
// Put the linker script somewhere the linker can find it
155+
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
156+
File::create(out.join("device.x"))
157+
.unwrap()
158+
.write_all(include_bytes!("device.x"))
159+
.unwrap();
160+
println!("cargo:rustc-link-search={}", out.display());
161+
162+
println!("cargo:rerun-if-changed=device.x");
163+
}
164+
165+
println!("cargo:rerun-if-changed=build.rs");
166+
}
167+
}
168+
}

0 commit comments

Comments
 (0)