lexus2k / ssd1306

Driver for SSD1306, SSD1331, SSD1351, IL9163, ILI9341, ST7735, PCD8544, Nokia 5110 displays running on Arduino/ESP32/Linux (Rasperry) platforms

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Image size of AVR builds

montaguk opened this issue · comments

While investigating the build issues I encountered on #74, I (somewhat accidentally) discovered that building for the ATTiny85 and ATTiny45 results in a .text segment that is too large for the available device RAM:

avr-gcc -o ../bld/demos/ssd1306_demo.out -g -Os -w -ffreestanding -mmcu=attiny45 -DF_CPU=16000000 -MD -g -Os -w -ffreestanding -I./demos/ssd1306_demo -I../src -Wall -Werror -Wl,--gc-sections -ffunction-sections -fdata-sections  ../bld/main.o ../bld/demos/ssd1306_demo/sova.o ../bld/demos/ssd1306_demo/ssd1306_demo.o -L../bld -lssd1306
/usr/lib/gcc/avr/5.4.0/../../../avr/bin/ld: ../bld/demos/ssd1306_demo.out section `.text' will not fit in region `text'
/usr/lib/gcc/avr/5.4.0/../../../avr/bin/ld: region `text' overflowed by 740 bytes
collect2: error: ld returned 1 exit status

To generate the build failure I simply ran the command below after removing the -Werror and -Wall flags from Makefile.common. Leaving -Werror/-Wall in the Makefile causes the build fail before the link stage complaining about implicit casting to smaller integer types.

./build_and_run.sh -p avr -m attiny45 -f demos/ssd1306_dem

Is this behavior/limitation already known/expected? Perhaps this is just a result of building the demo with so many features and would work just fine if only building the library and linking to project code.

Thanks again for the awesome library!

Hello.

Oh, my god. I thought, I fixed issue with the types, but it seems, it was in 2.0.0 branch. Thank you for the finding.
As for AVR size, yeah, it is known issue on latest releases. Code size increased due to new features. And disassembly and learning how to optimize code size takes much time.

AVR code size is greatly improved in 2.0.0 version (currently experimental branch is 2.0.0_dev_no_virtual) via using class templates. But this requires full library rework, and changes library interface (compatibility is lost).
The examples, which work for now on that branch are demo/ssd1306_demo and nano_engine/snowflakes.

ssd1306_demo for attiny85 needs 6170 bytes of flash (canvas work is removed for attiny85):

AVR Memory Usage
----------------
Device: Unknown

Program:    6170 bytes
(.text + .data + .bootloader)

Data:        186 bytes
(.data + .bss + .noinit)

is there a way to remove spi functions? i think it is uncommon to have both spi and i2c in a attiny project. editing the file UserSetting.h did not make the trick and the final .text size does not change

@aldolo69 What about UserSettings.h?
The library supports such type of tuning

@aldolo69 What about UserSettings.h?
The library supports such type of tuning

yes. indeed using i2c the compiler does not look for spi lib in any case. even stripping the splash screen i'm 700 bytes away from using an atmega8.

i'll investigate .text section. just for fun.

@aldolo69 I compiled simple test for Attiny85 at 8MHz in Arduino IDE (Damellis package):

#include "ssd1306.h"
void setup()
{
    ssd1306_128x64_i2c_init();
}
void loop()
{
}

Just display initialization, and it took only 1334 bytes or flash. No spi functions except only 1, which is common for i2c and spi implementations: ssd1306_spiDataMode(), which aquires only 106 bytes. I didn't find Adafruit SSD1306 for attiny85, but for Atmega328p Adafruit library needs 9700 bytes in the same case.

i can confirm that no unused part of the library are linked. i was able to shrink down a little bit the build size using the LinkTimeOptimization, turned off by default in the minicore atmega8 settings.

Reducing code size for AVR microcontrollers is a big challenge. In 2.0.0_dev version I moved to c++, hoping that c++ templates would allow gcc linker/compiler to completely remove unused code, and to make ssd1306 library code execution even faster than 1.7.X versions, since c++ templates allow not to use pointers to functions.
But supporting different types of lcd displays needs some special low layer implementation, and doesn't allow to make thing as simple as possible. And as for now, c++ gave only 1-5% of flash consumption improvement (and I've got too big effort for library reworking while moving to c++). And sometimes c++ needs even more flash. 2.0.0 version uses less SRAM by 10-20%, and it supports multiple OLEDs working at the same time. I'm trying to understand, how it is reasonable to move on with 2.0.0 version. Many modern microcontrollers (ESP, ARM architecture based) have much more resources, and winning another 300-500 bytes for them is not such a valuable prize.

Here is the status for now:

Features 1.X.X 2.X.X Comments
Support multiple displays - +
Flash requirements + + both versions have advantages and disadvantages
RAM requirements - + 2.x.x needs 10-20% less RAM
Compatibility - - 1.X.X and 2.X.X API is not compatible
VGA D-Sub + -

@montaguk After latest commits ssd1306_demo can be compiled for attiny85 and attiny45.
Please check latest master branch