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 操作系统
首先,运行 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"