#stdio #qemu #arm #io #risc-v #host #xtensa

nightly no-std 半宿主模式

适用于 AArch64、ARM、RISC-V、MIPS32、MIPS64 和 Xtensa 的半宿主模式

14 个版本

新版本 0.1.14 2024 年 8 月 23 日
0.1.13 2024 年 7 月 22 日
0.1.11 2024 年 6 月 16 日
0.1.7 2024 年 3 月 21 日
0.1.0 2023 年 3 月 22 日

#20嵌入式开发

Download history 837/week @ 2024-05-03 560/week @ 2024-05-10 1109/week @ 2024-05-17 2228/week @ 2024-05-24 1457/week @ 2024-05-31 1397/week @ 2024-06-07 1548/week @ 2024-06-14 1815/week @ 2024-06-21 2019/week @ 2024-06-28 1975/week @ 2024-07-05 3138/week @ 2024-07-12 3535/week @ 2024-07-19 3575/week @ 2024-07-26 3244/week @ 2024-08-02 5519/week @ 2024-08-09 4403/week @ 2024-08-16

17,438 每月下载量
用于 4 个 crate (2 个直接使用)

Apache-2.0 或 MIT 协议

175KB
3K SLoC

半宿主模式

crates.io docs.rs license msrv github actions

适用于 AArch64、ARM、RISC-V、MIPS32、MIPS64 和 Xtensa 的半宿主模式。

此库提供了对半宿主模式的访问,半宿主模式是一种机制,允许在真实或虚拟(例如 QEMU)目标上运行的程序与主机系统上的 I/O 设施进行通信。有关半宿主模式的更多信息,请参阅 ARM 文档

API 分为以下四种类型

  • 顶级 API (semihosting::{io,fs,..}) 提供了标准库中类似 API 的子集。

    • io:提供无 std io 特性和 std{in,out,err}。(std{in,out,err} 需要 stdio 功能,其他都是无条件提供的)
    • fs:提供操作主机文件系统内容的方法。(需要 fs 功能)
    • process:提供 abortexit
    • dbg!/print{,ln}!/eprint{,ln}!:将输出到 stdout/stderr 的宏。(需要 stdio 功能)

    请注意,某些 API 并不是严格的标准库子集。

    • 使用在 core 中不可用的类型(例如 Path)的 API(技术上,可以实现相同的功能,但直接使用 CStr 更有意义,因为将长的 Path/OsStr 转换为 CStr 时,需要进行分配或返回错误)。
    • std 中失败时引发恐慌的 API(在没有 std 的环境中,由于默认 panic=abort,返回 Result 是有意义的)。
  • 当使用此库时很有用的辅助函数。

    • c!CStr 文字面量宏。(自 Rust 1.77 以来,该宏已被软弃用,转而使用 C 字符串文字(c"..."))。
  • 提供对特定平台半主机接口的低级访问的 semihosting::sys 模块。

  • 提供实验性 API 的 semihosting::experimental 模块。更多信息请参阅 可选功能

此外,此库还提供半主机恐慌处理程序,支持 -C panic=unwind,通过 trap-hlt 功能 支持回溯,通过 可选功能

平台支持

以下目标架构受到支持

target_arch 规范 semihosting::sys 模块 注意
aarch64 AArch32 和 AArch64 的半主机 sys::arm_compat
arm AArch32 和 AArch64 的半主机 sys::arm_compat 默认情况下,根据 ARM 的建议使用 SVC 在 A+R 配置文件中,但可以通过 trap-hlt 功能 进行更改。
riscv32/riscv64 RISC-V 半主机 sys::arm_compat
xtensa OpenOCD 半主机 sys::arm_compat 需要 openocd-semihosting 功能
mips/mips32r6/mips64/mips64r6 统一托管接口 (MD01069) sys::mips

主机必须运行仿真器或连接到目标的调试器。

以下目标已在 CI 上进行了测试。(qemu-system 已在 Linux、macOS 和 Windows 主机上进行了测试,qemu-user 在 Linux 主机上进行了测试。)

target 退出 all-apis [1](系统) all-apis [1](用户模式) panic-unwind(系统 [2]) 注意
aarch64-未知-{,-软浮点}
{arm,thumb}v4t--eabi
{arm,thumb}v5te--eabi
armv7a--eabi{,hf}
armv7r--eabi{,hf}
armebv7r--eabi{,hf}
armv8r-none-eabihf
thumbv6m-none-eabi N/A
thumbv7m-none-eabi N/A
thumbv7em--eabi{,hf} N/A
thumbv8m.base--eabi N/A
thumbv8m.main--eabi{,hf} N/A
riscv32*-未知--elf
riscv64*-未知--elf
mips{,el}-未知- N/A [3] [4]
mips64{,el}-未知- N/A [3] [4]
mipsisa32r6{,el}-未知- N/A [3] [4]
mipsisa64r6{,el}-未知- N/A [3] [4]

[1] stdiofstimeargs
[2] 我不确定如何在 qemu-user 上测试 panic-unwind。
[3] 由于 #![feature(asm_experimental_arch)],需要使用夜间版本。
[4] 它似乎不支持 QEMU 8.0+。

可选功能

默认情况下禁用所有功能。

