Arduino AVR Core is supposed to be already efficient, as the resulting code will run on AVR ATmega168 and ATmega328 MCUs with just 16 to 32KB of internal flash storage and 8 to 16 MHz clock speeds.
But Nerd Ralph felt there was space for improvement as for instance the Blink sample takes 924 bytes of flash storage when compiled for the Arduino Uno. So he developed ArduinoShrink library with the same functions as Arduino AVR Core but enabling smaller and faster firmware files.
The result is pretty impressive as we can see from the screenshot above with the Blink sample now taking just 196 bytes or an almost 80% reduction in size.
So how was this feat achieved exactly? Ralph explains it in details in a blog post, but in a nutshell, the following main two steps were taken:
- Writing modular, self-contained code instead of providing a single static library as in Arduino AVR Core.
- Rewrite part of the code in AVR assembler, especially code that is often poorly optimized by the compiler such as interrupt service routines
Besides resulting in smaller code, ArduinoShrink can also make the code faster. For instance, the timer0 interrupt would typically take 5us to run blocking interrupt in the process, but the first instruction in ArduinoShrink’s ISR is ‘sei’, which allows other interrupts to run, reducing the latency impact to a few cycles more than the hardware minimum. This may also reduce power consumption leading to longer battery life.
One downside of the current version is that the compiler must be able to resolve the pin number for the digital IO functions at compile-time, and avr-gcc is not always able to recognize the pin is a compile-time constant. But Ralph plans to write a more portable version of digitalWrite function that is still smaller and faster.
If you’d like to give it a try go over to the Github repository and install ArduinoShrink in the Arduino IDE. It is not the first Arduino optimization project from Nerd Raph, as he previously wrote picoCore for ATtiny13 and ATtiny85 series AVR microcontrollers.
Via Hackaday
Jean-Luc started CNX Software in 2010 as a part-time endeavor, before quitting his job as a software engineering manager, and starting to write daily news, and reviews full time later in 2011.
Support CNX Software! Donate via cryptocurrencies, become a Patron on Patreon, or purchase goods on Amazon or Aliexpress
For sure, 924 bytes by default just to blink a LED leaves a lot of room for improvement. I’m not that much surprised, seeing how long the build takes on arduino due to the massive includes of lots of not necessarily useful stuff.
Let’s hope the optimizer doesn’t change timings in time-sensitive parts. Also I don’t know if it can shrink a code that’s already too large, considering that often you end up with errors like “fatal: hello world too large for this device”. But that’s great overall.
It’s a very long time I haven’t done any AVR libc programming anymore. But isn’t the sei() at the start of an ISR slightly contra productive? Doesn’t that allow subsequent interrupts to interrupt the execution of the current ISR? Which might be less than desirable.