2

In reading various code I stumble across symbols that seem to be the result of #define or other macro like symbols that I cannot find just by tracking through the code ( including its chain, if any, of includes ).

Can someone offer some reasonably simple, but complete, guidance on how the arduino ide works with especially emphasis on automatically included files ( and their location ) and any other automagically appearing stuff.

5
  • The Arduino IDE handles very few of these itself. Try looking at what AVR-GCC does. Mar 6 '15 at 15:29
  • 2
    On Linux, I usually just grep -l FOO /usr/share/arduino/hardware/arduino/cores/arduino/*.h or grep -lr FOO /usr/lib/avr/include/. Mar 6 '15 at 16:57
  • Most of the #defines happen an Arduino.h and the board variant files, although a few are passed as compiler arguments if you still can't find anything.
    – BrettAM
    Mar 6 '15 at 17:12
  • I usually do a search on the github page (github.com/arduino/Arduino/tree/master/hardware/arduino/avr/…)
    – Gerben
    Mar 6 '15 at 17:23
  • Arduino inclusion is dark magic mixed with randomness... I haven't been able to find a consistent include "scheme" for Arduino, although I haven't poked around in the source. Mar 6 '15 at 23:26
4

It might help to point out the use of -D switches of gcc here. If you turn on verbose output of the Arduino IDE (I am using a pretty old version):

Arduino IDE preferences

you will see, when you compile a sketch, that the compiler is not only called with a switch -m (e.g. -mmcu=atmega328p) which describes the target (i.e. the ATMEL AVR instruction set or MCU type) for which the code is compiled, but also with a number of -D switches.

The -D switches predefine a name as a macro and also that depend on the target.

You might see for example

-DF_CPU=16000000L -DARDUINO=100

where F_CPU is used to pass information about the target's clock speed (16 MHz in this case) to code that depends on this, e.g. the delay function or the Serial library.

3 ways to define macros

In general, the confusion might come from the fact that including files in the Arduino build chain depends a lot on compiler flags, and there are several ways to define these:

  1. #define
  2. using -D switches
  3. from the target specification (compiler built-in, -m)

The last point means that the above mentioned -matmega328p defines the macro __AVR_ATmega328P__ which is e.g. used in io.h to include the appropriate file with pin mappings, RAM sizes etc. (Google for avr-mcus.def to find a full list of these predefined macros for AVR targets.)

Finally, note that the Arduino IDE also sets include paths depending on the target. The appropriate set of pin definitions is selected by passing an include path like this to avr-g++:

-I/usr/share/arduino/hardware/arduino/variants/standard

where standard is replaced by leonardo, micro, mega etc.

Short answer / summary / how to debug

First, to generate a list of the current #define directives, use the -dM option like this (compiling an empty program that is specified to be C with -x c):

echo | avr-gcc -x c -E -dM -mmcu=atmega328p - | sort

Change -mmcu=atmega328p to your needs (you can also leave it out).

Second, you can use the option -g3 to include the macro definitions in the output. Keep the intermediate files by using -save-temps. You can append these to the compiler call by the IDE:

avr-g++ -c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega168 -DF_CPU=8000000L -DARDUINO=100 -I/usr/share/arduino/hardware/arduino/cores/arduino -I/usr/share/arduino/hardware/arduino/variants/standard /tmp/build5017602110288.tmp/SerialManual.cpp -o/tmp/build5017602110288.tmp/SerialManual.cpp.o -save-temps -g3

which will create a long output file *.ii (here SerialManual.ii) that lists among others the defines and typedefs and, most importantly, from which files they come.

Sample output:

# 1 "/tmp/build501760211028815624.tmp/SerialManual.cpp"
# 1 "/tmp/1//"
# 1 "<built-in>"
#define __STDC__ 1
#define __cplusplus 1
#define __AVR_ATmega168__ 1
#define __CHAR16_TYPE__ short unsigned int
...
# 1 "<command-line>"
#define F_CPU 8000000L
#define ARDUINO 100
...
# 1 "/usr/lib/gcc/avr/4.5.3/../../../avr/include/avr/iom168.h" 1 3
# 34 "/usr/lib/gcc/avr/4.5.3/../../../avr/include/avr/iom168.h" 3
#define _AVR_IOM168_H_ 1
#define SPM_PAGESIZE 128
#define RAMSTART (0x100)
#define RAMEND 0x4FF
#define XRAMEND RAMEND
#define E2END 0x1FF
#define E2PAGESIZE 4
#define FLASHEND 0x3FFF
...
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.