diff options
author | 2020-10-13 23:32:15 +0000 | |
---|---|---|
committer | 2020-10-13 23:32:15 +0000 | |
commit | 432e5f527430394570d1d07454e26cc41d5b2936 (patch) | |
tree | d3cde25a18eabfc5f0342dbf2d31ab767f21bab9 /cortex-m-semihosting/src/debug.rs | |
parent | f77d64a2d1505335e4a170d03a40993bb066fd02 (diff) | |
parent | b51178fae6373d8dae95f2fb661e0635359e8bc0 (diff) | |
download | cortex-m-432e5f527430394570d1d07454e26cc41d5b2936.tar.gz cortex-m-432e5f527430394570d1d07454e26cc41d5b2936.tar.zst cortex-m-432e5f527430394570d1d07454e26cc41d5b2936.zip |
Merge #263p-sh-v0.5.3c-m-sh-v0.3.5
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>
Diffstat (limited to 'cortex-m-semihosting/src/debug.rs')
-rw-r--r-- | cortex-m-semihosting/src/debug.rs | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/cortex-m-semihosting/src/debug.rs b/cortex-m-semihosting/src/debug.rs new file mode 100644 index 0000000..a4fa6d8 --- /dev/null +++ b/cortex-m-semihosting/src/debug.rs @@ -0,0 +1,96 @@ +//! Interacting with debugging agent +//! +//! # Example +//! +//! This example will show how to terminate the QEMU session. The program +//! should be running under QEMU with semihosting enabled +//! (use `-semihosting` flag). +//! +//! Target program: +//! +//! ```no_run +//! use cortex_m_semihosting::debug::{self, EXIT_SUCCESS, EXIT_FAILURE}; +//! +//! fn main() { +//! if 2 == 2 { +//! // report success +//! debug::exit(EXIT_SUCCESS); +//! } else { +//! // report failure +//! debug::exit(EXIT_FAILURE); +//! } +//! } +//! + +/// This values are taken from section 5.5.2 of +/// ADS Debug Target Guide (DUI0058). +// TODO document +#[allow(missing_docs)] +pub enum Exception { + // Hardware reason codes + BranchThroughZero = 0x20000, + UndefinedInstr = 0x20001, + SoftwareInterrupt = 0x20002, + PrefetchAbort = 0x20003, + DataAbort = 0x20004, + AddressException = 0x20005, + IRQ = 0x20006, + FIQ = 0x20007, + // Software reason codes + BreakPoint = 0x20020, + WatchPoint = 0x20021, + StepComplete = 0x20022, + RunTimeErrorUnknown = 0x20023, + InternalError = 0x20024, + UserInterruption = 0x20025, + ApplicationExit = 0x20026, + StackOverflow = 0x20027, + DivisionByZero = 0x20028, + OSSpecific = 0x20029, +} + +/// Status enum for `exit` syscall. +pub type ExitStatus = Result<(), ()>; + +/// Successful execution of a program. +pub const EXIT_SUCCESS: ExitStatus = Ok(()); + +/// Unsuccessful execution of a program. +pub const EXIT_FAILURE: ExitStatus = Err(()); + +/// Reports to the debugger that the execution has completed. +/// +/// This call can be used to terminate QEMU session and report back success +/// or failure. If you need to pass more than one type of error, consider +/// using `report_exception` syscall instead. +/// +/// This call should not return. However, it is possible for the debugger +/// to request that the application continue. In that case this call +/// returns normally. +/// +pub fn exit(status: ExitStatus) { + match status { + EXIT_SUCCESS => report_exception(Exception::ApplicationExit), + EXIT_FAILURE => report_exception(Exception::RunTimeErrorUnknown), + } +} + +/// Report an exception to the debugger directly. +/// +/// Exception handlers can use this SWI at the end of handler chains +/// as the default action, to indicate that the exception has not been handled. +/// +/// This call should not return. However, it is possible for the debugger +/// to request that the application continue. In that case this call +/// returns normally. +/// +/// # Arguments +/// +/// * `reason` - A reason code reported back to the debugger. +/// +pub fn report_exception(reason: Exception) { + let code = reason as usize; + unsafe { + syscall1!(REPORT_EXCEPTION, code); + } +} |