Skip to content

Commit ad9025d

Browse files
bors[bot]cr1901
andauthored
Merge #401
401: MSP430 Improvements r=therealprof a=cr1901 This PR brings MSP430 PAC generation up to parity with Cortex M PAC generation. Among other things, a `device.x` file is now generated for each MSP430 PAC, and the `interrupt!` macro has been replaced with an attribute macro from the not-yet-published `msp430-rt v0.2.0`. The remaining changes are docs and cleanups of the generated code; a number of features have become stable. Only `abi_msp430_interrupt` is not stable yet, and I have a workaround for this that I've not written yet. Switching to an `interrupt` attribute macro is a breaking change, so I incremented the "major" version number. Co-authored-by: William D. Jones <thor0505@comcast.net>
2 parents 960b03c + 783fbd0 commit ad9025d

File tree

9 files changed

+154
-87
lines changed

9 files changed

+154
-87
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
### Changed
11+
12+
- [breaking-change] Among other cleanups, MSP430 crates are now expected to
13+
use the `msp430_rt::interrupt` attribute macro and `device.x` for interrupt
14+
support. The `INTERRUPT` array has been renamed `__INTERRUPT`.
15+
1016
## [v0.17.0] - 2019-12-31
1117

1218
### Fixed

ci/svd2rust-regress/src/errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::path::PathBuf;
2-
error_chain!{
2+
error_chain! {
33
errors {
44
ProcessFailed(command: String, stderr: Option<PathBuf>, stdout: Option<PathBuf>, previous_processes_stderr: Vec<PathBuf>) {
55
description("Process Failed")

ci/svd2rust-regress/src/main.rs

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ struct Opt {
2727
/// (which must be already built)
2828
#[structopt(short = "p", long = "svd2rust-path", parse(from_os_str))]
2929
bin_path: Option<PathBuf>,
30-
30+
3131
// TODO: Consider using the same strategy cargo uses for passing args to rustc via `--`
3232
/// Run svd2rust with `--nightly`
3333
#[structopt(long = "nightly")]
@@ -38,12 +38,20 @@ struct Opt {
3838
chip: Vec<String>,
3939

4040
/// Filter by manufacturer, case sensitive, may be combined with other filters
41-
#[structopt(short = "m", long = "manufacturer", raw(validator = "validate_manufacturer"))]
41+
#[structopt(
42+
short = "m",
43+
long = "manufacturer",
44+
raw(validator = "validate_manufacturer")
45+
)]
4246
mfgr: Option<String>,
4347

4448
/// Filter by architecture, case sensitive, may be combined with other filters
4549
/// Options are: "CortexM", "RiscV", and "Msp430"
46-
#[structopt(short = "a", long = "architecture", raw(validator = "validate_architecture"))]
50+
#[structopt(
51+
short = "a",
52+
long = "architecture",
53+
raw(validator = "validate_architecture")
54+
)]
4755
arch: Option<String>,
4856

4957
/// Include tests expected to fail (will cause a non-zero return code)
@@ -74,23 +82,23 @@ struct Opt {
7482
// TODO: Compile svd2rust?
7583
}
7684

77-
fn validate_chips(s: String) -> Result<(), String>{
85+
fn validate_chips(s: String) -> Result<(), String> {
7886
if tests::TESTS.iter().any(|t| t.chip == s) {
7987
Ok(())
8088
} else {
8189
Err(format!("Chip `{}` is not a valid value", s))
8290
}
8391
}
8492

85-
fn validate_architecture(s: String) -> Result<(), String>{
93+
fn validate_architecture(s: String) -> Result<(), String> {
8694
if tests::TESTS.iter().any(|t| format!("{:?}", t.arch) == s) {
8795
Ok(())
8896
} else {
8997
Err(format!("Architecture `{}` is not a valid value", s))
9098
}
9199
}
92100

93-
fn validate_manufacturer(s: String) -> Result<(), String>{
101+
fn validate_manufacturer(s: String) -> Result<(), String> {
94102
if tests::TESTS.iter().any(|t| format!("{:?}", t.mfgr) == s) {
95103
Ok(())
96104
} else {
@@ -144,7 +152,8 @@ fn main() {
144152
default_svd2rust_iter.iter().chain(["svd2rust.exe"].iter())
145153
} else {
146154
default_svd2rust_iter.iter().chain(["svd2rust"].iter())
147-
}.collect();
155+
}
156+
.collect();
148157

149158
let bin_path = match opt.bin_path {
150159
Some(ref bp) => bp,
@@ -170,11 +179,7 @@ fn main() {
170179
(&Some(ref path), true) => Some(path),
171180
(&None, true) => {
172181
// FIXME: Use Option::filter instead when stable, rust-lang/rust#45860
173-
if default_rustfmt
174-
.iter()
175-
.find(|p| p.is_file())
176-
.is_none()
177-
{
182+
if default_rustfmt.iter().find(|p| p.is_file()).is_none() {
178183
panic!("No rustfmt found");
179184
}
180185
default_rustfmt.as_ref()
@@ -260,8 +265,13 @@ fn main() {
260265
any_fails.store(true, Ordering::Release);
261266
let additional_info = if opt.verbose > 0 {
262267
match *e.kind() {
263-
errors::ErrorKind::ProcessFailed(_, _, Some(ref stderr), ref previous_processes_stderr) => {
264-
let mut buf = String::new();
268+
errors::ErrorKind::ProcessFailed(
269+
_,
270+
_,
271+
Some(ref stderr),
272+
ref previous_processes_stderr,
273+
) => {
274+
let mut buf = String::new();
265275
if opt.verbose > 1 {
266276
for stderr in previous_processes_stderr {
267277
read_file(&stderr, &mut buf);

ci/svd2rust-regress/src/svd_test.rs

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
use crate::errors::*;
2+
use crate::tests::TestCase;
23
use reqwest;
34
use std::fs::{self, File, OpenOptions};
45
use std::io::prelude::*;
56
use std::path::PathBuf;
67
use std::process::{Command, Output};
7-
use crate::tests::TestCase;
88

99
static CRATES_ALL: &[&str] = &["bare-metal = \"0.2.0\"", "vcell = \"0.1.0\""];
1010
static CRATES_MSP430: &[&str] = &["msp430 = \"0.1.0\""];
1111
static CRATES_CORTEX_M: &[&str] = &["cortex-m = \"0.5.0\"", "cortex-m-rt = \"0.5.0\""];
1212
static CRATES_RISCV: &[&str] = &["riscv = \"0.4.0\"", "riscv-rt = \"0.4.0\""];
1313
static PROFILE_ALL: &[&str] = &["[profile.dev]", "incremental = false"];
1414
static FEATURES_ALL: &[&str] = &["[features]"];
15-
static FEATURES_CORTEX_M: &[&str] = &["const-fn = [\"bare-metal/const-fn\", \"cortex-m/const-fn\"]"];
15+
static FEATURES_CORTEX_M: &[&str] =
16+
&["const-fn = [\"bare-metal/const-fn\", \"cortex-m/const-fn\"]"];
1617
static FEATURES_EMPTY: &[&str] = &[];
1718

1819
fn path_helper(input: &[&str]) -> PathBuf {
@@ -66,20 +67,26 @@ impl CommandHelper for Output {
6667
};
6768

6869
if cant_fail && !self.status.success() {
69-
return Err(
70-
ErrorKind::ProcessFailed(name.into(),
71-
stdout.cloned(),
72-
stderr.cloned(),
73-
previous_processes_stderr.to_vec(),
74-
).into()
75-
);
70+
return Err(ErrorKind::ProcessFailed(
71+
name.into(),
72+
stdout.cloned(),
73+
stderr.cloned(),
74+
previous_processes_stderr.to_vec(),
75+
)
76+
.into());
7677
}
7778

7879
Ok(())
7980
}
8081
}
8182

82-
pub fn test(t: &TestCase, bin_path: &PathBuf, rustfmt_bin_path: Option<&PathBuf>, nightly: bool, verbosity: u8) -> Result<Option<Vec<PathBuf>>> {
83+
pub fn test(
84+
t: &TestCase,
85+
bin_path: &PathBuf,
86+
rustfmt_bin_path: Option<&PathBuf>,
87+
nightly: bool,
88+
verbosity: u8,
89+
) -> Result<Option<Vec<PathBuf>>> {
8390
let user = match std::env::var("USER") {
8491
Ok(val) => val,
8592
Err(_) => "rusttester".into(),
@@ -90,7 +97,7 @@ pub fn test(t: &TestCase, bin_path: &PathBuf, rustfmt_bin_path: Option<&PathBuf>
9097
if let Err(err) = fs::remove_dir_all(&chip_dir) {
9198
match err.kind() {
9299
std::io::ErrorKind::NotFound => (),
93-
_ => Err(err).chain_err(|| "While removing chip directory")?
100+
_ => Err(err).chain_err(|| "While removing chip directory")?,
94101
}
95102
}
96103

@@ -151,7 +158,7 @@ pub fn test(t: &TestCase, bin_path: &PathBuf, rustfmt_bin_path: Option<&PathBuf>
151158
file_helper(&svd, &svd_file)?;
152159

153160
// Generate the lib.rs from the SVD file using the specified `svd2rust` binary
154-
// If the architecture is cortex-m we move the generated lib.rs file to src/
161+
// If the architecture is cortex-m or msp430 we move the generated lib.rs file to src/
155162
let lib_rs_file = path_helper_base(&chip_dir, &["src", "lib.rs"]);
156163
let svd2rust_err_file = path_helper_base(&chip_dir, &["svd2rust.err.log"]);
157164
let target = match t.arch {
@@ -173,21 +180,25 @@ pub fn test(t: &TestCase, bin_path: &PathBuf, rustfmt_bin_path: Option<&PathBuf>
173180
output.capture_outputs(
174181
true,
175182
"svd2rust",
176-
if t.arch != CortexM { Some(&lib_rs_file) } else { None }, // use Option.filter
183+
Some(&lib_rs_file).filter(|_| (t.arch != CortexM) && (t.arch != Msp430)),
177184
Some(&svd2rust_err_file),
178185
&[],
179186
)?;
180187
process_stderr_paths.push(svd2rust_err_file);
181188

182-
if let CortexM = t.arch {
183-
// TODO: Give error the path to stderr
184-
fs::rename(path_helper_base(&chip_dir, &["lib.rs"]), &lib_rs_file).chain_err(|| "While moving lib.rs file")?
189+
match t.arch {
190+
CortexM | Msp430 => {
191+
// TODO: Give error the path to stderr
192+
fs::rename(path_helper_base(&chip_dir, &["lib.rs"]), &lib_rs_file)
193+
.chain_err(|| "While moving lib.rs file")?
194+
}
195+
_ => {}
185196
}
186197

187198
let rustfmt_err_file = path_helper_base(&chip_dir, &["rustfmt.err.log"]);
188199
if let Some(rustfmt_bin_path) = rustfmt_bin_path {
189200
// Run `cargo fmt`, capturing stderr to a log file
190-
201+
191202
let output = Command::new(rustfmt_bin_path)
192203
.arg(lib_rs_file)
193204
.output()
@@ -200,7 +211,6 @@ pub fn test(t: &TestCase, bin_path: &PathBuf, rustfmt_bin_path: Option<&PathBuf>
200211
&process_stderr_paths,
201212
)?;
202213
process_stderr_paths.push(rustfmt_err_file);
203-
204214
}
205215
// Run `cargo check`, capturing stderr to a log file
206216
let cargo_check_err_file = path_helper_base(&chip_dir, &["cargo-check.err.log"]);
@@ -215,7 +225,11 @@ pub fn test(t: &TestCase, bin_path: &PathBuf, rustfmt_bin_path: Option<&PathBuf>
215225
None,
216226
Some(&cargo_check_err_file),
217227
&process_stderr_paths,
218-
)?;
228+
)?;
219229
process_stderr_paths.push(cargo_check_err_file);
220-
Ok(if verbosity > 1 {Some(process_stderr_paths)} else {None})
230+
Ok(if verbosity > 1 {
231+
Some(process_stderr_paths)
232+
} else {
233+
None
234+
})
221235
}

ci/svd2rust-regress/src/tests.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,9 @@ pub const TESTS: &[&TestCase] = &[
709709
arch: CortexM,
710710
mfgr: Atmel,
711711
chip: "ATSAMD21G18A",
712-
svd_url: Some("https://raw.githubusercontent.com/wez/atsamd21-rs/master/svd/ATSAMD21G18A.svd"),
712+
svd_url: Some(
713+
"https://raw.githubusercontent.com/wez/atsamd21-rs/master/svd/ATSAMD21G18A.svd",
714+
),
713715
should_pass: true,
714716
run_when: NotShort,
715717
},
@@ -4220,7 +4222,7 @@ pub const TESTS: &[&TestCase] = &[
42204222
arch: Msp430,
42214223
mfgr: TexasInstruments,
42224224
chip: "msp430g2553",
4223-
svd_url: Some("https://github.com/pftbest/msp430g2553/raw/v0.1.0/msp430g2553.svd"),
4225+
svd_url: Some("https://github.com/pftbest/msp430g2553/raw/v0.1.3-svd/msp430g2553.svd"),
42244226
should_pass: true,
42254227
run_when: Always,
42264228
},

src/generate/device.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,6 @@ pub fn render(
3535
});
3636
}
3737

38-
if target != Target::None && target != Target::CortexM && target != Target::RISCV {
39-
out.extend(quote! {
40-
#![cfg_attr(feature = "rt", feature(global_asm))]
41-
#![cfg_attr(feature = "rt", feature(use_extern_macros))]
42-
#![cfg_attr(feature = "rt", feature(used))]
43-
});
44-
}
45-
4638
out.extend(quote! {
4739
#![doc = #doc]
4840
// Deny a subset of warnings
@@ -84,8 +76,6 @@ pub fn render(
8476
extern crate msp430;
8577
#[cfg(feature = "rt")]
8678
extern crate msp430_rt;
87-
#[cfg(feature = "rt")]
88-
pub use msp430_rt::default_handler;
8979
});
9080
}
9181
Target::RISCV => {
@@ -158,6 +148,17 @@ pub fn render(
158148
}
159149
}
160150

151+
if target == Target::Msp430 {
152+
out.extend(quote! {
153+
// XXX: Are there any core peripherals, really? Requires bump of msp430 crate.
154+
// pub use msp430::peripheral::Peripherals as CorePeripherals;
155+
#[cfg(feature = "rt")]
156+
pub use msp430_rt::interrupt;
157+
#[cfg(feature = "rt")]
158+
pub use self::Interrupt as interrupt;
159+
});
160+
}
161+
161162
let generic_file = std::str::from_utf8(include_bytes!("generic.rs")).unwrap();
162163
if generic_mod {
163164
writeln!(File::create("generic.rs").unwrap(), "{}", generic_file).unwrap();

src/generate/interrupt.rs

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -97,29 +97,11 @@ pub fn render(
9797
});
9898
}
9999
Target::Msp430 => {
100-
let aliases = names
101-
.iter()
102-
.map(|n| {
103-
format!(
104-
"
105-
.weak {0}
106-
{0} = DH_TRAMPOLINE",
107-
n
108-
)
109-
})
110-
.collect::<Vec<_>>()
111-
.concat();
112-
113-
mod_items.push(quote! {
114-
#[cfg(feature = "rt")]
115-
global_asm!("
116-
DH_TRAMPOLINE:
117-
br #DEFAULT_HANDLER
118-
");
119-
120-
#[cfg(feature = "rt")]
121-
global_asm!(#aliases);
100+
for name in &names {
101+
writeln!(device_x, "PROVIDE({} = DefaultHandler);", name).unwrap();
102+
}
122103

104+
root.extend(quote! {
123105
#[cfg(feature = "rt")]
124106
extern "msp430-interrupt" {
125107
#(fn #names();)*
@@ -136,7 +118,7 @@ pub fn render(
136118
#[link_section = ".vector_table.interrupts"]
137119
#[no_mangle]
138120
#[used]
139-
pub static INTERRUPTS:
121+
pub static __INTERRUPTS:
140122
[Vector; #n] = [
141123
#(#elements,)*
142124
];
@@ -169,7 +151,7 @@ pub fn render(
169151
}
170152
};
171153

172-
if target == Target::CortexM {
154+
if target == Target::CortexM || target == Target::Msp430 {
173155
root.extend(interrupt_enum);
174156
} else {
175157
mod_items.push(quote! {
@@ -196,7 +178,7 @@ pub fn render(
196178
_ => "C",
197179
};
198180

199-
if target != Target::CortexM {
181+
if target != Target::CortexM && target != Target::Msp430 {
200182
mod_items.push(quote! {
201183
#[cfg(feature = "rt")]
202184
#[macro_export]
@@ -283,7 +265,7 @@ pub fn render(
283265
}
284266
}
285267

286-
if !interrupts.is_empty() && target != Target::CortexM {
268+
if !interrupts.is_empty() && target != Target::CortexM && target != Target::Msp430 {
287269
root.extend(quote! {
288270
#[doc(hidden)]
289271
pub mod interrupt {

0 commit comments

Comments
 (0)