Why 'static const ... PROGMEM' for ActiveLayerColor

Hi all,

the example source code for ActiveLayerColor (and probably some other plugins too) has a variable definition of

static const cRGB foo[] PROGMEM = …

I tried to turn it to plain

constexpr cRGB foo[] = …

and thought that’s safe due to constexpr forcing everything to be calculatable at compile time.

However, I got weird behaviour and switch back to the code from the example layout. Know I wonder two things:

  • What is PROGMEM and how does it work? It does not seem to be valid C++ for me.
  • Why static?
  • Why didn’t constexpr safe me?

I hope that the answer to this questions would be very educative for others too. Could anyone point me out to the documentation please? I could not find the answers myself.

Thank you very much.

PROGMEM is a magic preprocessor macro that tells the compiler to place the data into flash memory instead of SRAM. The AVR architecture used by the ATMega32u4 MCU (the heart of the keyboard) has two kinds of memory: flash memory and SRAM. Flash memory is read-only, except when flashing the keyboard. SRAM is read-write. The reason we put a lot of things into PROGMEM (short for “program memory”) is because there’s considerably more of that on the MCU: there’s about 28k flash, and only 2k SRAM. So anything that’s read-only, is usually put into flash, to save SRAM for things that do need to be writeable.

The relevant arduino docs are here:

https://www.arduino.cc/reference/en/language/variables/utilities/progmem/

constexpr didn’t save you, because even though that calculates things at compile time, the result will still be put in SRAM, while the code expects it to be in PROGMEM/flash.

In this case, the array is defined inside the setup() function, then a pointer to that array is set which gets used after setup() has returned. If it wasn’t declared static, the memory allocated for that array could be freed and then overwritten, resulting in unpredictable behaviour when the pointer is used.

In this case, however, the memory can’t be overwritten, because it’s read-only program memory, as @algernon already explained. If the compiler doesn’t detect an error, it would probably work just fine without declaring it static, but it would be poor practice to do so.