Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Xtensa (OpenOCD Semihosting) #9

Merged
merged 1 commit into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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, probe-rs, etc.\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
Loading