Skip to content

Commit

Permalink
Support Xtensa (OpenOCD Semihosting)
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Mar 21, 2024
1 parent 8ba812e commit 372c608
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 14 deletions.
4 changes: 4 additions & 0 deletions .github/.cspell/project-dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ ebreak
EINTR
EINVAL
errno
espup
fipe
FLEN
fopen
Expand Down Expand Up @@ -39,6 +40,7 @@ nlink
norvc
nsec
OMAP
openocd
opensbi
pcnet
plog
Expand All @@ -55,12 +57,14 @@ requirechecksums
rustfilt
sdbbp
Seekable
simcall
slli
srai
subarch
subcode
syscall
TDMI
Tensilica
tickfreq
timespec
TMPNAM
Expand Down
14 changes: 13 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ jobs:
- run: cargo test --workspace --features $TEST_FEATURES --release --target ${{ matrix.target }} $DOCTEST_XCOMPILE $BUILD_STD
- run: cargo careful test --workspace --features $TEST_FEATURES --target ${{ matrix.target }} $DOCTEST_XCOMPILE $BUILD_STD
if: startsWith(matrix.rust, 'nightly')
- run: cargo hack build --workspace --no-private --feature-powerset --depth 2 --optional-deps=portable-atomic --exclude-features panic-unwind,backtrace --target ${{ matrix.target }} $BUILD_STD
- run: cargo hack build --workspace --no-private --feature-powerset --depth 2 --optional-deps=portable-atomic --exclude-features panic-unwind,backtrace,openocd-semihosting --target ${{ matrix.target }} $BUILD_STD
- run: cargo minimal-versions build --workspace --no-private --detach-path-deps=skip-exact --features $TEST_FEATURES --target ${{ matrix.target }} $BUILD_STD
- run: cargo minimal-versions build --workspace --no-private --detach-path-deps=skip-exact --features $TEST_FEATURES --target ${{ matrix.target }} $BUILD_STD --direct

Expand All @@ -117,6 +117,12 @@ jobs:
- uses: taiki-e/checkout-action@v1
- name: Install Rust
run: rustup toolchain add ${{ matrix.rust }} --no-self-update --component rust-src && rustup default ${{ matrix.rust }}
- uses: taiki-e/install-action@v2
with:
tool: espup
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
if: startsWith(matrix.rust, 'nightly') && (startsWith(matrix.os, 'ubuntu') || matrix.os == '')
- run: |
set -eEuxo pipefail
sudo apt-get -o Acquire::Retries=10 -qq update && sudo apt-get -o Acquire::Retries=10 -o Dpkg::Use-Pty=0 install -y --no-install-recommends \
Expand Down Expand Up @@ -164,6 +170,12 @@ jobs:
echo "C:\Program Files\qemu" >>"${GITHUB_PATH}"
"C:\Program Files\qemu\qemu-system-arm" --version
if: startsWith(matrix.os, 'windows')
- run: espup install --targets esp32
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
if: startsWith(matrix.rust, 'nightly') && (startsWith(matrix.os, 'ubuntu') || matrix.os == '')
- run: tools/no-std.sh
- run: TEST_RUNNER=qemu-user tools/no-std.sh
if: startsWith(matrix.os, 'ubuntu') || matrix.os == ''
- run: cargo +esp build --target xtensa-esp32-none-elf -Z build-std=core,alloc --features $TEST_FEATURES,openocd-semihosting
if: startsWith(matrix.rust, 'nightly') && (startsWith(matrix.os, 'ubuntu') || matrix.os == '')
7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ keywords = ["qemu"]
categories = ["embedded", "hardware-support", "no-std", "no-std::no-alloc"]
exclude = ["/.*", "/tools", "/target-specs"]
description = """
Semihosting for AArch64, ARM, RISC-V, MIPS32, and MIPS64.
Semihosting for AArch64, ARM, RISC-V, MIPS32, MIPS64, and Xtensa.
"""

[package.metadata.docs.rs]
Expand Down Expand Up @@ -77,6 +77,11 @@ backtrace = ["stdio", "unwinding", "unwinding/hide-trace"]
# See readme for details.
portable-atomic = ["dep:portable-atomic"]

# Xtensa-specific: Use OpenOCD Semihosting.
#
# See readme for details.
openocd-semihosting = []

