# [−] [src] Crate cortex_m_semihosting

Semihosting for ARM Cortex-M processors

# What is semihosting?

"Semihosting is a mechanism that enables code running on an ARM target to communicate and use the Input/Output facilities on a host computer that is running a debugger." - ARM

# Interface

This crate provides implementations of `core::fmt::Write`, so you can use it, in conjunction with `core::format_args!` or the `write!` macro, for user-friendly construction and printing of formatted strings.

Since semihosting operations are modeled as system calls, this crate exposes an untyped `syscall!` interface just like the `sc` crate does.

# Forewarning

Semihosting operations are very slow. Like, each WRITE operation can take hundreds of milliseconds.

# Example

## Using `hio::HStdout`

This example will demonstrate how to print formatted strings.

    extern crate cortex_m_semihosting;

    use cortex_m_semihosting::hio;
    use core::fmt::Write;

    // This function will be called by the application
    fn print() -> Result<(), core::fmt::Error> {
        let mut stdout = match hio::hstdout() {
            Ok(fd) => fd,
            Err(()) => return Err(core::fmt::Error),
        };

        let language = "Rust";
        let ranking = 1;

        write!(stdout, "{} on embedded is #{}!", language, ranking)?;

        Ok(())
    }

On the host side:

    $ openocd -f $INTERFACE -f $TARGET -l /tmp/openocd.log
    Open On-Chip Debugger 0.9.0 (2016-04-27-23:18)
    Licensed under GNU GPL v2
    For bug reports, read
            http://openocd.org/doc/doxygen/bugs.html
    # the command will block at this point

The OpenOCD logs will be redirected to `/tmp/openocd.log`. You can view those logs in "real time" using `tail`

    $ tail -f /tmp/openocd.log
    Info : Unable to match requested speed 1000 kHz, using 950 kHz
    Info : Unable to match requested speed 1000 kHz, using 950 kHz
    Info : clock speed 950 kHz
    Info : STLINK v1 JTAG v11 API v2 SWIM v0 VID 0x0483 PID 0x3744
    Info : using stlink api v2
    Info : nrf51.cpu: hardware has 4 breakpoints, 2 watchpoints

Alternatively you could omit the `-l` flag from the `openocd` call, and the `tail -f` command but the OpenOCD output will have intermingled in it logs from its normal operation.

Then, we run the program:

    $ arm-none-eabi-gdb hello-world
    (gdb) # Connect to OpenOCD
    (gdb) target remote :3333

    (gdb) # Enable OpenOCD's semihosting support
    (gdb) monitor arm semihosting enable

    (gdb) # Flash the program
    (gdb) load

    (gdb) # Run the program
    (gdb) continue

And you'll see the output under OpenOCD's terminal

    # openocd -f $INTERFACE -f $TARGET -l /tmp/openocd.log
    (..)
    Rust on embedded is #1!

## Using the syscall interface

This example will show how to print "Hello, world!" on the host.

Target program:

    extern crate cortex_m_semihosting;

    // This function will be called by the application
    fn print() {
        // File descriptor (on the host)
        const STDOUT: usize = 1; // NOTE the host stdout may not always be fd 1
        static MSG: &'static [u8] = b"Hello, world!\n";

        // Signature: fn write(fd: usize, ptr: *const u8, len: usize) -> usize
        let r = unsafe { syscall!(WRITE, STDOUT, MSG.as_ptr(), MSG.len()) };
    }

Output and monitoring proceed as in the above example.

# Optional features

## `inline-asm`

When this feature is enabled semihosting is implemented using inline assembly (`asm!`) and compiling this crate requires nightly.

When this feature is disabled semihosting is implemented using FFI calls into an external assembly file and compiling this crate works on stable and beta.

# Reference

For documentation about the semihosting operations, check:

'Chapter 8 - Semihosting' of the 'ARM Compiler toolchain Version 5.0' manual.

## Modules

debug | Interacting with debugging agent
hio | Host I/O
nr | Semihosting operations

## Macros

syscall | Variable argument version of `syscall`
syscall1 | Macro version of `syscall1`

## Functions

syscall ⚠ | Performs a semihosting operation, takes a pointer to an argument block
syscall1 ⚠ | Performs a semihosting operation, takes one integer as an argument

# Help

## Keyboard Shortcuts

`?`
  Show this help dialog
`S`
  Focus the search field
`↑`
  Move up in search results
`↓`
  Move down in search results
`↹`
  Switch tab
`⏎`
  Go to active search result
`+`
  Expand all sections
`-`
  Collapse all sections

## Search Tricks

Prefix searches with a type followed by a colon (e.g. `fn:`) to restrict the search to a given type.

Accepted types are: `fn`, `mod`, `struct`, `enum`, `trait`, `type`, `macro`, and `const`.

Search functions by type signature (e.g. `vec -> usize` or `* -> vec`)

Search multiple things at once by splitting your query with comma (e.g. `str,u8` or `String,struct:Vec,test`)