ARMv6-Z bare metal cross-compilation fails

Hello,
I am trying to build a very simple bare metal program for blinking an LED to the Raspberry Pi Zero W, but I have encountered a few problems.

First things first, there isn't an official build target for ARMv6-Z which the RPi Zero is based on, so I had to scour the internet for a target script which I did find in this topic, after the OSDev guide didn't work.

In the topic, it does mention that even a simple for loop causes the linker to throw an error, because it predicts the use of a panic handler, and I seem to have encountered the same problem, even though I am using the same target script, and building the same way as the solution seems to indicate, with the exception of using the assembly from the OSDev guide.

Here is lib.rs:

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

use core::panic::PanicInfo;

mod mem;

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

#[panic_handler]
pub extern fn panic(_panic_info: &PanicInfo) -> ! {
    loop {}
}

#[no_mangle]
pub extern fn _kernel_entry() -> ! {
    mem::write_addr_val(0x2020_0008, 0b1000);

    loop {
        mem::write_addr_val(0x2020_001C, 1<<21);

        for _ in 1..50000 {
            unsafe { core::arch::asm!("nop") };
        }

        mem::write_addr_val(0x2020_0028, 1<<21);

        for _ in 1..50000 {
            unsafe { core::arch::asm!("nop") };
        }
    }

}

Here is mem.rs:

pub fn read_addr_val(addr: u32) -> u32 {
    let mut memory_addr_val: u32 = 0;
    unsafe {
        memory_addr_val = core::intrinsics::volatile_load(addr as *mut u32);
    };
    return memory_addr_val;
}

pub fn write_addr_val(addr: u32, value: u32) {
    unsafe {
        core::intrinsics::volatile_store(addr as *mut u32, value);
    }
}

Here is my Cargo.toml:

[package]
name = "agbos"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

[profile.dev]
panic = "abort"

[profile.release]
panic = "abort"

Here is my Makefile:

all: clean
	cargo build --target=arm-none-eabihf.json -Z build-std=core,compiler_builtins
	arm-none-eabi-gcc -mcpu=arm1176jzf-s -fpic -ffreestanding -c src/boot/boot.s -o build/boot.o
	arm-none-eabi-gcc -T linker.ld -o bin/agbos.elf -ffreestanding -O2 -nostdlib build/boot.o target/arm-none-eabihf/debug/libagbos.rlib
	arm-none-eabi-objcopy -O binary bin/agbos.elf bin/kernel.img
	
clean:
	rm -rf bin/*
	rm -rf build/*
	echo "This is a placeholder file" > bin/placeholder
	echo "This is a placeholder file" > build/placeholder

And here is the error I am getting from the linker:

/usr/bin/../lib/gcc/arm-none-eabi/12.2.1/../../../../arm-none-eabi/bin/ld: target/arm-none-eabihf/debug/libagbos.rlib(agbos-bc8850426024c591.kz8stg7sqqwrrvg.rcgu.o): in function `core::ptr::read::runtime':
/home/arongeo/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/intrinsics.rs:2487: undefined reference to `core::panicking::panic_nounwind'
/usr/bin/../lib/gcc/arm-none-eabi/12.2.1/../../../../arm-none-eabi/bin/ld: target/arm-none-eabihf/debug/libagbos.rlib(agbos-bc8850426024c591.kz8stg7sqqwrrvg.rcgu.o): in function `core::ptr::write::runtime':
/home/arongeo/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/intrinsics.rs:2487: undefined reference to `core::panicking::panic_nounwind'
/usr/bin/../lib/gcc/arm-none-eabi/12.2.1/../../../../arm-none-eabi/bin/ld: target/arm-none-eabihf/debug/libagbos.rlib(agbos-bc8850426024c591.33woj6jg28126ek3.rcgu.o): in function `core::ptr::const_ptr::<impl *const T>::is_aligned_to':
/home/arongeo/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/const_ptr.rs:1566: undefined reference to `core::panicking::panic_fmt'
/usr/bin/../lib/gcc/arm-none-eabi/12.2.1/../../../../arm-none-eabi/bin/ld: target/arm-none-eabihf/debug/libagbos.rlib(agbos-bc8850426024c591.44bldghmgm5fml40.rcgu.o): in function `core::ptr::const_ptr::<impl *const T>::is_aligned_to::runtime_impl':
/home/arongeo/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/const_ptr.rs:1571: undefined reference to `core::panicking::panic'
/usr/bin/../lib/gcc/arm-none-eabi/12.2.1/../../../../arm-none-eabi/bin/ld: target/arm-none-eabihf/debug/libagbos.rlib(agbos-bc8850426024c591.537kmjnkoq6gdird.rcgu.o): in function `core::fmt::Arguments::new_const':
/home/arongeo/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/mod.rs:401: undefined reference to `core::panicking::panic_fmt'
collect2: error: ld returned 1 exit status

As I said I use the same linker script and assembly as in the OSDev guide, with the modification that it jumps to _kernel_entry of course, and I use the target file from the other topic on this.

Thank you for your help in advance.

Did you use xargo? :

We will use xargo to build our project, which works just like a drop-in replacement for Cargo. xargo automatically handles the significant task of compiling and linking in components of the Rust language we will need (such as libcore.rs) for our target.

Oh man, why didn't I think of that? Thanks for the help, works perfectly now. :slight_smile:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.