In short, a global const variable (array) defined in a .cpp file disappeared from the .o file, causing "undefined reference ... " error. The problem can be imperfectly solved by add 'volatile' to the definition of variable. It's useless to turn off compiler optimization or '-flto'.
Compiler: AVR-GCC 11.10 from https://github.com/ZakKemble/avr-gcc-build/releases.
Enviroment: PlatformIO.
OS: Windows 11 x64.
The definition is like:
// file: oled_basic_init_sequence.cpp
#include <Arduino.h>
namespace oled_basic {
const uint8_t _init_sequence_for_ssd1316_4_wire_spi[25] PROGMEM = {
0xae, /*display off*/
0x00, /*set lower column address*/
// ...
};
const uint8_t _init_sequence_for_ssd1306_2_wire_i2c[23] PROGMEM = {
0xAE,
0xD5,
// ...
};
} // namespace oled_basic
With or without PROGMEM
doesn't matter. In .h file:
// file: oled_basic_init_sequence.h
#pragma once
#include <stdint.h>
namespace oled_basic {
extern const uint8_t _init_sequence_for_ssd1316_4_wire_spi[25];
extern const uint8_t _init_sequence_for_ssd1306_2_wire_i2c[23];
} // namespace oled_basic
In main.cpp file:
#include <Arduino.h>
#include "oled_basic_init_sequence.h"
volatile uint8_t * test = 0;
void setup() {
*test = oled_basic::_init_sequence_for_ssd1316_4_wire_spi[0];
// this doesn't help
*test = pgm_read_byte(&(oled_basic::_init_sequence_for_ssd1316_4_wire_spi[0]));
}
void loop() {
}
compilation failed with:
Building in release mode
Compiling .pio\build\ATmega128\src\oled_basic_init_sequence.cpp.o
Linking .pio\build\ATmega128\firmware.elf
c:/users/xxxxx/.platformio/packages/toolchain-atmelavr/bin/../lib/gcc/avr/11.1.0/../../../../avr/bin/ld.exe: C:\Users\xxxxx\AppData\Local\Temp\ccelvOYl.ltrans0.ltrans.o: in function `main':
<artificial>:(.text.startup+0x5a): undefined reference to `_ZN10oled_basic37_init_sequence_for_ssd1316_4_wire_spiE'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\ATmega128\firmware.elf] Error 1
========================================================= [FAILED] Took 3.42 seconds =========================================================
Verbose build info:
avr-g++ -o .pio\build\ATmega128\firmware.elf -mmcu=atmega128 -Os -Wl,--gc-sections -flto -fuse-linker-plugin .pio\build\ATmega128\src\main.cpp.o .pio\build\ATmega128\src\oled_basic_font.cpp.o .pio\build\ATmega128\src\oled_basic_init_sequence.cpp.o -L.pio\build\ATmega128 -Wl,--start-group .pio\build\ATmega128\lib81f\libi2c.a .pio\build\ATmega128\lib685\libSPI.a .pio\build\ATmega128\libe29\libWire.a .pio\build\ATmega128\libFrameworkArduinoVariant.a .pio\build\ATmega128\libFrameworkArduino.a -lm -Wl,--end-group
Maybe I just made some low level syntax mistakes and still can't realize.