Impossible to build Adafruit GFX with PlatformIO

Hi,

I have a compilation problem with the GFX library on my code, building for ATMega4809.
I have therefore decided, to clear any own code related issue to try and build the GFX canvas example.

I’ve been through almost all the issues I have been able to read on this forum and elsewhere… the missing Adafruit_I2CDevice.h, that I’ve tried to fix with lib_ldf_mode=chain+ ( and even further with deep+ ) with no success, so I’ve added it explicitely in the main file.

It moved one step and then I had something else wrong in the Adafruit_SPIDevice.h : the BitOrder was not defined in the code.

However it is defined in that Adafruit file :

// some modern SPI definitions don’t have BitOrder enum
#if ((defined(AVR) && !defined(ARDUINO_ARCH_MEGAAVR)) ||
defined(ESP8266) || defined(TEENSYDUINO) || defined(SPARK) ||
defined(ARDUINO_ARCH_SPRESENSE) || defined(MEGATINYCORE) ||
defined(DXCORE) || defined(ARDUINO_AVR_ATmega4809) ||
defined(ARDUINO_AVR_ATmega4808) || defined(ARDUINO_AVR_ATmega3209) ||
defined(ARDUINO_AVR_ATmega3208) || defined(ARDUINO_AVR_ATmega1609) ||
defined(ARDUINO_AVR_ATmega1608) || defined(ARDUINO_AVR_ATmega809) ||
defined(ARDUINO_AVR_ATmega808))
typedef enum _BitOrder {
SPI_BITORDER_MSBFIRST = MSBFIRST,
SPI_BITORDER_LSBFIRST = LSBFIRST,
} BitOrder;
#elif (defined(ESP32) || defined(ASR6501))
// some modern SPI definitions don’t have BitOrder enum and have different SPI
// mode defines
typedef enum _BitOrder {
SPI_BITORDER_MSBFIRST = SPI_MSBFIRST,
SPI_BITORDER_LSBFIRST = SPI_LSBFIRST,
} BitOrder;

#else
// Some platforms have a BitOrder enum but its named MSBFIRST/LSBFIRST
#define SPI_BITORDER_MSBFIRST MSBFIRST
#define SPI_BITORDER_LSBFIRST LSBFIRST
#endif

So I’ve pulled it out from that definition to give it a try. It passed that step to another issue.
Adafruit_GFX_Library\Adafruit_GrayOLED.cpp:143:50: error: no matching function for call to 'Adafruit_SPIDevice(int8_t&, uint32_t&, int, SPI_MODE_enum, SPIClass*&)'
it looked like neverending problem and also seemed not reasonnable to keep and edit a third party library that does work fully under different circumstances ( and Arduino IDE is one of these ).

Configuration file for ATMega4809:
[env:ATmega4809]
platform = atmelmegaavr
board = ATmega4809
framework = arduino
lib_extra_dirs = ~/Documents/Arduino/libraries
lib_ldf_mode = chain+

So I finally I’ve decided to give it a go with a different chip, a classical ATMega2560, and… guess what : it does compile with no errors,

Configuration file for ATMega2560
[env:megaatmega2560]
platform = atmelavr
board = megaatmega2560
framework = arduino
lib_extra_dirs = ~/Documents/Arduino/libraries
lib_ldf_mode = chain+

how can I check that all preprocessor variables are properly set for my cpu ( yes, it’s ATMega4809 that I’m using ) I now suspect that there are missing preprocessor directives for this CPU as it does compile with another one

Any view on this problem or what could be missing in this configuration ?

Does it work with the Arduino IDE? If no, then it’s a problem in the library.

Hi maxgerhardt,

Thanks for having taken time to have a look,

Actually, my original sketch was built for Arduino Nano Every in Arduino IDE, and it does compile with no problem in there. Same thing for the GFX Canvas example :

Linking everything together...
"C:\\Users\\Frede\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino5/bin/avr-gcc" -w -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -Wl,--section-start=.text=0x0 -mmcu=atmega4809 -o "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139/GFXcanvas.ino.elf" "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139\\sketch\\GFXcanvas.ino.cpp.o" "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139\\sketch\\GFXcanvasSerialDemo.cpp.o" "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139\\libraries\\Adafruit_GFX_Library\\glcdfont.c.o" "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139\\libraries\\Adafruit_GFX_Library\\Adafruit_GFX.cpp.o" "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139\\libraries\\Adafruit_GFX_Library\\Adafruit_GrayOLED.cpp.o" "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139\\libraries\\Adafruit_GFX_Library\\Adafruit_SPITFT.cpp.o" "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139\\libraries\\Adafruit_BusIO\\Adafruit_BusIO_Register.cpp.o" "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139\\libraries\\Adafruit_BusIO\\Adafruit_I2CDevice.cpp.o" "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139\\libraries\\Adafruit_BusIO\\Adafruit_SPIDevice.cpp.o" "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139\\libraries\\Wire\\Wire.cpp.o" "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139\\libraries\\Wire\\utility\\twi.c.o" "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139\\libraries\\SPI\\SPI.cpp.o" "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139\\core\\variant.c.o" "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139/core\\core.a" "-LC:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139" -lm
"C:\\Users\\Frede\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino5/bin/avr-objcopy" -O binary -R .eeprom "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139/GFXcanvas.ino.elf" "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139/GFXcanvas.ino.bin"
"C:\\Users\\Frede\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino5/bin/avr-objcopy" -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139/GFXcanvas.ino.elf" "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139/GFXcanvas.ino.eep"
"C:\\Users\\Frede\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino5/bin/avr-objcopy" -O ihex -R .eeprom "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139/GFXcanvas.ino.elf" "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139/GFXcanvas.ino.hex"
Utilisation de la bibliothèque Adafruit_GFX_Library version 1.10.7 dans le dossier: C:\Users\Frede\Documents\Arduino\libraries\Adafruit_GFX_Library 
Utilisation de la bibliothèque Adafruit_BusIO version 1.7.3 dans le dossier: C:\Users\Frede\Documents\Arduino\libraries\Adafruit_BusIO 
Utilisation de la bibliothèque Wire version 1.0 dans le dossier: C:\Users\Frede\AppData\Local\Arduino15\packages\arduino\hardware\megaavr\1.8.7\libraries\Wire 
Utilisation de la bibliothèque SPI version 1.0 dans le dossier: C:\Users\Frede\AppData\Local\Arduino15\packages\arduino\hardware\megaavr\1.8.7\libraries\SPI 
"C:\\Users\\Frede\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino5/bin/avr-size" -A "C:\\Users\\Frede\\AppData\\Local\\Temp\\arduino_build_289139/GFXcanvas.ino.elf"
Le croquis utilise 18567 octets (37%) de l'espace de stockage de programmes. Le maximum est de 49152 octets.
Les variables globales utilisent 490 octets (7%) de mémoire dynamique, ce qui laisse 5654 octets pour les variables locales. Le maximum est de 6144 octets.

