hexagon-unknown-none-elf
层级: 3
用于裸机 Hexagon DSP 的 Rust。
目标 | 描述 |
---|---|
hexagon-unknown-none-elf | Hexagon 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
并根据你的环境进行编辑。
- 下面的
hex_toolchain
指的是 仅使用公开开源存储库的 Hexagon 工具链。 - 下面的
cc
指的是 clang。你可以使用发行版中的clang
,只要它至少是clang-17
。或者,你可以使用 Hexagon 开源工具链版本 中的hexagon-unknown-none-elf-clang
。
# 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"