kitesurfer1404 / WS2812FX

WS2812 FX Library for Arduino and ESP8266
MIT License
1.6k stars 347 forks source link

Compiling error: "in expansion of macro 'F'" #83

Closed sushukka closed 6 years ago

sushukka commented 6 years ago

When trying to compile WS2812FX with MySensors node, I get following error message:

In file included from C:\Omat\Own_projects\Arduino\omat\libraries\MySensors/MySensors.h:28:0,
  from C:\Omat\Own_projects\Arduino\omat\MySensors\HomeNumber_IrRemote\HomeNumber_IrRemote.ino:39:

C:\Users\userxxx\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/pgmspace.h:21:51: error: __c causes a section type conflict with __c

 #define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];}))

                                                   ^

C:\Omat\Own_projects\Arduino\omat\libraries\MySensors/core/MySensorsCore.h:91:40: note: in definition of macro 'CORE_DEBUG'

 #define CORE_DEBUG(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug

                                        ^

C:\Omat\Own_projects\Arduino\omat\libraries\MySensors/core/MySensorsCore.cpp:594:13: note: in expansion of macro 'PSTR'

  CORE_DEBUG(PSTR("MCO:SLP:WUP=%d\n"), result); // sleep wake-up

             ^

In file included from C:\Users\userxxx\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/Arduino.h:243:0,

                 from sketch\HomeNumber_IrRemote.ino.cpp:1:

C:\Users\userxxx\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/pgmspace.h:21:51: note: '__c' was declared here

 #define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];}))

                                                   ^

C:\Users\userxxx\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/WString.h:38:76: note: in definition of macro 'FPSTR'

 #define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))

                                                                            ^

C:\Users\userxxx\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/WString.h:39:34: note: in expansion of macro 'PSTR'

 #define F(string_literal) (FPSTR(PSTR(string_literal)))

                                  ^

C:\Omat\Own_projects\Arduino\libraries\WS2812FX-master/WS2812FX.h:284:50: note: in expansion of macro 'F'

       _name[FX_MODE_CUSTOM]                    = F("Custom");

                                                  ^

exit status 1
Error compiling for board WeMos D1 R2 & mini.

Not sure where the problem lies. Have around 100 MySensor nodes and this is the first time I get this error. Something overlapping or...?

moose4lord commented 6 years ago

This issue has been around for quite a while. See the explanation for this bug here: https://github.com/esp8266/Arduino/issues/3351 Basically, both the WS2812FX library and the MySensors library are putting non-global strings in Flash memory (to conserve RAM memory), which causes a conflict. The link above references a couple workarounds you can investigate. Or you might want to try using Board Manager to upgrade to the latest version of the ESP8266 platform (v2.4.1). They may have fixed this issue in that release.

sushukka commented 6 years ago

Thanks! Updated to V2.4.1 but the problem persist. Have to dig deeper into the link you provided, but so far it seems that one have to modify more or less the actual source codes of WS2812FX or Mysensors library. For future maintainability/upgradeability I'm not very keen to go that path. But hopefully there will be some neat solution I haven't found yet...

moose4lord commented 6 years ago

I think you're right about having to modify the library source code. I agree, not a great option for future maintainability. But for the WS2812FX lib it's not terribly hard. You just need to move all the strings out of Flash memory and into RAM memory, i.e. change all the F(...) functions to regular strings and change all the __FlashStringHelper references to char references.

The getModeName() function in WS2812FX.cpp becomes this:

const char* WS2812FX::getModeName(uint8_t m) {
  if(m < MODE_COUNT) {
    return _name[m];
  } else {
    return "";
  }
}

And all the mode strings in WS2812FX.h change to regular strings:

_name[FX_MODE_STATIC]                    = "Static";
_name[FX_MODE_BLINK]                     = "Blink";
_name[FX_MODE_BREATH]                    = "Breath";
...

I'll have to give some thought to changing all the strings in WS2812FX to global variables, so this doesn't continue to be a problem.

sushukka commented 6 years ago

Hello, Thanks a lot for your help! :) I made the modifications and got still some flashtring errors, but only because I had to make two more changes: const __FlashStringHelper* getModeName(uint8_t m); --> const char* getModeName(uint8_t m); and const __FlashStringHelper* _name[MODE_COUNT]; // SRAM footprint: 2 bytes per element --> const char* _name[MODE_COUNT]; // SRAM footprint: 2 bytes per element Now compilation ends ok! Reading your comments in the code I assume that this flashstring stuff is needed with some lower memory controllers (like Nano you commented... :)), but with ESP8266 there are much more playroom. Maybe some AVR check for Nano/similar and then branch to different methods after that...However, the problem would still persist with Nano+MySensors&WS2812FX so probably your global variable solution is the way to go.