hexagon-unknown-none-elf

层级: 3

用于裸机 Hexagon DSP 的 Rust。

目标描述
hexagon-unknown-none-elfHexagon 32 位(独立,硬浮点)

目标维护者

要求

此目标是交叉编译的。不支持 std。没有默认分配器,但可以通过提供分配器来使用 alloc

默认情况下,使用此目标生成的代码应该在 Hexagon DSP 硬件上运行。

  • -Ctarget-cpu=hexagonv73 添加对 Hexagon V73 及之前定义的指令的支持。

标记为 extern "C" 的函数使用 Hexagon 架构调用约定

此目标生成 PIC ELF 二进制文件。

构建目标

可以通过在 config.toml 中的 target 列表中添加它来构建支持该目标的 Rust。

[build]
build-stage = 1
host = ["<target for your host>"]
target = ["<target for your host>", "hexagon-unknown-none-elf"]

[target.hexagon-unknown-none-elf]

cc = "hexagon-unknown-none-elf-clang"
cxx = "hexagon-unknown-none-elf-clang++"
linker = "hexagon-unknown-none-elf-clang"
ranlib = "hexagon-unknown-none-elf-ranlib"
ar = "hexagon-unknown-none-elf-ar"
llvm-libunwind = 'in-tree'

<target for your host> 替换为 x86_64-unknown-linux-gnu 或适合你的主机机器的任何其他内容。

构建 Rust 程序

Rust 尚未为此目标提供预编译的工件。要为此目标编译,你需要启用目标构建 Rust(参见上面的“构建目标”),或者通过使用 build-std 或类似方法构建自己的 core 副本。

测试

由于 hexagon-unknown-none-elf 支持各种不同的环境并且不支持 std,因此此目标不支持运行 Rust 测试套件。

交叉编译工具链和 C 代码

此目标已使用 qemu-system-hexagon 进行测试。

hexagon-unknown-none-elf 的一个常见用例是构建与 C 代码链接的库,这些库可以在模拟或具有 Hexagon DSP 的设备上使用。

Hexagon SDK 包含在设备上运行时有用的库,可以与之链接。

独立操作系统

下面的脚本将针对“Hexagon 独立操作系统”构建一个可执行文件,该文件适用于模拟或裸机设备测试。

首先,运行 cargo new --bin demo1_hexagon,然后将下面的源代码添加为 src/main.rs。此程序演示了通过半主机进行的控制台输出。

#![no_std]
#![no_main]

extern "C" {
    fn putchar(ch: i32);
    fn _exit(code: i32) -> !;
}

#[no_mangle]
extern "C" fn main() -> i32 {
    let message = "Hello, this is Rust!";
    for b in message.bytes() {
        unsafe {
            putchar(b as i32);
        }
    }
    0
}

#[panic_handler]
fn panic(_panic: &core::panic::PanicInfo) -> ! {
    unsafe {
        _exit(1);
    }
}

接下来,将下面的脚本保存为 build.sh 并根据你的环境进行编辑。

# Hexagon SDK, required for target libraries:
hex_sdk_root=/local/mnt/workspace/Qualcomm/Hexagon_SDK/5.3.0.0
hex_sdk_toolchain=${hex_sdk_root}/tools/HEXAGON_Tools/8.6.06

sdk_libs=${hex_sdk_toolchain}/Tools/target/hexagon/lib
q6_arch=v65
g0_lib_path=${sdk_libs}/${q6_arch}/G0
pic_lib_path=${sdk_libs}/${q6_arch}/G0/pic

build_cfg=release
cargo build --target=hexagon-unknown-none-elf -Zbuild-std --release

# Builds an executable against "hexagon standalone OS" suitable for emulation:
${cc} --target=hexagon-unknown-none-elf -o testit \
    -fuse-ld=lld \
    -m${q6_arch} \
    -nodefaultlibs \
    -nostartfiles \
    ${g0_lib_path}/crt0_standalone.o \
    ${g0_lib_path}/crt0.o \
    ${g0_lib_path}/init.o \
    -L${sdk_libs}/${q6_arch}/ \
    -L${sdk_libs}/ \
    wrap.c \
    target/hexagon-unknown-none-elf/${build_cfg}/libdemo1_hexagon.rlib \
    target/hexagon-unknown-none-elf/${build_cfg}/deps/libcore-*.rlib \
    target/hexagon-unknown-none-elf/${build_cfg}/deps/libcompiler_builtins-*.rlib \
    -Wl,--start-group \
    -Wl,--defsym,_SDA_BASE_=0,--defsym,__sbss_start=0,--defsym,__sbss_end=0 \
    ${g0_lib_path}/libstandalone.a \
    ${g0_lib_path}/libc.a \
    -lgcc \
    -lc_eh \
    -Wl,--end-group \
    ${g0_lib_path}/fini.o \

