mirror of
https://github.com/nkbai/book.git
synced 2026-09-05 22:14:54 +08:00
getting started: add semihosting section
This commit is contained in:
@@ -22,6 +22,7 @@ more information and coordination
|
||||
- [QEMU](./start/qemu.md)
|
||||
- [Hardware](./start/hardware.md)
|
||||
- [Memory-mapped Registers](./start/registers.md)
|
||||
- [Semihosting](./start/semihosting.md)
|
||||
- [Panicking](./start/panicking.md)
|
||||
- [Exceptions](./start/exceptions.md)
|
||||
- [IO](./start/io.md)
|
||||
|
||||
128
src/start/semihosting.md
Normal file
128
src/start/semihosting.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# Semihosting
|
||||
|
||||
Semihosting is a mechanism that lets embedded devices do I/O on the host and is
|
||||
mainly used to log messages to the host console. Semihosting requires a debug
|
||||
session and pretty much nothing else (no extra wires!) so it's super convenient
|
||||
to use. The downside is that it's super slow: each write operation can take
|
||||
several milliseconds depending on the hardware debugger (e.g. ST-Link) you use.
|
||||
|
||||
The [`cortex-m-semihosting`] crate provides an API to do semihosting operations
|
||||
on Cortex-M devices. The program below is the semihosting version of "Hello,
|
||||
world!":
|
||||
|
||||
[`cortex-m-semihosting`]: https://crates.io/crates/cortex-m-semihosting
|
||||
|
||||
``` rust
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate panic_halt;
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use cortex_m_semihosting::hprintln;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
hprintln!("Hello, world!").unwrap();
|
||||
|
||||
loop {}
|
||||
}
|
||||
```
|
||||
|
||||
If you run this program on hardware you'll see the "Hello, world!" message
|
||||
within the OpenOCD logs.
|
||||
|
||||
``` console
|
||||
$ openocd
|
||||
(..)
|
||||
Hello, world!
|
||||
(..)
|
||||
```
|
||||
|
||||
QEMU understands semihosting operations so the above program will also work with
|
||||
`qemu-system-arm` without having to start a debug session. Note that you'll
|
||||
need to pass the `-semihosting-config` flag to QEMU to enable semihosting
|
||||
support; these flags are already included in the `.cargo/config` file of the
|
||||
template.
|
||||
|
||||
``` console
|
||||
$ # this program will block the terminal
|
||||
$ cargo run
|
||||
Running `qemu-system-arm (..)
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
There's also an `exit` semihosting operation that can be used to terminate the
|
||||
QEMU process. Important: do **not** use `debug::exit` on hardware; this function
|
||||
can corrupt your OpenOCD session and you will not be able to debug more programs
|
||||
until you restart it.
|
||||
|
||||
``` rust
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate panic_halt;
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use cortex_m_semihosting::debug;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let roses = "blue";
|
||||
|
||||
if roses == "red" {
|
||||
debug::exit(debug::EXIT_SUCCESS);
|
||||
} else {
|
||||
debug::exit(debug::EXIT_FAILURE);
|
||||
}
|
||||
|
||||
loop {}
|
||||
}
|
||||
```
|
||||
|
||||
``` console
|
||||
$ cargo run
|
||||
Running `qemu-system-arm (..)
|
||||
|
||||
$ echo $?
|
||||
1
|
||||
```
|
||||
|
||||
One last tip: you can set the panicking behavior to `exit(EXIT_FAILURE)`. This
|
||||
will let you write `no_std` run-pass tests that you can run on QEMU.
|
||||
|
||||
For convenience, the `panic-semihosting` crate has an "exit" feature that when
|
||||
enabled invokes `exit(EXIT_FAILURE)` after logging the panic message to the host
|
||||
stderr.
|
||||
|
||||
``` rust
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate panic_semihosting; // features = ["exit"]
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use cortex_m_semihosting::debug;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let roses = "blue";
|
||||
|
||||
assert_eq!(roses, "red");
|
||||
|
||||
loop {}
|
||||
}
|
||||
```
|
||||
|
||||
``` console
|
||||
$ cargo run
|
||||
Running `qemu-system-arm (..)
|
||||
panicked at 'assertion failed: `(left == right)`
|
||||
left: `"blue"`,
|
||||
right: `"red"`', examples/hello.rs:15:5
|
||||
|
||||
$ echo $?
|
||||
1
|
||||
```
|
||||
Reference in New Issue
Block a user