半主机
半主机是这样一种机制,它允许嵌入式设备在主机上执行I/O操作,主要用于将消息记录输出到主机控制台。半主机除了需要调试会话之外,几乎不需要其他任何操作(不需要额外的接线!),因此使用起来超级方便。缺点是它非常慢:根据您使用的硬件调试器不同(例如ST-Link),每个写入操作可能要花费几毫秒。
cortex-m-semihosting crate提供了一个API,可以在Cortex-M设备上进行半主机操作。下面的程序是“ Hello,world!”的半主机版本:
#![no_main]
#![no_std]
extern crate panic_halt;
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一起使用,而无需启动调试会话。注意,您需要将-semihosting-config参数传递给QEMU以启用半主机支持。这些参数已经包含在模板的cargo/config文件中。
$ # this program will block the terminal
$ cargo run
Running `qemu-system-arm (..)
Hello, world!
还有一个exit半主机操作可用于终止QEMU进程。重要提示:不要在硬件上使用debug::exit;此功能可能会破坏您的OpenOCD会话,并且只有重新启动它才能调试更多程序。
#![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 {}
}
$ cargo run
Running `qemu-system-arm (..)
$ echo $?
1
最后一个提示:您可以将恐慌行为设置为exit(EXIT_FAILURE)。这将使您编写可以在QEMU上运行的no_std测试案例。
为方便起见,panic-semihostingcrate具有“退出”功能,启用后,会将panic消息记录到主机stderr后调用exit(EXIT_FAILURE)。
#![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 {}
}
$ 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上启用此功能,请在您的Cargo.toml依赖项部分中编辑panic-semihosting:
panic-semihosting = { version = "VERSION", features = ["exit"] }
其中VERSION 是所需的版本。有关依赖项功能的更多信息,请参阅《Cargo手册》中的specifying dependencies部分。