${hex_toolchain}/x86_64-linux-gnu/bin/qemu-system-hexagon -monitor none -display none -kernel ./testit

QuRT OS

首先,运行 cargo new --lib demo2_hexagon,然后将下面的源代码添加为 src/lib.rs。此程序演示了内联汇编和通过半主机进行的控制台输出。

#![no_std]
#![no_main]
#![feature(lang_items)]
#![feature(asm_experimental_arch)]

use core::arch::asm;

extern "C" {
    fn putchar(ch: i32);
    fn _exit(code: i32) -> !;
}

fn hexagon_specific() {
    let mut buffer = [0_u8; 128];

    unsafe {
        let mut x = &buffer;
        asm!(
                "{{\n\t",
                "  v0=vmem({addr}+#0)\n\t",
                "  {tmp} = and({tmp}, #1)\n\t",
                "}}\n\t",
                addr = in(reg) x,
                tmp = out(reg) _,
            );
    }
}

#[no_mangle]
extern "C" fn hello() -> i32 {
    let message = "Hello, this is Rust!\n";
    for b in message.bytes() {
        unsafe {
            putchar(b as i32);
        }
    }
    hexagon_specific();
    0
}

#[panic_handler]
fn panic(_panic: &core::panic::PanicInfo) -> ! {
    unsafe {
        _exit(1);
    }
}

#[lang = "eh_personality"]
fn rust_eh_personality() {}

接下来,创建一个 C 程序作为入口点,将下面的内容保存为 wrap.c

int hello();

int main() {
    hello();
}

然后,将下面的脚本保存为 build.sh 并根据你的环境进行编辑。下面的脚本将针对 QuRT RTOS 构建一个共享对象,该对象适用于通过 fastrpc-shell 加载时进行模拟或设备测试。

# Hexagon SDK, required for target libraries:
hex_sdk_root=/local/mnt/workspace/Qualcomm/Hexagon_SDK/5.3.0.0
hex_sdk_toolchain=${hex_sdk_root}/tools/HEXAGON_Tools/8.6.06

sdk_libs=${hex_sdk_toolchain}/Tools/target/hexagon/lib
q6_arch=v65
g0_lib_path=${sdk_libs}/${q6_arch}/G0
pic_lib_path=${sdk_libs}/${q6_arch}/G0/pic
runelf=${hex_sdk_root}/rtos/qurt/computev65/sdksim_bin/runelf.pbn
rmohs=${hex_sdk_root}/libs/run_main_on_hexagon/ship/hexagon_toolv86_${q6_arch}/run_main_on_hexagon_sim

# Builds a library suitable for loading into "run_main_on_hexagon_sim" for
# emulation or frpc shell on real target:
${cc} --target=hexagon-unknown-none-elf -o testit.so \
    -fuse-ld=lld \
    -fPIC -shared \
    -nostdlib \
    -Wl,-Bsymbolic \
      -Wl,--wrap=malloc \
      -Wl,--wrap=calloc \
      -Wl,--wrap=free \
      -Wl,--wrap=realloc \
      -Wl,--wrap=memalign \
    -m${q6_arch} \
    wrap.c \
    target/hexagon-unknown-none-elf/${build_cfg}/libdemo2_hexagon.rlib \
    target/hexagon-unknown-none-elf/${build_cfg}/deps/libcore-*.rlib \
    target/hexagon-unknown-none-elf/${build_cfg}/deps/libcompiler_builtins-*.rlib \
    -Wl,-soname=testit \
    ${pic_lib_path}/libc.so

# -Bsymbolic above for memory alloc funcs is necessary to access the heap on
# target, but otherwise not required.

# multi-stage loader: runelf => run_main_on_hexagon_sim => testit.so{`main`}
${hex_toolchain}/x86_64-linux-gnu/bin/qemu-system-hexagon \
    -monitor none \
    -display none \
    -kernel ${runelf} \
    -append "${rmohs} -- ./testit.so"