在一般的使用场景中,你可能只需要 stdio 功能,它启用了与打印相关的宏,以及/或 panic-handler 功能,在 panic 时会以非零错误码退出。

[dependencies]
semihosting = { version = "0.1", features = ["stdio", "panic-handler"] }
  • alloc
    使用 alloc

  • stdio
    启用 semihosting::io::{stdin,stdout,stderr}semihosting::{print*,eprint*,dbg}

  • fs
    启用 semihosting::fs

  • panic-handler
    基于 semihosting::process::exit 提供panic处理程序。

    如果同时启用了 stdio 功能,则会尝试将panic消息和位置输出到stderr。

  • trap-hlt
    ARM专用:在A+R配置文件中使用HLT指令。

    ARM文档说明

    HLT 编码是新版本2.0的半主机接口规范中的内容。尽可能让半主机调用者继续使用先前存在的陷阱指令以确保与旧版半主机实现兼容。这些陷阱指令是 A64 的 HLT,A+R 配置文件 A32 或 T32 的 SVC,以及 M 配置文件的 BKPT。但是,为了正确支持混合 AArch32/AArch64 系统,有必要将 SVC 指令更改为 HLT 指令。

    ARM鼓励半主机调用者实现支持 A32 和 T32 的 HLT 陷阱,作为一个可配置选项。ARM强烈反对半主机调用者在同一可执行文件中混合 HLTSVC 机制。

    根据ARM的建议,这被实现为一个可选功能。

    在ARM A+R配置文件以外的架构上启用此功能会导致编译错误。

  • openocd-semihosting
    Xtensa专用:使用OpenOCD半主机。

    Xtensa有两个半主机接口

    • Cadence工具和 QEMU 中使用的Tensilica ISS SIMCALL。
    • OpenOCDprobe-rs 中使用的与ARM半主机兼容的半主机接口。 (这个包称其为 "OpenOCD半主机",与 newlib 中的选项名相同。)

    这个包目前不支持基于SIMCALL的半主机,但用户需要明确启用此功能,以避免意外选择其他不是真正想使用的选项。

    在Xtensa以外的架构上启用此功能会导致编译错误。

  • portable-atomic
    使用 portable-atomic 的原子类型。

    portable-atomic 在标准库不提供原子 CAS 的目标上提供原子 CAS。要在这样的目标上使用 panic-unwind 功能(例如,没有A扩展的RISC-V),你需要启用此功能。

    有关详细信息,请参阅其文档

  • args
    启用 semihosting::experimental::env::args

    注意

    • 此功能为实验性(跟踪问题:#1)且不在常规的semver保证范围内,semihosting的次要或补丁版本可能随时对其进行破坏性更改。
  • 时间
    启用 semihosting::experimental::time

    注意

    • 此功能为实验性(跟踪问题:#2)且不在常规的semver保证范围内,semihosting的次要或补丁版本可能随时对其进行破坏性更改。
  • panic-unwind
    为panic处理器提供 -C panic=unwind 支持,并启用 semihosting::experimental::panic::catch_unwind

    目前使用 unwinding crate 来支持unwinding。请参阅其文档以了解支持的平台和要求。

    注意

    • 此功能为实验性(跟踪问题:#3)且不在常规的semver保证范围内,semihosting的次要或补丁版本可能随时对其进行破坏性更改。
    • 需要使用nightly编译器。
    • 此功能隐式启用了 allocpanic-handler 功能。
    • 此功能使用原子CAS。如果您的目标不支持原子CAS(例如,没有A扩展的RISC-V),则需要与 portable-atomic 功能一起使用。
    • 启用此功能时,您可能需要使用 -C panic=unwind 选项重新构建标准库,以便 catch_unwind 能够正常工作。重新构建标准库的推荐方法是向cargo传递 -Z build-std="core,alloc" 选项。
  • backtrace
    为panic处理器提供回溯支持。

    目前使用 unwinding crate 来支持回溯。请参阅其文档以了解支持的平台和要求。

    注意

    • 此功能为实验性(跟踪问题:#3)且不在常规的semver保证范围内,semihosting的次要或补丁版本可能随时对其进行破坏性更改。

    • 需要使用nightly编译器。

    • 此功能隐式启用了 stdio 功能。

    • 启用此功能时,建议同时启用 panic-unwind 功能。否则,此时将不会显示合理的回溯。使用 -C force-unwind-tables 可能有效,但尚未进行测试。

    • 目前生成的回溯不可读。

      panicked at 'a', src/main.rs:86:13
      stack backtrace:
        0x84dc0
        0x8ed80
        0x8332c
        0x83654
        0x80644
        0x803cc
        0x809dc
        0x800bc
      

      您可以使用 addr2line 解析地址,并使用 rustfilt 解除Rust符号的混淆。例如,运行以下命令(请将 <path/to/binary> 替换为您的二进制路径),然后粘贴地址

      llvm-addr2line -fipe <path/to/binary> | rustfilt
      

许可

根据您的选择,受Apache License, Version 2.0MIT license 许可。

除非您明确表示,否则根据Apache-2.0许可证定义的,您有意提交的任何贡献,都应按照上述方式双重许可,不附加任何额外条款或条件。

依赖关系

~0–500KB
~10K SLoC