Skip to content

Commit 432e5f5

Browse files
Merge #263
263: Import cortex-m-semihosting and panic-semihosting into this repo r=adamgreig a=jonas-schievink Motivation: * Allows writing QEMU tests for `cortex-m`'s functionality that use semihosting to control QEMU. Previously these crates would pull in another cortex-m version, which doesn't work. Now they have a `path` dependency on the root crate. * Lets us share the outline-inline-assembly setup and `cargo-xtask` in general. * Lets us share CI and bot setup between more crates. * 2 fewer repos to triage and keep track of (I'll transfer their issues after this is merged). I also want to import cortex-m-rt, but I'll do that in a later PR. CI was updated to build-test all crates with all or most feature combinations, like it did before. Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
2 parents f77d64a + b51178f commit 432e5f5

32 files changed

+1146
-25
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ inline-asm = []
2727
linker-plugin-lto = []
2828

2929
[workspace]
30-
members = ["xtask"]
30+
members = ["xtask", "cortex-m-semihosting", "panic-semihosting"]
3131

3232
[package.metadata.docs.rs]
3333
targets = [

asm/inline.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,13 @@ pub unsafe fn __wfi() {
175175
asm!("wfi");
176176
}
177177

178+
/// Semihosting syscall.
179+
#[inline(always)]
180+
pub unsafe fn __syscall(mut nr: u32, arg: u32) -> u32 {
181+
asm!("bkpt #0xab", inout("r0") nr, in("r1") arg);
182+
nr
183+
}
184+
178185
// v7m *AND* v8m.main, but *NOT* v8m.base
179186
#[cfg(any(armv7m, armv8m_main))]
180187
pub use self::v7m::*;

asm/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ macro_rules! shims {
4646
pub unsafe extern "C" fn $name(
4747
$($arg: $argty),*
4848
) $(-> $ret)? {
49-
crate::inline::$name($($arg)*)
49+
crate::inline::$name($($arg),*)
5050
}
5151
)+
5252
};
@@ -72,9 +72,10 @@ shims! {
7272
fn __udf();
7373
fn __wfe();
7474
fn __wfi();
75+
fn __syscall(nr: u32, arg: u32) -> u32;
7576
}
7677

77-
// v7m *AND* v8m.main, but *NOT* v8m.base
78+
// v7m *AND* v8m.main, but *NOT* v8m.base
7879
#[cfg(any(armv7m, armv8m_main))]
7980
shims! {
8081
fn __basepri_max(val: u8);

bin/thumbv6m-none-eabi-lto.a

608 Bytes
Binary file not shown.

bin/thumbv6m-none-eabi.a

640 Bytes
Binary file not shown.

bin/thumbv7em-none-eabi-lto.a

640 Bytes
Binary file not shown.

bin/thumbv7em-none-eabi.a

640 Bytes
Binary file not shown.

bin/thumbv7em-none-eabihf-lto.a

652 Bytes
Binary file not shown.

bin/thumbv7em-none-eabihf.a

640 Bytes
Binary file not shown.

bin/thumbv7m-none-eabi-lto.a

632 Bytes
Binary file not shown.

bin/thumbv7m-none-eabi.a

640 Bytes
Binary file not shown.

bin/thumbv8m.base-none-eabi-lto.a

612 Bytes
Binary file not shown.

bin/thumbv8m.base-none-eabi.a

628 Bytes
Binary file not shown.

bin/thumbv8m.main-none-eabi-lto.a

584 Bytes
Binary file not shown.

bin/thumbv8m.main-none-eabi.a

628 Bytes
Binary file not shown.

bin/thumbv8m.main-none-eabihf-lto.a

588 Bytes
Binary file not shown.

bin/thumbv8m.main-none-eabihf.a

624 Bytes
Binary file not shown.

cortex-m-semihosting/CHANGELOG.md

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# Change Log
2+
3+
All notable changes to this project will be documented in this file.
4+
This project adheres to [Semantic Versioning](http://semver.org/).
5+
6+
## [Unreleased]
7+
8+
## [v0.3.5] - 2019-08-29
9+
10+
### Added
11+
12+
- Adds a feature to work around JLink quirks
13+
- Adds a dbg! macro using heprintln
14+
- Added thumbv8m.main support on stable
15+
16+
### Fixed
17+
18+
- Now Rust 2018 edition
19+
20+
## [v0.3.4] - 2019-08-13
21+
22+
### Fixed
23+
24+
- Support for thumbv8 mainline hf target
25+
26+
## [v0.3.3] - 2019-04-22
27+
28+
### Added
29+
30+
- Adds support for thumbv8 and cortex-m v0.6.0
31+
32+
## [v0.3.2] - 2018-11-04
33+
34+
### Added
35+
36+
- Added a family of `hprint` macros for printing to the host standard output /
37+
error via globally shared `HStdout` / `HStderr` handles .
38+
39+
## [v0.3.1] - 2018-08-27
40+
41+
### Changed
42+
43+
- This crate no longer depends on `arm-none-eabi-gcc`.
44+
45+
## [v0.3.0] - 2018-05-10
46+
47+
### Changed
48+
49+
- [breaking-change] `inline-asm` is no longer a default feature (i.e. a feature that's enabled by
50+
default). The consequence is that this crate now compiles on 1.27 (beta) by default, and opting
51+
into `inline-asm` requires nightly.
52+
53+
## [v0.2.1] - 2018-04-25
54+
55+
### Added
56+
57+
- An opt-out "inline-asm" Cargo feature. When this feature is disabled semihosting is implemented
58+
using an external assembly file instead of using the unstable inline assembly (`asm!`) feature
59+
meaning that this crate can be compiled on stable.
60+
61+
## [v0.2.0] - 2017-07-07
62+
63+
### Added
64+
65+
- `exit` and `report_exception` syscalls
66+
67+
- `HStdout` and `HStderr` structs that represent handles to the host stdout and
68+
stderr stream respectively.
69+
70+
### Changed
71+
72+
- [breaking-change] The `io` module has been renamed to `hio` to reflect that
73+
this is I/O *on the host*.
74+
75+
### Removed
76+
77+
- [breaking-change] the family of `write` functions in the `io` module. Instead
78+
use `HStdout` / `HStderr` and its `write_all` method and `fmt::Write`
79+
implementation.
80+
81+
- [breaking-change] the `hprint!` family of macros. Instead use `HStdout` and
82+
the standard `write!` macro.
83+
84+
## [v0.1.3] - 2017-02-27
85+
86+
### Added
87+
88+
- A family of `ewrite` functions and `ehprint!` macros to write to the host's
89+
stderr.
90+
91+
### Fixed
92+
93+
- `write_all` logic when a single write doesn't write all the buffer bytes
94+
95+
## [v0.1.2] - 2017-02-15
96+
97+
### Fixed
98+
99+
- the `hprintln!` macro when called without arguments.
100+
101+
## [v0.1.1] - 2017-01-22
102+
103+
### Added
104+
105+
- Expose a family of `write` functions to write to the host's stdout without
106+
going through the `hprint!` macros.
107+
108+
## v0.1.0 - 2017-01-22
109+
110+
- Initial release
111+
112+
[Unreleased]: https://github.com/rust-embedded/cortex-m-semihosting/compare/v0.3.5...HEAD
113+
[v0.3.5]: https://github.com/rust-embedded/cortex-m-semihosting/compare/v0.3.4...v0.3.5
114+
[v0.3.4]: https://github.com/rust-embedded/cortex-m-semihosting/compare/v0.3.3...v0.3.4
115+
[v0.3.3]: https://github.com/rust-embedded/cortex-m-semihosting/compare/v0.3.2...v0.3.3
116+
[v0.3.2]: https://github.com/rust-embedded/cortex-m-semihosting/compare/v0.3.1...v0.3.2
117+
[v0.3.1]: https://github.com/rust-embedded/cortex-m-semihosting/compare/v0.3.0...v0.3.1
118+
[v0.3.0]: https://github.com/rust-embedded/cortex-m-semihosting/compare/v0.2.1...v0.3.0
119+
[v0.2.1]: https://github.com/rust-embedded/cortex-m-semihosting/compare/v0.2.0...v0.2.1
120+
[v0.2.0]: https://github.com/rust-embedded/cortex-m-semihosting/compare/v0.1.3...v0.2.0
121+
[v0.1.3]: https://github.com/rust-embedded/cortex-m-semihosting/compare/v0.1.2...v0.1.3
122+
[v0.1.2]: https://github.com/rust-embedded/cortex-m-semihosting/compare/v0.1.1...v0.1.2
123+
[v0.1.1]: https://github.com/rust-embedded/cortex-m-semihosting/compare/v0.1.0...v0.1.1

cortex-m-semihosting/Cargo.toml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[package]
2+
authors = [
3+
"The Cortex-M Team <cortex-m@teams.rust-embedded.org>",
4+
"Jorge Aparicio <japaricious@gmail.com>",
5+
]
6+
description = "Semihosting for ARM Cortex-M processors"
7+
documentation = "https://docs.rs/cortex-m-semihosting"
8+
keywords = ["semihosting", "arm", "cortex-m"]
9+
license = "MIT OR Apache-2.0"
10+
name = "cortex-m-semihosting"
11+
readme = "README.md"
12+
repository = "https://github.com/rust-embedded/cortex-m"
13+
version = "0.3.5"
14+
edition = "2018"
15+
16+
[features]
17+
inline-asm = []
18+
jlink-quirks = []
19+
no-semihosting = []
20+
21+
[dependencies]
22+
cortex-m = { path = "..", version = ">= 0.5.8, < 0.7" }

cortex-m-semihosting/README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
[![crates.io](https://img.shields.io/crates/v/cortex-m-semihosting.svg)](https://crates.io/crates/cortex-m-semihosting)
2+
[![crates.io](https://img.shields.io/crates/d/cortex-m-semihosting.svg)](https://crates.io/crates/cortex-m-semihosting)
3+
4+
# `cortex-m-semihosting`
5+
6+
> Semihosting for ARM Cortex-M processors
7+
8+
This project is developed and maintained by the [Cortex-M team][team].
9+
10+
## [Documentation](https://docs.rs/cortex-m-semihosting)
11+
12+
# Minimum Supported Rust Version (MSRV)
13+
14+
This crate is guaranteed to compile on stable Rust 1.33.0 and up. It *might*
15+
compile with older versions but that may change in any new patch release.
16+
17+
## License
18+
19+
Licensed under either of
20+
21+
- Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or
22+
http://www.apache.org/licenses/LICENSE-2.0)
23+
- MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT)
24+
25+
at your option.
26+
27+
### Contribution
28+
29+
Unless you explicitly state otherwise, any contribution intentionally submitted
30+
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
31+
dual licensed as above, without any additional terms or conditions.
32+
33+
## Code of Conduct
34+
35+
Contribution to this crate is organized under the terms of the [Rust Code of
36+
Conduct][CoC], the maintainer of this crate, the [Cortex-M team][team], promises
37+
to intervene to uphold that code of conduct.
38+
39+
[CoC]: ../CODE_OF_CONDUCT.md
40+
[team]: https://github.com/rust-embedded/wg#the-cortex-m-team

cortex-m-semihosting/build.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use std::path::PathBuf;
2+
use std::{env, fs};
3+
4+
fn main() {
5+
let target = env::var("TARGET").unwrap();
6+
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
7+
let name = env::var("CARGO_PKG_NAME").unwrap();
8+
9+
if target.starts_with("thumbv") {
10+
if env::var_os("CARGO_FEATURE_INLINE_ASM").is_none() {
11+
fs::copy(
12+
format!("../bin/{}.a", target),
13+
out_dir.join(format!("lib{}.a", name)),
14+
)
15+
.unwrap();
16+
17+
println!("cargo:rustc-link-lib=static={}", name);
18+
println!("cargo:rustc-link-search={}", out_dir.display());
19+
}
20+
21+
println!("cargo:rustc-cfg=thumb");
22+
}
23+
}

cortex-m-semihosting/src/debug.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
//! Interacting with debugging agent
2+
//!
3+
//! # Example
4+
//!
5+
//! This example will show how to terminate the QEMU session. The program
6+
//! should be running under QEMU with semihosting enabled
7+
//! (use `-semihosting` flag).
8+
//!
9+
//! Target program:
10+
//!
11+
//! ```no_run
12+
//! use cortex_m_semihosting::debug::{self, EXIT_SUCCESS, EXIT_FAILURE};
13+
//!
14+
//! fn main() {
15+
//! if 2 == 2 {
16+
//! // report success
17+
//! debug::exit(EXIT_SUCCESS);
18+
//! } else {
19+
//! // report failure
20+
//! debug::exit(EXIT_FAILURE);
21+
//! }
22+
//! }
23+
//!
24+
25+
/// This values are taken from section 5.5.2 of
26+
/// ADS Debug Target Guide (DUI0058).
27+
// TODO document
28+
#[allow(missing_docs)]
29+
pub enum Exception {
30+
// Hardware reason codes
31+
BranchThroughZero = 0x20000,
32+
UndefinedInstr = 0x20001,
33+
SoftwareInterrupt = 0x20002,
34+
PrefetchAbort = 0x20003,
35+
DataAbort = 0x20004,
36+
AddressException = 0x20005,
37+
IRQ = 0x20006,
38+
FIQ = 0x20007,
39+
// Software reason codes
40+
BreakPoint = 0x20020,
41+
WatchPoint = 0x20021,
42+
StepComplete = 0x20022,
43+
RunTimeErrorUnknown = 0x20023,
44+
InternalError = 0x20024,
45+
UserInterruption = 0x20025,
46+
ApplicationExit = 0x20026,
47+
StackOverflow = 0x20027,
48+
DivisionByZero = 0x20028,
49+
OSSpecific = 0x20029,
50+
}
51+
52+
/// Status enum for `exit` syscall.
53+
pub type ExitStatus = Result<(), ()>;
54+
55+
/// Successful execution of a program.
56+
pub const EXIT_SUCCESS: ExitStatus = Ok(());
57+
58+
/// Unsuccessful execution of a program.
59+
pub const EXIT_FAILURE: ExitStatus = Err(());
60+
61+
/// Reports to the debugger that the execution has completed.
62+
///
63+
/// This call can be used to terminate QEMU session and report back success
64+
/// or failure. If you need to pass more than one type of error, consider
65+
/// using `report_exception` syscall instead.
66+
///
67+
/// This call should not return. However, it is possible for the debugger
68+
/// to request that the application continue. In that case this call
69+
/// returns normally.
70+
///
71+
pub fn exit(status: ExitStatus) {
72+
match status {
73+
EXIT_SUCCESS => report_exception(Exception::ApplicationExit),
74+
EXIT_FAILURE => report_exception(Exception::RunTimeErrorUnknown),
75+
}
76+
}
77+
78+
/// Report an exception to the debugger directly.
79+
///
80+
/// Exception handlers can use this SWI at the end of handler chains
81+
/// as the default action, to indicate that the exception has not been handled.
82+
///
83+
/// This call should not return. However, it is possible for the debugger
84+
/// to request that the application continue. In that case this call
85+
/// returns normally.
86+
///
87+
/// # Arguments
88+
///
89+
/// * `reason` - A reason code reported back to the debugger.
90+
///
91+
pub fn report_exception(reason: Exception) {
92+
let code = reason as usize;
93+
unsafe {
94+
syscall1!(REPORT_EXCEPTION, code);
95+
}
96+
}

0 commit comments

Comments
 (0)