Skip to content

Commit 8b107cd

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 d35250c + 4eed932 commit 8b107cd

File tree

7 files changed

+103
-57
lines changed

7 files changed

+103
-57
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/svd_test.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ pub fn test(t: &TestCase, bin_path: &PathBuf, rustfmt_bin_path: Option<&PathBuf>
151151
file_helper(&svd, &svd_file)?;
152152

153153
// 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/
154+
// If the architecture is cortex-m or msp430 we move the generated lib.rs file to src/
155155
let lib_rs_file = path_helper_base(&chip_dir, &["src", "lib.rs"]);
156156
let svd2rust_err_file = path_helper_base(&chip_dir, &["svd2rust.err.log"]);
157157
let target = match t.arch {
@@ -173,21 +173,26 @@ pub fn test(t: &TestCase, bin_path: &PathBuf, rustfmt_bin_path: Option<&PathBuf>
173173
output.capture_outputs(
174174
true,
175175
"svd2rust",
176-
if t.arch != CortexM { Some(&lib_rs_file) } else { None }, // use Option.filter
176+
Some(&lib_rs_file).filter(|_| {
177+
(t.arch != CortexM) && (t.arch != Msp430)
178+
}),
177179
Some(&svd2rust_err_file),
178180
&[],
179181
)?;
180182
process_stderr_paths.push(svd2rust_err_file);
181183

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")?
184+
match t.arch {
185+
CortexM | Msp430 => {
186+
// TODO: Give error the path to stderr
187+
fs::rename(path_helper_base(&chip_dir, &["lib.rs"]), &lib_rs_file).chain_err(|| "While moving lib.rs file")?
188+
},
189+
_ => { }
185190
}
186191

187192
let rustfmt_err_file = path_helper_base(&chip_dir, &["rustfmt.err.log"]);
188193
if let Some(rustfmt_bin_path) = rustfmt_bin_path {
189194
// Run `cargo fmt`, capturing stderr to a log file
190-
195+
191196
let output = Command::new(rustfmt_bin_path)
192197
.arg(lib_rs_file)
193198
.output()

ci/svd2rust-regress/src/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4220,7 +4220,7 @@ pub const TESTS: &[&TestCase] = &[
42204220
arch: Msp430,
42214221
mfgr: TexasInstruments,
42224222
chip: "msp430g2553",
4223-
svd_url: Some("https://github.com/pftbest/msp430g2553/raw/v0.1.0/msp430g2553.svd"),
4223+
svd_url: Some("https://github.com/pftbest/msp430g2553/raw/v0.1.3-svd/msp430g2553.svd"),
42244224
should_pass: true,
42254225
run_when: Always,
42264226
},

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 {

src/lib.rs

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -71,35 +71,86 @@
7171
//! rt = ["cortex-m-rt/device"]
7272
//! ```
7373
//!
74-
//! ## target != cortex-m
74+
//! ## target = msp430
7575
//!
76-
//! When the target is msp430, riscv or none `svd2rust` will emit only the `lib.rs` file. Like in
76+
//! MSP430 does not natively use the SVD format. However, SVD files can be generated using the
77+
//! [`msp430_svd` application](https://github.com/pftbest/msp430_svd). Most header and DSLite
78+
//! files provided by TI are mirrored in the repository of `msp430_svd`.
79+
//!
80+
//! When targeting the MSP430 architecture `svd2rust` will _also_ generate three files in the
81+
//! current directory:
82+
//!
83+
//! - `build.rs`, build script that places `device.x` somewhere the linker can find.
84+
//! - `device.x`, linker script that weakly aliases all the interrupt handlers to the default
85+
//! exception handler (`DefaultHandler`).
86+
//! - `lib.rs`, the generated code.
87+
//!
88+
//! All these files must be included in the same device crate. The `lib.rs` file contains several
89+
//! inlined modules and its not formatted. It's recommend to split it out using the [`form`] tool
90+
//! and then format the output using `rustfmt` / `cargo fmt`:
91+
//!
92+
//! [`form`]: https://crates.io/crates/form
93+
//!
94+
//! ``` text
95+
//! $ msp430gen msp430g2553 > out.svd
96+
//!
97+
//! $ xmllint -format out.svd > msp430g2553.svd
98+
//!
99+
//! $ svd2rust --target=msp430 -i msp430g2553.svd
100+
//!
101+
//! $ rm -rf src
102+
//!
103+
//! $ form -i lib.rs -o src/ && rm lib.rs
104+
//!
105+
//! $ cargo fmt
106+
//! ```
107+
//!
108+
//! The resulting crate must provide an opt-in "rt" feature and depend on these crates:
109+
//! `bare-metal` v0.2.x, `msp430` v0.2.x, `msp430-rt` v0.2.x and `vcell` v0.1.x. Furthermore
110+
//! the "device" feature of `msp430-rt` must be enabled when the "rt" feature is enabled. The
111+
//! `Cargo.toml` of the device crate will look like this:
112+
//!
113+
//! ``` toml
114+
//! [dependencies]
115+
//! bare-metal = "0.2.0"
116+
//! msp430 = "0.2.0"
117+
//! vcell = "0.1.0"
118+
//!
119+
//! [dependencies.msp430-rt]
120+
//! optional = true
121+
//! version = "0.2.0"
122+
//!
123+
//! [features]
124+
//! rt = ["msp430-rt/device"]
125+
//! ```
126+
//!
127+
//! ## Other targets
128+
//!
129+
//! When the target is riscv or none `svd2rust` will emit only the `lib.rs` file. Like in
77130
//! the cortex-m case we recommend you use `form` and `rustfmt` on the output.
78131
//!
79132
//! The resulting crate must provide an opt-in "rt" feature and depend on these crates:
80133
//!
81134
//! - [`bare-metal`](https://crates.io/crates/bare-metal) v0.2.x
82135
//! - [`vcell`](https://crates.io/crates/vcell) v0.1.x
83-
//! - [`msp430`](https://crates.io/crates/msp430) v0.1.x if target = msp430.
84-
//! - [`msp430-rt`](https://crates.io/crates/msp430-rt) v0.1.x if target = msp430.
85136
//! - [`riscv`](https://crates.io/crates/riscv) v0.4.x if target = riscv.
86137
//! - [`riscv-rt`](https://crates.io/crates/riscv-rt) v0.4.x if target = riscv.
87138
//!
88139
//! The `*-rt` dependencies must be optional only enabled when the "rt" feature is enabled. The
89-
//! `Cargo.toml` of the device crate will look like this for an msp430 target:
140+
//! `Cargo.toml` of the device crate will look like this for a riscv target:
90141
//!
91142
//! ``` toml
92143
//! [dependencies]
93-
//! bare-metal = "0.1.0"
94-
//! msp430 = "0.1.0"
144+
//! bare-metal = "0.2.0"
145+
//! riscv = "0.4.0"
95146
//! vcell = "0.1.0"
96147
//!
97-
//! [dependencies.msp430-rt]
148+
//! [dependencies.riscv-rt]
98149
//! optional = true
99-
//! version = "0.1.0"
150+
//! version = "0.4.0"
100151
//!
101152
//! [features]
102-
//! rt = ["msp430-rt"]
153+
//! rt = ["riscv-rt"]
103154
//! ```
104155
//!
105156
//! # Peripheral API
@@ -418,8 +469,9 @@
418469
//!
419470
//! If the "rt" Cargo feature of the svd2rust generated crate is enabled the crate will populate the
420471
//! part of the vector table that contains the interrupt vectors and provide an
421-
//! [`interrupt!`](macro.interrupt.html) macro (non Cortex-M targets) or [`interrupt`] attribute
422-
//! (Cortex-M) that can be used to register interrupt handlers.
472+
//! [`interrupt!`](macro.interrupt.html) macro (non Cortex-M/MSP430 targets) or [`interrupt`] attribute
473+
//! (Cortex-M or [MSP430](https://docs.rs/msp430-rt-macros/0.1/msp430_rt_macros/attr.interrupt.html))
474+
//! that can be used to register interrupt handlers.
423475
//!
424476
//! [`interrupt`]: https://docs.rs/cortex-m-rt-macros/0.1/cortex_m_rt_macros/attr.interrupt.html
425477
//!
@@ -502,7 +554,7 @@ pub fn generate(xml: &str, target: Target, nightly: bool) -> Result<Generation>
502554

503555
/// Assigns a handler to an interrupt
504556
///
505-
/// **NOTE** The `interrupt!` macro on Cortex-M device crates is closer in syntax to the
557+
/// **NOTE** The `interrupt!` macro on Cortex-M and MSP430 device crates is closer in syntax to the
506558
/// [`exception!`] macro. This documentation doesn't apply to it. For the exact syntax of this macro
507559
/// check the documentation of the device crate you are using.
508560
///

src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ fn run() -> Result<()> {
109109
file.write_all(data.as_ref())
110110
.expect("Could not write code to lib.rs");
111111

112-
if target == Target::CortexM {
112+
if target == Target::CortexM || target == Target::Msp430 {
113113
writeln!(File::create("device.x").unwrap(), "{}", device_x).unwrap();
114114
writeln!(File::create("build.rs").unwrap(), "{}", build_rs()).unwrap();
115115
}

0 commit comments

Comments
 (0)