[dependencies]
portable-atomic = { version = "1.3", optional = true, default-features = false, features = ["require-cas"] }
unwinding = { version = "0.2", optional = true, default-features = false, features = ["unwinder"] }
Expand Down
23 changes: 17 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
[![github actions](https://img.shields.io/github/actions/workflow/status/taiki-e/semihosting/ci.yml?branch=main&style=flat-square&logo=github)](https://github.com/taiki-e/semihosting/actions)

<!-- tidy:crate-doc:start -->
Semihosting for AArch64, ARM, RISC-V, MIPS32, and MIPS64.
Semihosting for AArch64, ARM, RISC-V, MIPS32, MIPS64, and Xtensa.

This library provides access to semihosting, a mechanism for programs running on the real or virtual (e.g., QEMU) target to communicate with I/O facilities on the host system. See the [ARM documentation](https://github.com/ARM-software/abi-aa/blob/HEAD/semihosting/semihosting.rst) for more information on semihosting.

Expand Down Expand Up @@ -36,11 +36,12 @@ Additionally, this library provides a panic handler for semihosting, `-C panic=u

The following target architectures are supported:

| target_arch | Specification | `semihosting::sys` module |
| ----------- | ------------- | ------------------------- |
| arm/aarch64 | [Semihosting for AArch32 and AArch64](https://github.com/ARM-software/abi-aa/blob/HEAD/semihosting/semihosting.rst) | `sys::arm_compat` |
| riscv32/riscv64 | [RISC-V Semihosting](https://github.com/riscv-software-src/riscv-semihosting/blob/HEAD/riscv-semihosting-spec.adoc) | `sys::arm_compat` |
| mips/mips32r6/mips64/mips64r6 | Unified Hosting Interface (MD01069) | `sys::mips` |
| target_arch | Specification | `semihosting::sys` module | Note |
| ----------- | ------------- | ------------------------- | ---- |
| arm/aarch64 | [Semihosting for AArch32 and AArch64](https://github.com/ARM-software/abi-aa/blob/HEAD/semihosting/semihosting.rst) | `sys::arm_compat` | |
| riscv32/riscv64 | [RISC-V Semihosting](https://github.com/riscv-software-src/riscv-semihosting/blob/HEAD/riscv-semihosting-spec.adoc) | `sys::arm_compat` | |
| xtensa | [OpenOCD Semihosting](https://github.com/espressif/openocd-esp32/blob/HEAD/src/target/espressif/esp_xtensa_semihosting.c) | `sys::arm_compat` | requires the [`openocd-semihosting` feature](#optional-features-openocd-semihosting) |
| mips/mips32r6/mips64/mips64r6 | Unified Hosting Interface (MD01069) | `sys::mips` | |

The host must be running an emulator or a debugger attached to the target.

Expand Down Expand Up @@ -98,6 +99,16 @@ semihosting = { version = "0.1", features = ["stdio", "panic-handler"] }
If the `stdio` feature is also enabled, this attempt to output panic message and
location to stderr.

- <a name="optional-features-openocd-semihosting"></a>**`openocd-semihosting`**<br>
Xtensa-specific: Use OpenOCD Semihosting.

Xtensa has two semihosting interfaces:

- Tensilica ISS SIMCALL used in Cadence tools and [QEMU](https://www.qemu.org/docs/master/about/emulation.html#supported-targets).
- ARM-semihosting-compatible semihosting interface used in [OpenOCD](https://github.com/espressif/openocd-esp32/blob/HEAD/src/target/espressif/esp_xtensa_semihosting.c) and [probe-rs](https://github.com/probe-rs/probe-rs/pull/2303). (This crate calls it "OpenOCD Semihosting", which is the same as the option name in [newlib](https://github.com/espressif/newlib-esp32/blob/esp_based_on_4_1_0/libgloss/xtensa/syscalls.c#L23).)

This crate does not currently support SIMCALL-based semihosting, but users need to explicitly enable the feature to avoid accidentally selecting a different one than one actually want to use.

- **`portable-atomic`**<br>
Use [portable-atomic]'s atomic types.

Expand Down
1 change: 1 addition & 0 deletions src/experimental/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ mod sys {
target_arch = "arm",
target_arch = "riscv32",
target_arch = "riscv64",
all(target_arch = "xtensa", feature = "openocd-semihosting"),
))]
mod imp {
use core::cell::Cell;
Expand Down
1 change: 1 addition & 0 deletions src/experimental/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ mod sys {
target_arch = "arm",
target_arch = "riscv32",
target_arch = "riscv64",
all(target_arch = "xtensa", feature = "openocd-semihosting"),
))]
mod inner {
use super::{SystemTime, Timespec};
Expand Down
35 changes: 29 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

/*!
<!-- tidy:crate-doc:start -->
Semihosting for AArch64, ARM, RISC-V, MIPS32, and MIPS64.
Semihosting for AArch64, ARM, RISC-V, MIPS32, MIPS64, and Xtensa.
This library provides access to semihosting, a mechanism for programs running on the real or virtual (e.g., QEMU) target to communicate with I/O facilities on the host system. See the [ARM documentation](https://github.com/ARM-software/abi-aa/blob/HEAD/semihosting/semihosting.rst) for more information on semihosting.
Expand Down Expand Up @@ -31,11 +31,12 @@ Additionally, this library provides a panic handler for semihosting, `-C panic=u
The following target architectures are supported:
| target_arch | Specification | `semihosting::sys` module |
| ----------- | ------------- | ------------------------- |
| arm/aarch64 | [Semihosting for AArch32 and AArch64](https://github.com/ARM-software/abi-aa/blob/HEAD/semihosting/semihosting.rst) | `sys::arm_compat` |
| riscv32/riscv64 | [RISC-V Semihosting](https://github.com/riscv-software-src/riscv-semihosting/blob/HEAD/riscv-semihosting-spec.adoc) | `sys::arm_compat` |
| mips/mips32r6/mips64/mips64r6 | Unified Hosting Interface (MD01069) | `sys::mips` |
| target_arch | Specification | `semihosting::sys` module | Note |
| ----------- | ------------- | ------------------------- | ---- |
| arm/aarch64 | [Semihosting for AArch32 and AArch64](https://github.com/ARM-software/abi-aa/blob/HEAD/semihosting/semihosting.rst) | `sys::arm_compat` | |
| riscv32/riscv64 | [RISC-V Semihosting](https://github.com/riscv-software-src/riscv-semihosting/blob/HEAD/riscv-semihosting-spec.adoc) | `sys::arm_compat` | |
| xtensa | [OpenOCD Semihosting](https://github.com/espressif/openocd-esp32/blob/HEAD/src/target/espressif/esp_xtensa_semihosting.c) | `sys::arm_compat` | requires the [`openocd-semihosting` feature](#optional-features-openocd-semihosting) |
| mips/mips32r6/mips64/mips64r6 | Unified Hosting Interface (MD01069) | `sys::mips` | |
The host must be running an emulator or a debugger attached to the target.
Expand Down Expand Up @@ -93,6 +94,16 @@ semihosting = { version = "0.1", features = ["stdio", "panic-handler"] }
If the `stdio` feature is also enabled, this attempt to output panic message and
location to stderr.
- <a name="optional-features-openocd-semihosting"></a>**`openocd-semihosting`**<br>
Xtensa-specific: Use OpenOCD Semihosting.
Xtensa has two semihosting interfaces:
- Tensilica ISS SIMCALL used in Cadence tools and [QEMU](https://www.qemu.org/docs/master/about/emulation.html#supported-targets).
- ARM-semihosting-compatible semihosting interface used in [OpenOCD](https://github.com/espressif/openocd-esp32/blob/HEAD/src/target/espressif/esp_xtensa_semihosting.c) and [probe-rs](https://github.com/probe-rs/probe-rs/pull/2303). (This crate calls it "OpenOCD Semihosting", which is the same as the option name in [newlib](https://github.com/espressif/newlib-esp32/blob/esp_based_on_4_1_0/libgloss/xtensa/syscalls.c#L23).)
This crate does not currently support SIMCALL-based semihosting, but users need to explicitly enable the feature to avoid accidentally selecting a different one than one actually want to use.
- **`portable-atomic`**<br>
Use [portable-atomic]'s atomic types.
Expand Down Expand Up @@ -212,6 +223,7 @@ semihosting = { version = "0.1", features = ["stdio", "panic-handler"] }
target_arch = "mips32r6",
target_arch = "mips64",
target_arch = "mips64r6",
target_arch = "xtensa",
),
feature(asm_experimental_arch)
)]
Expand All @@ -227,8 +239,19 @@ semihosting = { version = "0.1", features = ["stdio", "panic-handler"] }
target_arch = "mips32r6",
target_arch = "mips64",
target_arch = "mips64r6",
target_arch = "xtensa",
)))]
compile_error!("unsupported target");
#[cfg(target_arch = "xtensa")]
#[cfg(not(feature = "openocd-semihosting"))]
compile_error!(
"xtensa has two semihosting interfaces so you have to select implementation;\n\
please enable `openocd-semihosting` feature if you want to use OpenOCD Semihosting used in OpenOCD and probe-rs.\n\
see <https://docs.rs/semihosting/latest/semihosting/#optional-features-openocd-semihosting> for more."
);
#[cfg(not(target_arch = "xtensa"))]
#[cfg(feature = "openocd-semihosting")]
compile_error!("`openocd-semihosting` feature does not compatible with this target");

#[cfg(feature = "alloc")]
extern crate alloc;
Expand Down
1 change: 1 addition & 0 deletions src/sys/arm_compat/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//! - Semihosting for AArch32 and AArch64 <https://github.com/ARM-software/abi-aa/blob/HEAD/semihosting/semihosting.rst>
//! - RISC-V Semihosting <https://github.com/riscv-software-src/riscv-semihosting/blob/HEAD/riscv-semihosting-spec.adoc>
//! - <https://github.com/qemu/qemu/blob/HEAD/semihosting/arm-compat-semi.c>
//! - <https://github.com/espressif/openocd-esp32/blob/HEAD/src/target/espressif/esp_xtensa_semihosting.c>
#![allow(clippy::missing_safety_doc)] // TODO

Expand Down
1 change: 1 addition & 0 deletions src/sys/arm_compat/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub use arch::{syscall, syscall_readonly};
#[cfg_attr(target_arch = "aarch64", path = "aarch64.rs")]
#[cfg_attr(target_arch = "arm", path = "arm.rs")]
#[cfg_attr(any(target_arch = "riscv32", target_arch = "riscv64"), path = "riscv.rs")]
#[cfg_attr(target_arch = "xtensa", path = "xtensa.rs")]
mod arch;

pub use crate::sys::reg::{ParamRegR, ParamRegW, RetReg};
Expand Down
39 changes: 39 additions & 0 deletions src/sys/arm_compat/syscall/xtensa.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT

use core::arch::asm;

use super::{OperationNumber, ParamRegR, ParamRegW, RetReg};

/// Raw semihosting call with a parameter that will be read + modified by the host
#[inline]
pub unsafe fn syscall(number: OperationNumber, parameter: ParamRegW<'_>) -> RetReg {
unsafe {
let r;
asm!(
"break 1, 14",
inout("a2") number.0 as usize => r, // OPERATION NUMBER REGISTER => RETURN REGISTER
// Use inout because operation such as SYS_ELAPSED suggest that
// PARAMETER REGISTER may be changed.
inout("a3") parameter.0 => _, // PARAMETER REGISTER
options(nostack, preserves_flags),
);
RetReg(r)
}
}

/// Raw semihosting call with a parameter that will be read (but not modified) by the host
#[inline]
pub unsafe fn syscall_readonly(number: OperationNumber, parameter: ParamRegR<'_>) -> RetReg {
unsafe {
let r;
asm!(
"break 1, 14",
inout("a2") number.0 as usize => r, // OPERATION NUMBER REGISTER => RETURN REGISTER
// Use inout because operation such as SYS_ELAPSED suggest that
// PARAMETER REGISTER may be changed.
inout("a3") parameter.0 => _, // PARAMETER REGISTER
options(nostack, preserves_flags, readonly),
);
RetReg(r)
}
}
3 changes: 3 additions & 0 deletions src/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
target_arch = "arm",
target_arch = "riscv32",
target_arch = "riscv64",
all(target_arch = "xtensa", feature = "openocd-semihosting"),
))]
use arm_compat as arch;
#[cfg(any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "riscv32",
target_arch = "riscv64",
all(target_arch = "xtensa", feature = "openocd-semihosting"),
))]
#[cfg_attr(
semihosting_doc_cfg,
Expand All @@ -29,6 +31,7 @@ use arm_compat as arch;
target_arch = "arm",
target_arch = "riscv32",
target_arch = "riscv64",
all(target_arch = "xtensa", feature = "openocd-semihosting"),
)))
)]
pub mod arm_compat;
Expand Down
3 changes: 3 additions & 0 deletions src/sys/reg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ impl<'a> ParamRegW<'a> {
target_arch = "arm",
target_arch = "riscv32",
target_arch = "riscv64",
all(target_arch = "xtensa", feature = "openocd-semihosting"),
))]
impl<'a> ParamRegW<'a> {
#[inline]
Expand Down Expand Up @@ -100,6 +101,7 @@ impl<'a> ParamRegR<'a> {
target_arch = "arm",
target_arch = "riscv32",
target_arch = "riscv64",
all(target_arch = "xtensa", feature = "openocd-semihosting"),
))]
impl<'a> ParamRegR<'a> {
#[inline]
Expand Down Expand Up @@ -157,6 +159,7 @@ impl RetReg {
target_arch = "arm",
target_arch = "riscv32",
target_arch = "riscv64",
all(target_arch = "xtensa", feature = "openocd-semihosting"),
))]
impl RetReg {
#[allow(clippy::cast_possible_truncation)]
Expand Down

0 comments on commit 372c608

Please sign in to comment.