In PlatformIO I’m hitting the wall on that missing BitOrder that should be defined in that #if expression, and if I change platform, it does work, this is why it made me think of missing preprocessor directive in the Atmega4809 definition.

I’ve of course added a

#define ARDUINO_ARCH_MEGAAVR 1234
#define ARDUINO_AVR_ATmega4809 1234

at the top of the main ino file but it does nothing, which leaves me without a clue so far.
It behaves in the same way when I’m using the Arduino IDE library and when I’m using PlatformIO installed Adafruit GFX lib

I decided to switch to PlatformIO for several reasons among which I want to build and implement the code directly on Atmega4809 from Microchip

From my poor understanding of development and C/C++ I really think there is something very wrong with the definition of the ATMega4809 in the platformio files, or I have missed a step regarding what to use as a target ?

So I’ve tried another tweak, I have tried to compile for Arduino Nano Every explicitely in PlatformIO ( not selecting ATMega4809 ) but in the end, the ini file is the same, and so does its behaviour… it is still not recognizing any of the specifics for that hardware.

I’m really thinking there is an issue with the definition of that new Arduino/4809 board that does not come from Adafruit nor my own code since both compile in Arduino IDE and not here, and since less recent targets in PlatformIO do accept the code.

Any further view on this ?

I can reproduce the same errors on the GFXCanvas and

[env:ATmega4809]
platform = atmelmegaavr
board = ATmega4809
framework = arduino
lib_ldf_mode = chain+
lib_deps =
     adafruit/Adafruit GFX Library @ ^1.10.7
     adafruit/Adafruit BusIO @ ^1.7.3
     SPI
     Wire

Fundamentally, when selecting ATmega4809 as board, it uses a different Arduino core (https://github.com/MCUdude/MegaCoreX) than when using nano_every (GitHub - arduino/ArduinoCore-megaavr: Arduino Core for the ATMEGA4809 CPU).

Every core can be implemented arbitrarily and thus are not necessarily compatible with each Arduino library.

When I use board = nano_every the sketch compiles no problems without modifications.

Processing ATmega4809 (platform: atmelmegaavr; board: nano_every; framework: arduino)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelmegaavr/nano_every.html
PLATFORM: Atmel megaAVR (1.4.0) > Arduino Nano Every
HARDWARE: ATMEGA4809 16MHz, 6KB RAM, 47.50KB Flash
PACKAGES:
 - framework-arduino-megaavr 1.8.7
 - toolchain-atmelavr 1.70300.191015 (7.3.0)
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain+, Compatibility ~ soft
Found 8 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <Adafruit GFX Library> 1.10.7
|   |-- <Adafruit BusIO> 1.7.3
|   |   |-- <Wire> 1.0
|   |   |-- <SPI> 1.0
|   |-- <Wire> 1.0
|   |-- <SPI> 1.0
|-- <Adafruit BusIO> 1.7.3
|   |-- <Wire> 1.0
|   |-- <SPI> 1.0
|-- <SPI> 1.0
|-- <Wire> 1.0
Building in release mode
Compiling .pio\build\ATmega4809\FrameworkArduinoVariant\variant.c.o
[..]
Building .pio\build\ATmega4809\firmware.hex
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [          ]   3.0% (used 187 bytes from 6144 bytes)
Flash: [===       ]  30.5% (used 14815 bytes from 48640 bytes)
==================== [SUCCESS] Took 2.92 seconds ====================

This is because for the Nano Every board, the Arduino core pulls in code from the ArduinoCore-API project which defines

and thus that type is declared and the include doesn’t trigger.

As for building with board = ATmega4809, the core does have the MSBFIRST and LSBFIRST macros…

but not the BitOrder type.

So in this in the header, the first block should light up.

However it doesn’t because ARDUINO_AVR_ATmega4809 is not defined for this board. Also

Is wrong because that is not seen globally when other .cpp files are compiled. The right way would be to do

build_flags = -DARDUINO_AVR_ATmega4809

which makes the sketch compile again.

The reason the flag is not defined is because it’s spelled differently in the PlatformIO definition…

thus this might a bug.

Tracked in Board macros have different name than expected · Issue #26 · platformio/platform-atmelmegaavr · GitHub.

Hi Maxgerhardt

I had made the build work by putting the

#define ARDUINO_AVR_ATmega4809 1234

in the Adafruit_SPIDevice.h but I admit I don’t like this pseudo solution.

Your ways are much much better. Thanks a lot for your time and analysis.