5 ms·
The fact that avr-gcc exists at all is quite amazing though. It's allowed many people to get into embedded design without needing to purchase licenses for other
by joshvm 4y ago
The fact that avr-gcc exists at all is quite amazing though. It's allowed many people to get into embedded design without needing to purchase licenses for other proprietary compilers. It might not be the most optimal compiler, but sub-optimal does not mean incorrect. If you know enough to quibble with the code, and you're seeing performance issues like this, you can just inline your assembly into C.
AVR has historically been one of the best routes to get into embedded work because there is solid open-source tooling, interfacing the hardware is simple, and it's very well documented in the open by Atmel/Microchip. Arduino would not exist without avr-gcc.
- bpye 4y agoI've hoped for a while that LLVM's support for such targets would improve, but maybe the ubiquity of ARM microcontrollers makes that more unlikely now. There is an AVR target for example, but in my attempt to use Rust on an AVR I ran into several incorrectness bugs - and newer versions of LLVM are plain broken [0]. There is also an MSP430 backend but I've never had an excuse to play around with that... Maybe the libgccjit backend for Rust will solve the specific scenario I was interested in, but it doesn't improve anything for LLVM itself. [0] - https://github.com/rust-lang/rust/issues/88252 https://github.com/rust-lang/rust/issues/88252
- tuetuopay 4y agoOff topic, but I can confirm Rust's MSP430 backend works great.
- bombela 4y agoTook a while but this issue was fixed this year. Until then, you could compile a patched version of LLVM, or use an older nightly. And the code generation was quite broken indeed. Most importantly the saving of registers within interrupt handlers. Hard to understand the bug, but I had documented a simple inline asm solution on the issue. It has been fixed since then. My last experience was quite good. And I didn't notice wrong codegen. As an aside, the inline asm combines pretty well with generics to produce custom machine code during compilation. For example I was able to reproduce the gcc-avr built-in for delays: https://github.com/avr-rust/delay/blob/cycacc/src/delay_cycles.rs https://github.com/avr-rust/delay/blob/cycacc/src/delay_cycl...
- bpye 4y agoOh hey, you're right, I went and found the issue but didn't scroll down after seeing it was still open. That's great! I might try and revive my previous project. I had tried an older nightly but that's where I think I was seeing bad codegen.
- Gordonjcp 4y agoIsn't Rust designed around things like immutable variables, where you need to copy and copy and copy the same things over and over, and therefore expect to run it on something with infinite amounts of memory? It might be suitable for modern desktop computers which have hundreds or even thousands of kilobytes of memory available, but not a microcontroller with 2kB of RAM.
- pix128 4y agoMaybe I'm dumb, but why would you need to copy an immutable value?
- ItsHarper 4y agoBecause the only way to have a modified version of that value is to make a brand new copy with the modification.
- cylon13 4y agoThis is incorrect
- Gordonjcp 4y agoWhich part is incorrect?
- arcticbull 4y agoIt's not fair to say that rust is 'designed around immutable variables' - rust has move semantics, but move semantics just mean that if you have a variable, 'a' and you assign it to variable 'b', the variable 'a' is now dead and can no longer be referenced. This exists at the lexical level, it's a no-op in generated code. Is that maybe what you were referring to? For certain scalar types, flexibility is increased by allowing 'copy' semantics where assigning 'a' into 'b' makes 'b' a copy of 'a', and both are alive. Then it ends up mattering how heavy the type is - although you can only implement 'copy' for things you can trivially memcpy, so nothing on the heap. Generally anything that would be expensive to duplicate doesn't get 'copy' semantics, but instead requires you to move it into a new variable, or explicitly clone it. Rust also has immutable-by-default semantics, but it's by default. You can mutate the contents of structs, but there can only be one mutable reference XOR an arbitrary quantity of read-only references and aliasing is not permitted. This forms the basis for many of the safety guarantees. Did that help? I was guessing at what you meant, so if that wasn't it I can always try again. [edit] within the context of microcontrollers Rust requires you to be very explicit about what is and isn't permitted, and how things should work. You can disallow in your construction pretty much anything expensive or non-trivial.