-2

I recently bought a NodeMCU ESP8266 and started playing with it. Even though almost all the scripts I've written for Arduino micro controllers work fine on ESP8266, there are some differences. For example, reading from the EEPROM or using the internal VREF in my Esp8266.

I know that one can identify which Arduino board is connected using the following code:

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)

//Code in here will only be compiled if an Arduino Mega is used.

#elseif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)

//Code in here will only be compiled if an Arduino Uno (or older) is used.

#elseif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)

//Code in here will only be compiled if an Arduino Leonardo is used.

#endif 

However, this works for arduino micro controllers. How would I be able to do it for an esp8266 microcontroller?

CoderUni
  • 5,474
  • 7
  • 26
  • 58
  • esp8266 arduino core has ESP8266 defined. the title of your question indicates runtime but the question is about compile time. – Juraj Feb 24 '20 at 09:19

2 Answers2

1

Like you mentioned in your question, the #if defined(__xxxxx__) statements are not actually running on the microcontroller. They're preprocessor directives. The if statements decide which code to pass to the actual compiler, and which ones to omit.

What you can do is write your code to read from the eeprom, but for the section of code that differs between microcontrollers (I'd recommend a separate function for each) you can choose between at compile time.

For example

#ifdef AVR_MICROCONTROLLER

read_from_eeprom(...)
{
  code for the avr chip
}

#else // I'm assuming there's no other options besides avr and esp
read_from_eeprom(...)
{
  code for esp chip
}
#endif

Then when compiling, use a -D flag to specify that you are using AVR or omit the tag for esp.

gcc ... -D AVR_MICROCONTROLLER ...

I sense the reason you asked this question might stem from confusion about where the __AVR_ATmega1280__, etc... tags come from. Basically, they aren't keywords used by the compiler to decide which chip to compile for. They're created by the person(s) who wrote the source file, and they're used for portability so the same file can be used with many different platforms/processors. In my answer I used a command line tag to define the AVR_MICROCONTROLLER tag. Other projects (E.g. Marlin firmware running on arduinos) also have config files full of define statements that can be used to configure exactly how the code is compiled. Long story short, yes the same can be done for other microcontrollers, and you would do it by writing your own preprocessor if statements and then choosing which parameters/variables to set at compile time depending on the chip you want to run the code on.

WindowsNT
  • 83
  • 1
  • 1
  • 6
0
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
//Code in here will only be compiled if an Arduino Mega is used.

Is it possible to do the same for other types of microcontrollers? For example the one in ESP8266? What should I look for?

The mentioned macros are built-in macros provided by avr-gcc. They are used to determine for which device to compile, for example by avr-libc. Actually, these macros are no more built-in in the compiler / preprocessor today but provided by the device-specs file device-specs/specs-<device> that injects respective -D__AVR_<DEVICE>__ to the preprocessor's command line according to -mmcu=<device>.

What you can use for AVR is #ifdef __AVR__ when compiling for AVR and, which is still a built-in macro from avr-gcc / avr-g++.

ESP8266 is a completely different architecture; you would use xtensa-g++ to compile code for that µC and that incarnation of GCC built-in defines __xtensa__ and __XTENSA__ (and definitely not __AVR__).

However, whereas device support in the AVR tools is very sophisticated and hundreds of different -mmcu=<device> options are recognized by avr-gcc, this is not the case for xtensa. You will have to define your own macros if you want to distinguish for different xtensa derivatives.

As avr and xtensa are very different architectures, you can also put the architecture specific stuff in own modules, like eeprom-avr.cpp that provides read_from_eeprom or whatever for avr and is only included in the build when building for avr with avr-g++, and a similar xtensa-only module eeprom-xtensa.cpp that's only included when built with xtensa-g++.

How to programmarically identify if the code is being compiled for AVR or ESP8266?

#if defined (__AVR__)
/* Code for AVR. */
#elif defined (__XTENSA__)
/* Code for ESP8266. */
#else
#error Compiling for unsupported target.
#endif
emacs drives me nuts
  • 2,785
  • 13
  • 23
  • Thank you all for the responses. WindowsNT and Jans you really helped and provided some nice suggestions and idea and helped clarify some confusion my mind. Emacs this is a little higher level than me right now, but I will surely come back and see more into it. Thank you all for the help –  Feb 25 '20 at 01:18
  • Added a code snip at the end that answers your question. – emacs drives me nuts Feb 26 '20 at 08:21