Code change:
Hi there! I encountered a weird situation when writing a device driver using . Despite getting correct temperature readings in byte form from my thermocouple converter, all readings were incorrect after casting them to floats and applying some fundamental transformations. After much confusion, I tried using instead and found it worked perfectly! However, I knew the transformations should be correct either way: I tested this exact setup and formula using Linux and the crate. That led me to test those transformations on a few different machines. Please take a look at the results below to gain better insight. Arduino Device Other machines for all below MacBook Pro M1 on macOS and Asahi Linux () Linux () macOS () Ryzen desktop machine running Linux () Milk-V Duo () I can do more if you'd like! If there's any additional context I can give, or checking to be done, please let me know, and I'll happily look into it! Also, I did check the crate to see if it was working properly! I assume that since the and ufmt_float'd are the same, it must be an issue with itself. Please see and of the original test to get more info. Thank you for taking a look at my problem!
trying to figure out if this is a regression. I see that you tested on , does it also reproduce on other versions of the rust compiler? Did you try using a stable compiler (if usable for your project)?
AVR doesn't support 64-bit floats in Rust (operations on them should end up being linker errors, though ): The fundamental issue is that AVR intrinsics (e.g. operations for i32 or f32) require a special calling convention that hasn't been yet exposed from LLVM, preventing Rust's compiler-builtins from chiming in with its own implementation. Some intrinsics (such as those for i32, u32, f32 etc.) get implemented by linking the resulting AVR binaries with (that's why working with AVR requires avr-gcc), but GCC doesn't provide implementations for f64. tl;dr f64 is not supported, but (probably) should throw a linker error instead of trying to link with compiler-builtin's implementation (because that implementation uses a different calling convention than the LLVM's codegen expects) Edit: GCC does seem to contain proper impls nowadays (, actually) - maybe LLVM gets the calling convention wrong? I'll take a look over the weekend.
Alright, got it! -- fix at: (note that merging that merge request in compiler-builtins doesn't yet solve the issue here, because then I'll need to prepare another merge request bumping compiler-builtins inside rustc - all should be ready within a few days) As for the cause - since AVRs don't have a native support for floating-point operations, those must be implemented in software; usually implementations for things like that end up in a crate called compiler-builtins (linked above), which implements them in Rust using simple bitwise operations and whatnot. There's a difference, though, between the ABI as expected by LLVM and the code that's present inside compiler-builtins - for "bigger" types (like i64, i128, f32 etc.), AVR requires a special calling convention (which defines things like "which register should contain which value") that is not yet supported by compiler-builtins (and not so easy to expose there). So instead, we pull hand-written functions ("intrinsics") from GCC's standard library (which is why avr-gcc is required as the linker) - those functions use the correct registers -- but the linking order is that stuff from compiler-builtins gets linked before GCC's, that's why those invalid intrinsics have to be commented out in compiler-builtins (so that the avr-gcc can provide its own, correct definitions). This is exactly the same case as we used to have .
Woah, thanks for the fix! Sorry for not updating this issue for a bit - my wired internet hasn't been working, so I haven't had access to my Linux machine to test this functionality. Thank you for taking the time to get it working (and explain it to me)!

Related discussion:
text: panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } libc = { version = "0.2.150", default-features = false, features = ['rustc-dep-of-std'], public = true } <del> compiler_builtins = { version = "0.1.103" } </del> <ins> compiler_builtins = { version = "0.1.104" } </ins> profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep-of-std'] }