Semihosting

Semihosting is a feature which allows targets without I/O support to use the I/O of the host. When the special BKPT instruction is reached, the host reads the characters directly from the micro:bit's memory.

Semihosting is slow

The most important thing to remember about semihosting is that it is slow. The processor halts entirely for each operation, making each operation take 107 milliseconds. This means that if you are doing any time sensitive work, you should not use it for logging. Check out this blog post for more information.

GDB

The first thing to do is to enable semihosting in GDB. As before, we will add this to .gdbinit to avoid typing it every time.

.gdbinit

target remote :3333
monitor arm semihosting enable
load

OpenOCD

You may have incorrectly assumed at this point that the outpust would appear in GDB. Remember that GDB simply connects to OpenOCD to interface with the micro:bit. OpenOCD is very loud currently, so it will be quite hard to see the output of our micro:bit in the noise. Fix this by stopping and restarting it with logging dumped to a file.

openocd -f interface/cmsis-dap.cfg -f target/nrf51.cfg -l /tmp/openocd.log

Panic

The easiest way to use semihosting is to use it for the panic! macro.

Cargo.toml

panic-semihosting = ""

You can then see what happens if you add a panic! to your code:

fn main() -> ! {
    panic!("test-panic");
}
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
panicked at 'test-panic', src/hello-world/src/main.rs:27:5

stdout

Finally, this is how to write to stdout.


# #![allow(unused_variables)]
#fn main() {
extern crate cortex_m_semihosting as sh;
use core::fmt::Write;
use sh::hio;
// -- snip --
    let mut stdout = hio::hstdout().unwrap();
    stdout.write_str("semitest\n\r").unwrap();
    // or
    writeln!(hio::hstdout().unwrap(), "Init").unwrap();
#}

Writing to stderr is just as easy.