Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Semihosting

Semihosting ist ein Mechanismus, der es eingebetteten Systemen ermöglicht, Ein-/Ausgabeoperationen über den eigenen Rechner (Host) durchzuführen; er wird hauptsächlich dazu genutzt, Meldungen auf der Host-Konsole zu protokollieren. Da Semihosting lediglich eine Debug-Sitzung und sonst so gut wie nichts (keine zusätzlichen Kabel!) erfordert, ist es äußerst komfortabel in der Anwendung. Der Nachteil ist jedoch die sehr geringe Geschwindigkeit: Je nach verwendetem Hardware-Debugger (z. B. ST-Link) kann jeder Schreibvorgang mehrere Millisekunden in Anspruch nehmen.

Das cortex-m-semihosting-Crate stellt eine API für Semihosting-Operationen auf Cortex-M-Geräten bereit. Das folgende Programm ist die Semihosting-Version von „Hello, world!“:

#![no_main]
#![no_std]

use panic_halt as _;

use cortex_m_rt::entry;
use cortex_m_semihosting::hprintln;

#[entry]
fn main() -> ! {
    hprintln!("Hello, world!").unwrap();

    loop {}
}

Wenn Sie dieses Programm auf der Hardware ausführen, sehen Sie die Meldung „Hello, world!“ in den OpenOCD-Protokollen.

$ openocd
(..)
Hello, world!
(..)

Sie müssen zunächst Semihosting in OpenOCD über GDB aktivieren:

(gdb) monitor arm semihosting enable
semihosting is enabled

QEMU unterstützt Semihosting-Operationen, sodass das obige Programm auch mit qemu-system-arm funktioniert, ohne dass eine Debug-Sitzung gestartet werden muss. Beachten Sie, dass Sie QEMU die Option -semihosting-config übergeben müssen, um die Semihosting-Unterstützung zu aktivieren; diese Optionen sind bereits in der Datei .cargo/config.toml der Vorlage enthalten.

$ # Dieses Programm wird das Terminal blockieren.
$ cargo run
     Running `qemu-system-arm (..)
Hello, world!

Es gibt auch eine exit-Semihosting-Operation, mit der sich der QEMU-Prozess beenden lässt. Wichtig: Verwenden Sie debug::exit nicht auf echter Hardware; diese Funktion kann Ihre OpenOCD-Sitzung beschädigen, sodass Sie keine weiteren Programme mehr debuggen können, bis Sie die Sitzung neu starten.

#![no_main]
#![no_std]

use panic_halt as _;

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 {}
}
$ cargo run
     Running `qemu-system-arm (..)

$ echo $?
1

Ein letzter Tipp: Du kannst das Verhalten bei einem Panic auf exit(EXIT_FAILURE) einstellen. Dadurch lassen sich no_std-Tests schreiben, die erfolgreich durchlaufen und unter QEMU ausgeführt werden können.

Praktischerweise bietet der panic-semihosting-Crate ein „exit“-Feature an; ist dieses aktiviert, wird exit(EXIT_FAILURE) aufgerufen, nachdem die Panic-Meldung auf dem stderr des Hosts ausgegeben wurde.

#![no_main]
#![no_std]

use panic_semihosting as _; // features = ["exit"]

use cortex_m_rt::entry;
use cortex_m_semihosting::debug;

#[entry]
fn main() -> ! {
    let roses = "blue";

    assert_eq!(roses, "red");

    loop {}
}
$ cargo run
     Running `qemu-system-arm (..)
panicked at 'assertion failed: `(left == right)`
  left: `"blue"`,
 right: `"red"`', examples/hello.rs:15:5

$ echo $?
1

HINWEIS: Um diese Funktion für panic-semihosting zu aktivieren, bearbeiten Sie den Abschnitt „dependencies“ in Ihrer Cargo.toml, in dem panic-semihosting wie folgt angegeben ist:

panic-semihosting = { version = "VERSION", features = ["exit"] }

wobei VERSION für die gewünschte Version steht. Weitere Informationen zu Abhängigkeiten und Funktionen finden Sie im Abschnitt “specifying dependencies” des Cargo-Buchs.