Rahix / avr-hal

embedded-hal abstractions for AVR microcontrollers
Apache License 2.0
1.3k stars 219 forks source link

Linker error when using a floating point operation #514

Closed MichalOp closed 6 months ago

MichalOp commented 6 months ago

It seems that I can't use a lot of the floating point functions (when compiling for atmega328p), for example min:

#![no_std]
#![no_main]

use panic_halt as _;

#[arduino_hal::entry]
fn main() -> ! {
    let dp = arduino_hal::Peripherals::take().unwrap();
    let pins = arduino_hal::pins!(dp);
    let mut led = pins.d13.into_output();
    let mut x: f32 = 0.0;
    loop {
        x += 0.1;
        led.toggle();
        arduino_hal::delay_ms(x.min(1000.0) as u16); 
    }
}

This fails to link with the following error:

~/Embedded/min-test$ cargo run
   Compiling min-test v0.1.0 ($HOME/Embedded/min-test)
WARN rustc_codegen_ssa::back::link Linker does not support -no-pie command line option. Retrying without.
error: linking with `avr-gcc` failed: exit status: 1
  |
  = note: LC_ALL="C" PATH="$HOME/.rustup/toolchains/nightly-2023-12-28-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin: ........" VSLANG="1033" "avr-gcc" "-mmcu=atmega328p" "/tmp/rustcjNe3pr/symbols.o" "$HOME/Embedded/min-test/target/avr-atmega328p/debug/deps/min_test-5e911a0772a75ebb.arduino_hal-e191b5c45c882469.arduino_hal.bbf3967b75265d73-cgu.0.rcgu.o.rcgu.o" "-Wl,--as-needed" "-L" "$HOME/Embedded/min-test/target/avr-atmega328p/debug/deps" "-L" "$HOME/Embedded/min-test/target/debug/deps" "-L" "$HOME/.rustup/toolchains/nightly-2023-12-28-x86_64-unknown-linux-gnu/lib/rustlib/avr-atmega328p/lib" "-Wl,-Bdynamic" "-lgcc" "-Wl,-z,noexecstack" "-L" "$HOME/.rustup/toolchains/nightly-2023-12-28-x86_64-unknown-linux-gnu/lib/rustlib/avr-atmega328p/lib" "-o" "$HOME/Embedded/min-test/target/avr-atmega328p/debug/deps/min_test-5e911a0772a75ebb.elf" "-Wl,--gc-sections"
  = note: $HOME/Embedded/min-test/target/avr-atmega328p/debug/deps/min_test-5e911a0772a75ebb.arduino_hal-e191b5c45c882469.arduino_hal.bbf3967b75265d73-cgu.0.rcgu.o.rcgu.o: In function `core::f32::_$LT$impl$u20$f32$GT$::min::h6a8fe8903685e749':
          $HOME/.rustup/toolchains/nightly-2023-12-28-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/f32.rs:929: undefined reference to `fminf'
          collect2: error: ld returned 1 exit status

  = note: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
  = note: use the `-l` flag to specify native libraries to link
  = note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)

error: could not compile `min-test` (bin "min-test") due to 1 previous error

My understanding is that this function and other float functions should be available in the avr-libc. I tried adding -lm to the linker args in avr-specs, but it didn't help. I also tried the new nightly toolchain and both the newest and mentioned in the readme commits of this repo.

I am on Ubuntu 22.04, and I installed the prerequisites according to the readme, so I have avr-gcc 5.4.0 and avr-libc 2.0.0. If I don't use the floating point functions, the code compiles normally - am I missing something?

Rahix commented 6 months ago

Hm, I know that in the past, a lot of the floating point methods didn't exist in libcore so you couldn't call them in the first place. The solution back then was to use the libm crate instead which has replacement implementations. libm::fminf() in your case...

But as your program is failing at the linker stage instead of simply erroring on a missing f32::min() method, it seems something has changed here. Maybe another compiler-builtins topic? @Patryk27, do you have any idea?

Patryk27 commented 6 months ago

I've just checked and the code compiles correctly on my machine - could you run avr-gcc --version and post the result? Maybe you're using an older avr-gcc which didn't yet have float intrinsics for AVR.

(for comparison, I'm on avr-gcc (Homebrew AVR GCC 9.4.0) 9.4.0)

MichalOp commented 6 months ago

It looks like this was the issue, thank you. I was using avr-gcc 5.4.0 - which is the default one installed via apt for Ubuntu, and I guess it is too old.

After I compiled gcc 13.2.0 from source for avr (I also compiled avr-libc 2.1.0 for good measure), the program compiled and ran without issues.