-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error: linking with avr-gcc failed #149
Comments
This error often occurs if your program size overflows the flash size. Are you building in release or debug mode? |
Sorry, should have read more carefully ... It seems you are already building in I'm not sure what the best way is to find out where this issue comes from. Personally, I'd use one of these:
|
Ah, that seems like a good place to start, thank you @Rahix . Would it be appropriate to alter the compiler so that it can catch that sort of problem and provide a clearer error message? |
@Rahix Do you know if there's a way to alter the target descriptor to trick it into thinking there's more space? At least it would let me confirm that it's a size constraint issue. |
Not really possible as final sizes are only known at link time.
You could write your own linker script, but I don't think the effort is worth it. Try compiling with |
@Rahix I'm having trouble figuring how how to follow your instructions. Currently my command to compile is xargo build --target avr-atmega328p --release So I tried altering it to be xargo rustc --target avr-atmega328p --release -- --emit=obj But it ends up giving the same error. It seems like |
It should be an object file ( |
Thanks so much for your help @Rahix . I find the file and got the output. 00000000 00000001 B DEVICE_PERIPHERALS
0000119c 00000002 r rust_begin_unwind
00000000 00000002 r __unnamed_3
00000008 00000002 r _ZN4core3ptr18real_drop_in_place17h671565532a8ec42eE
0000000a 00000002 r _ZN4core3ptr18real_drop_in_place17h84aaf412b5654cb2E
00000000 00000004 r _ZN112_$LT$embedded_hal..digital..v1_compat..OldOutputPin$LT$T$GT$$u20$as$u20$embedded_hal..digital..v1..OutputPin$GT$7set_low17ha964da085e52de99E
00000004 00000004 r _ZN112_$LT$embedded_hal..digital..v1_compat..OldOutputPin$LT$T$GT$$u20$as$u20$embedded_hal..digital..v1..OutputPin$GT$8set_high17h53da3a0de33410acE
000011a6 00000008 r _ZN4core9panicking5panic17h5dbe8e19a91fe7ddE
0000119e 00000008 r _ZN4core9panicking9panic_fmt17h88f68b20b00f166eE
00000000 0000000a d __unnamed_1
00000000 0000000a d __unnamed_2
00001190 0000000c r _ZN84_$LT$atmega328p_hal..spi..Spi$u20$as$u20$embedded_hal..spi..FullDuplex$LT$u8$GT$$GT$4read17h7ffa6261298b29e9E
00000000 00000019 r switch.table._ZN5w55008Register12control_byte17h997a9dab34649aa0E
00001120 00000070 r _ZN84_$LT$atmega328p_hal..spi..Spi$u20$as$u20$embedded_hal..spi..FullDuplex$LT$u8$GT$$GT$4send17hfd5c80352a5cc8d5E
0000000c 00000252 r _ZN5w550020ActiveW5500$LT$E$GT$8write_to17h03ad5119f6a62654E
0000025e 00000258 r _ZN5w550020ActiveW5500$LT$E$GT$9read_from17h90d8084f962a2233E
000004b6 00000c6a R main Based on some some searching, it sounds like the second column is the size of each object in hex. They sum up to ~4.5Kb The big things are w5500's |
Something I've found is that those two functions contain the only references to the dependency crate "BigEndian". https://github.com/kellerkindt/w5500/blob/master/src/lib.rs#L247 It's possible that this dependency is too large. Will need to investigate further. |
Apparently the ATMega328P has 32Kb of program memory. So it seems super weird that 4.5Kb would be too much... |
Hm. Try |
@Rahix I made the unwrap change you suggested (and pushed up to the repo), and tried
Even if I add |
Sorry, I really don't have the time right now to look into this in more detail ... I am pretty confident it has something to do with formatting of |
Thanks a lot for your input @Rahix . I'll start ripping the crate apart and see what I can get to compile. |
By commenting bits out one at a time, I finally narrowed the difference between successful compilation and failure down to the invocation to my SPI implementation... 😬 . Which is very odd since I can run a simple example if I call the SPI library directly. Still digging. |
I've been at it for a few hours, and I've distilled this down to the most simple POC that I can make demonstrate the problem. https://github.com/jonahbron/smart-plug/tree/error-demo The program here is very simple. The w5500 code is pulled into 36,37c36,37
< pub struct W5500<'c, E> {
< pub spi: &'c mut dyn FullDuplex<u8, Error = E>,
---
> pub struct W5500<'c, E, S: FullDuplex<u8, Error = E>> {
> pub spi: &'c mut S,
40c40
< impl<E> W5500<'_, E> {
---
> impl<E, S: FullDuplex<u8, Error = E>> W5500<'_, E, S> { Also, the error only appears if I call the // Removing one of these lines will get rid if the linker error
w5500.receive(&mut buffer[..]);
w5500.receive(&mut buffer[..]); Unless someone has any more thoughts @Rahix @dylanmckay , I don't see how this couldn't be a bug with the compiler. I'm going to try improving the generics on the full, original w5500 crate to see if that helps the issue. |
Oh wow, the driver is using a trait object? Trait objects need type IDs which are also |
@Rahix I doubt it, seems like a mistake by the dev. However I do see that all of the enums have this in front of them: #[repr(u8)] I'm guessing that prevents the need for u64 for discrimination. I'll try to refactor out that trait object tonight. Hopefully that resolves the issue. Would it make sense for the compiler to error over this, so it doesn't make it to the linker and fail? |
Thanks for your direction @Rahix ! Getting rid of those trait objects has fixed compilation. Still need to do a real test, but I've opened a PR: @dylanmckay I'd still like to know if you consider this something that could be turned into a more explicit error. |
So apparently I had a false positive. Even after my fix, I'm still getting the same compilation errors if if I call the |
It seems like this might be related to the usage of dynamic integers of type Could this be the case? Are |
Further testing doesn't seem to indicate this is a problem with u16. I've found two lines that I can tweak that allows the program to compile: --- a/src/lib.rs
+++ b/src/lib.rs
@@ -385,7 +385,7 @@ impl<E, ChipSelect: OutputPin, Spi: FullDuplex<u8, Error = E>> Udp<E> for (&mut
w5500.read_from(
socket.rx_register_at(read_pointer + 8),
- &mut destination[..data_length],
+ &mut destination[..42],
)?;
// self.read_from(socket.register_at(0x00_0C), &mut ip.address)?;
@@ -441,7 +441,7 @@ impl<E, ChipSelect: OutputPin, Spi: FullDuplex<u8, Error = E>> Udp<E> for (&mut
)?;
}
- let data_length = data.len() as u16;
+ let data_length = data.len() as u8;
{
let data_length = data_length.to_be_bytes(); That data_length variable in the first one of type
Changing it to a literal number (which I assume is coerced to usize) is the only thing that fixes it. 42 is the greatest integer that it accepts, which is extremely weird. I'd expect it to be a power of 2. The second item in the diff doesn't suffer at all from changing u16 to u8. I feel very lost right now, and it seems as though there are several layers of understanding that I'm lacking, given how confused I am by how these changes impact the linker. Any advice is welcome. |
I've made some progress! I got it to compile with a call to |
After spending about 3.5 hours and poring over hundreds of lines of code, I've been able to reduce the error demo down to 15 lines. I'm really hoping this sample is small enough for someone to be able to tell me what the problem with the code is, allow them to fix a bug in the compiler that makes this not work. I don't fully understand this code, I just know it's a direct simplification of the full version, and produces the same error. Full project: https://github.com/jonahbron/smart-plug/blob/error-demo-2/src/main.rs Source code: #![no_std]
#![no_main]
#![feature(asm)]
extern crate panic_halt;
#[no_mangle]
extern fn main() -> () {
let mem = unsafe {
&*{ 76 as *const vcell::VolatileCell<u8> }
};
let len = mem.get() as usize;
// If you change this 17 to 16, the error goes away
for _ in &mut [0u8; 17][..len] {
mem.get();
}
} Compiling this in the project repo with Fortunately for my application, a 16-byte packet length is perfectly fine. But I think there would be a lot of value for other people if this problem was sorted out, whether it's in avr-rust, svd2rust, avr-hal, avr-device, or w5500. |
Found a lead. I googled that missing function in the error, and got this result: https://stackoverflow.com/questions/29222673/math-symbols-missing-from-avr-libgcc Apparently those functions have been removed and replaced with something else. I guess the next step is to figure out what exactly is generating them (surely the compiler?) and update that code. |
The symbols you're missing are:
one option that you have is to visit https://github.com/gcc-mirror/gcc/blob/master/libgcc/config/lm32/_ashlsi3.S and pull their assembly files. If you're curious about what these functions are: http://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html Given the documentation on them, it seems like you're going to have a hard time getting away with just removing them, since you're in an embedded context which I could certainly believe doesn't have "hardware support for arithmetic operations on some modes" |
It looks like this is a known issue in LLVM that's being tracked here: Seems like this problem has been around a while, and got merged upstream into LLVM. It's even mentioned in the RFC. @dylanmckay Is there any light at the end of this tunnel? I see the activity on this repo has slowed since June. @TimNN Pinging you as well in case you're still involved in this project. Based on this comment you made last year, it sounds like you understand this problem. Did you make any progress in fixing it, or is there any direction you could offer to me in fixing it? While your description in the solution of the problem seems simple, I'm worried there might be more to it based on @dylanmckay's older comment here: |
Based on a review of libgcc, it appears that the functions mentioned in this error are present and supported. I'm no pro, but it looks to me like a couple things need to happen:
Maybe there are other steps, but based on my research so far it seems like that would fix the error. |
Both projects don't yet have any AVR related code which might make it hard to convince upstream to merge those changes ... I suggest forking [dependencies.core]
stage = 0
[dependencies.compiler_builtins]
stage = 1
git = "https://your.fork/"
rev = "git-hash" if I remember correctly. |
Thank you @Rahix. What advice can you give around how to add those intrinsics? This is all new to me, I know nothing. |
@Rahix I thought the base AVR work had been already merged into upstream LLVM? |
@Rahix I'm seeing some mysterious behavior in my attempt to add the missing symbols. As soon as I pull in compiler-builtins (without making any changes), the errors disappear. However, the parts of the code that produced that linker error do not behave as expected. Specifically, it seems that my driver is unable to communicate with the W5500 chip. How could this be, when compiler-builtins does not appear to provide these symbols? |
We haven't yet enabled AVR support in compiler-rt - it is possible to get most of it for free by letting compiler-rt fall back to the target independent C-only rtcall implementations, although the biggest prickle is a couple register allocation special cases inherited from avr-gcc for arithmetic routines like mul, div, mod, would require hand-rolled AVR asm to match the GNU AVRf libgcc ABI. |
I've sent a few weeks ago a patch to LLVM that implements what I think is a full GCC ABI compatible calling convention, but I'm afraid it fell through the mailing-list cracks 😢. Maybe it can help with these issues? |
I noticed that - great work! I spotted your patch a couple days ago, I've started the first round of review. I suspect it will help (especially with your removal one of one of libgcc special cases), but I feel like we'll still have to hand-roll a couple routines in compiler-rt to get them ABI compatible, as we won't get that with the generic C implementation AFAIK. Perhaps the best solution w.r.t. avr-libgcc compatibility is to eschew being compatible with the custom ABI routines and instead lower them to AVR instructions directly in the backend, removing the dependency on the rtlib for this. |
Oh, true, I hadn't notice, great! I'll review and rebase in a couple of days.
What I've done is to add this to my Xargo.toml:
And then in |
Hi, sorry for reviving an old issue, especially on an obsolete repo, but I recently bought a little arduino beginners kit with an atmega328p and started playing with the new AVR support in rust nightly and quickly faced this exact problem (which had me scratching my head for a couple of weeks). It looks like the LLVM patch linked above only just recently landed, so is it just a matter of waiting for rust to bump its LLVM version (which might take a while)? Is there any workaround in the meantime? |
@abusch try to check your avr-atmega328p.json. I just copied a latest json file from https://github.com/Rahix/avr-hal repo and it works. |
@yuanyuan2100 thanks for the suggestion but I already had the latest version. I should have mentioned that I got some code to work. It breaks down when I try to use |
I ran in the same problem as I try to read ds18b20 one wire sensors with my atmega328p. |
I think I got stuck at this issue as well, tried to read a dht22 sensor but the library returns an f32 datatype. When I try to print them with ufmt_float it won't compile because of that missing functions |
Try to set |
I could reduce the problem to the point where the error occurs if I try to cast an i16 to a f32. Setting <"no-builtins"> to fixed the linker error. |
@yuanyuan2100 this fixed the issue partly for me. Casting now work, but when i want to print out a f32 value and convert it with ufmt_float i still got the error |
Now that rust-lang/compiler-builtins#371 has been merged, this should no longer be an issue. I will close this but feel free to reopen/comment if the issue persists! |
For reference, last I checked there was still a related problem: It works in release mode, but in debug mode where |
For what it's worth: I'm still seeing this linker error when using ufmt_float. Setting no-builtins to true and building with a release profile does not solve it. Using nightly-2021-01-07 as prescribed by @Rahix. Could this be a regression?
|
Can you try applying rust-lang#82242 (comment), as I did in Rahix/avr-hal@4d288ac? |
This was generated using your template, so it's already in there :)
|
The offending line for completeness sake: ufmt::uwrite!(&mut serial, "Current temp: {}", uFmt_f32::Two(current_temp)).void_unwrap(); |
And now the whole file. Btw, I am aware that this app could be done completely without floats, but I just wanted to try them. Also happy to open an issue somewhere else, when necessary. https://github.com/jeroenvlek/rust-arduino-projects-book/blob/main/src/bin/read-temperature.rs |
Compiler generating code that links to That being said, I've just checked your code (that @jeroenvlek in order to compile that code, you had to have rustc + llvm built manually on your machine, right? If so, could you try re-applying the newest version of the LLVM-AVR patch and trying again? (for reference, I'm checked out at rustc@e4b1d5841494d6eb7f4944c91a057e16b0f0a9ea + llvm-project@4041354b4c12fb4329853b67f61b8617252188d6) |
Ah, I've just checked with the unpatched rustc + llvm (i.e. the ones managed automatically by rustup) and that's what causes those Seems like the bugfix is gone with the relatively-newest rustc + relatively-newest llvm (with that patch I've linked) - so if you want to test it locally, you'd have to build rustc with patched LLVM on your machine (you'd have to google it a bit though, I don't have any tutorial at hand :x); hopefully the patch will be merged soon~ish, as it's waiting for review. |
Ah, I assumed, given the date this was closed, that the patches were already merged. For now I can do without formatted floats and will wait for the patches to appear, but it's good to know that I can roll my own if necessary.
Hahaha, that's valuable information in this case though! :) |
I'm working on a program that uses @Rahix's avr-hal and the w5500 driver crate. However when compiling, I get this error:
Because these clearly aren't normal Rust compiler errors, it seems like this might be a bug with the Rust compiler itself. Does anything obvious stand out as a problem here? Could there be a problem with my setup? I just updated and re-compiled avr-rust today to make sure. Note that this error only occurs if I invoke the receive method of w5500 in my application. Full application code can be found here:
https://github.com/jonahbron/smart-plug/tree/c9f8994
The text was updated successfully, but these errors were encountered: