Last active
July 24, 2024 05:12
-
-
Save lupyuen/69da35a027cf780680944010b4a85fe7 to your computer and use it in GitHub Desktop.
Apache NuttX RTOS: Build Rust App for QEMU RISC-V 32-bit with Rust Custom Target. See https://lupyuen.github.io/articles/rust4
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# Build NuttX for QEMU RISC-V 32-bit with Rust App | |
## TODO: Set PATH | |
export PATH="$HOME/xpack-riscv-none-elf-gcc-13.2.0-2/bin:$PATH" | |
set -e # Exit when any command fails | |
set -x # Echo commands | |
## Build NuttX | |
function build_nuttx { | |
## Go to NuttX Folder | |
pushd ../nuttx | |
## Build NuttX | |
make -j 8 | |
## Return to previous folder | |
popd | |
} | |
## Build Rust App for QEMU RISC-V 32-bit with Rust Custom Target | |
function build_rust_riscv32 { | |
## Go to NuttX Folder | |
pushd ../nuttx | |
## Download our Custom Target for `riscv32gc` | |
rm -f riscv32gc-unknown-none-elf.json | |
wget https://raw.githubusercontent.com/lupyuen/nuttx-rust-app/main/riscv32gc-unknown-none-elf.json | |
## Custom Target needs Nightly Build of Rust Compiler | |
rustup override set nightly | |
rustup component add rust-src --toolchain nightly | |
## Verify our Custom Target, make sure it's OK | |
rustc \ | |
--print cfg \ | |
--target riscv32gc-unknown-none-elf.json | |
## `cargo build` requires a Rust Project, so we create an empty one. | |
rm -rf app | |
cargo new app | |
## Build the Rust Core Library for `riscv32gc` | |
## Include the `alloc` library, which will support Heap Memory in future. | |
## Ignore the error: `can't find crate for std` | |
pushd app | |
cargo build \ | |
-Zbuild-std=core,alloc \ | |
--target ../riscv32gc-unknown-none-elf.json \ | |
|| true | |
popd | |
## Compile our Rust App with Rust Core Library for `riscv32gc` | |
## We changed the Target to `riscv32gc-unknown-none-elf.json` | |
rustc \ | |
--target riscv32gc-unknown-none-elf.json \ | |
--edition 2021 \ | |
--emit obj \ | |
-g \ | |
-C panic=abort \ | |
-O \ | |
../apps/examples/hello_rust/hello_rust_main.rs \ | |
-o ../apps/examples/hello_rust/*hello_rust.o \ | |
\ | |
-C incremental=app/target/riscv32gc-unknown-none-elf/debug/incremental \ | |
-L dependency=app/target/riscv32gc-unknown-none-elf/debug/deps \ | |
-L dependency=app/target/debug/deps \ | |
--extern noprelude:alloc=`ls app/target/riscv32gc-unknown-none-elf/debug/deps/liballoc-*.rlib` \ | |
--extern noprelude:compiler_builtins=`ls app/target/riscv32gc-unknown-none-elf/debug/deps/libcompiler_builtins-*.rlib` \ | |
--extern noprelude:core=`ls app/target/riscv32gc-unknown-none-elf/debug/deps/libcore-*.rlib` \ | |
-Z unstable-options | |
## NuttX Build need us to copy hello_rust.o to hello_rust_1.o | |
cp \ | |
../apps/examples/hello_rust/*hello_rust.o \ | |
../apps/examples/hello_rust/*hello_rust_1.o | |
## Return to previous folder | |
popd | |
} | |
## Obsolete: Fix the Rust Build for QEMU RISC-V 32-bit by patching the ELF Header | |
function old_build_rust_riscv32 { | |
## Add the Rust Target | |
rustup target add riscv32i-unknown-none-elf | |
## Go to NuttX Folder | |
pushd ../nuttx | |
## Patch the ELF Header, changing it from Software Floating-Point to Double Precision Hardware Floating-Point | |
## https://gist.github.com/lupyuen/7be4bedc6a109b2c3d1201aee6030428 | |
xxd -c 1 ../apps/examples/hello_rust/*hello_rust_1.o \ | |
| sed 's/00000024: 00/00000024: 04/' \ | |
| xxd -r -c 1 - /tmp/hello_rust_1.o | |
cp /tmp/hello_rust_1.o ../apps/examples/hello_rust/*hello_rust_1.o | |
## Return to previous folder | |
popd | |
} | |
## Pull updates | |
git pull && git status && hash1=`git rev-parse HEAD` | |
pushd ../apps | |
git pull && git status && hash2=`git rev-parse HEAD` | |
popd | |
echo NuttX Source: https://github.com/apache/nuttx/tree/$hash1 >nuttx.hash | |
echo NuttX Apps: https://github.com/apache/nuttx-apps/tree/$hash2 >>nuttx.hash | |
## Show the versions of GCC and Zig | |
riscv-none-elf-gcc -v | |
## Configure the NuttX Build | |
make distclean | |
tools/configure.sh rv-virt:nsh | |
## Enable the Hello Rust App | |
kconfig-tweak --enable CONFIG_EXAMPLES_HELLO_RUST | |
## Update the Kconfig Dependencies | |
make olddefconfig | |
## Build NuttX. Ignore the error: `can't link soft-float modules with double-float modules` | |
build_nuttx || true | |
## Build the Rust App with Custom Target | |
build_rust_riscv32 | |
# Previously: old_build_rust_riscv32 | |
## Link the Rust App with NuttX | |
build_nuttx | |
## Show the size | |
riscv-none-elf-size nuttx | |
## Export the Binary Image to nuttx.bin | |
riscv-none-elf-objcopy \ | |
-O binary \ | |
nuttx \ | |
nuttx.bin | |
## Copy the config | |
cp .config nuttx.config | |
## Dump the NuttX Kernel Disassembly to nuttx.S | |
riscv-none-elf-objdump \ | |
--syms --source --reloc --demangle --line-numbers --wide \ | |
--debugging \ | |
nuttx \ | |
>nuttx.S \ | |
2>&1 | |
## Dump the Rust App Disassembly to hello_rust_1.S | |
riscv-none-elf-objdump \ | |
--syms --source --reloc --demangle --line-numbers --wide \ | |
--debugging \ | |
../apps/examples/hello_rust/*1.o \ | |
>hello_rust_1.S \ | |
2>&1 | |
## Check coding style | |
# ../nxstyle arch/risc-v/src/bl808/bl808_mm_init.c | |
## Start the emulator | |
qemu-system-riscv32 \ | |
-semihosting \ | |
-M virt,aclint=on \ | |
-cpu rv32 \ | |
-kernel nuttx \ | |
-nographic \ | |
-bios none |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment