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

セミホスティング

セミホスティングは、組み込みデバイスがホスト上で I/O を行えるようにする 仕組みで、主にホストのコンソールにメッセージをログ出力するために使われます。 セミホスティングに必要なのはデバッグセッションと、ほかにはほとんど何もありません (追加の配線も不要です!)ので、とても手軽に使えます。欠点は非常に遅いことです。 書き込み操作のたびに、使用するハードウェアデバッガ(例: ST-Link)によっては 数ミリ秒かかることがあります。

cortex-m-semihosting クレートは、Cortex-M デバイス上でセミホスティング操作を 行うための API を提供します。以下のプログラムは、「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 {}
}

このプログラムを実機で実行すると、OpenOCD のログ内に “Hello, world!” メッセージが表示されます。

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

ただし、最初に GDB から OpenOCD でセミホスティングを有効にする必要があります:

(gdb) monitor arm semihosting enable
semihosting is enabled

QEMU はセミホスティング操作を理解するので、上のプログラムは デバッグセッションを開始しなくても qemu-system-arm でも動作します。なお、 セミホスティングのサポートを有効にするには、QEMU に -semihosting-config フラグを渡す必要があります。これらのフラグは、テンプレートの .cargo/config.toml ファイルにすでに含まれています。

$ # このプログラムはターミナルをブロックします
$ cargo run
     Running `qemu-system-arm (..)
Hello, world!

QEMU プロセスを終了するために使用できる exit セミホスティング操作もあります。 重要: 実機では debug::exit決して 使用しないでください。この関数は OpenOCD セッションを壊す可能性があり、再起動するまでそれ以上プログラムを デバッグできなくなります。

#![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

最後にもう 1 つヒントです: panic 時の動作を exit(EXIT_FAILURE) に設定できます。これに より、QEMU 上で実行できる no_std の run-pass テストを書けるようになります。

利便性のために、panic-semihosting クレートには “exit” feature があり、これを 有効にすると panic メッセージをホストの stderr に記録したあとで exit(EXIT_FAILURE) を呼び出します。

#![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

: panic-semihosting でこの feature を有効にするには、 panic-semihosting を指定している Cargo.toml の依存関係セクションを次のように 編集してください:

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

ここで VERSION は必要なバージョンです。依存関係の feature について詳しくは、 Cargo book の specifying dependencies セクションを参照してください。