conditional include based on processor type

hi,
i want my program to run on a mega2560 or a due, depending on the user’s choice. because the due does not have EEPROM, i will use the DueFlashStorage library, but i do not want to include the library when the code is compiled for a mega2560.

how can i determine the processor of the current board? i already tried the following, but without success:

  1. based on the code of the ArduinoBoardManager library. compiling for the due works fine, but when i select the arduino mega board, the library is still included.
#if defined __AVR_ATSAM3X8E__
  #include <DueFlashStorage.h>
#endif
#ifdef __AVR_ATmega2560__
  //nothing to do
#else
  #include <DueFlashStorage.h>
#endif
  1. based on response #8 in this thread: http://forum.arduino.cc/index.php?topic=113656.0 . same problem as 1)
#ifdef __AVR_MEGA2560__
  //nothing to do
#else
  #include <DueFlashStorage.h>
#endif

My list shows the DUE processor defined as “SAM3X8E”, not as “AVR_ATSAM3X8E”.

Have you tried:-

#if defined __SAM3X8E__ // DUE
#include <DueFlashStorage.h>
#endif

What IDE version do you use? There was a bug about the #include directive always being processed, this was fixed few months ago, so try with latest IDE.

wergor:
how can i determine the processor of the current board?

Maybe try this:

// this data borrowed from Nick Gammon's "ATmega fuse calculator"
// http://www.gammon.com.au/forum/?id=11653
const uint64_t sigs[] = {
	0x1E910B,0x1E9207,0x1E930C,0x1E9108,0x1E9206,0x1E930B,
	0x1E920A,0x1E930F,0x1E940B,0x1E950F,0x1E940A,0x1E9508,
	0x1E960A,0x1E9608,0x1E9703,0x1E9704,0x1E9801,0x1E9802,
	0x1E9382,0x1E9482,0x1E9389,0x1E9489,0x1E958A,0x1E9488,
	0x1E9587,0x1E9705,0x1E910A,0x1E920D,0x1E9007,0x1E9307,
};

// this data borrowed from Nick Gammon's "ATmega fuse calculator"
// http://www.gammon.com.au/forum/?id=11653
const char *names[] = {
	"ATtiny24","ATtiny44","ATtiny84","ATtiny25","ATtiny45","ATtiny85",
	"ATmega48PA","ATmega88PA","ATmega168PA","ATmega328P","ATmega164P","ATmega324P",
	"ATmega644P","ATmega640","ATmega1280","ATmega1281","ATmega2560","ATmega2561",
	"At90USB82","At90USB162","ATmega8U2","ATmega16U2","ATmega32U2","ATmega16U4",
	"ATmega32U4","ATmega1284P","ATtiny2313A","ATtiny4313","ATtiny13A","ATmega8A",
	"Not found",
};

// AVR signature reader & chip identifier
// (c) 2016 Roger A. Krupski <rakrupski@verizon.net>
// Free code - GPL3 license
void setup (void)
{
	Serial.begin (115200);
	uint8_t x, y, addr;
	uint64_t signature = 0;
	char buffer[32];

	// get AVR signature bytes
	// signature bytes are at 0, 2 and 4
	for (addr = 0; addr < 3; addr++) { // read the 3 bytes
		signature <<= 8; // slide them into the uint64_t
		signature |= boot_signature_byte_get (addr * 2);
	}

	y = (sizeof (sigs) / sizeof (*sigs));
	for (x = 0; x < y; x++) { // check through all
		if (sigs[x] == signature) { // if there's a match
			break; // exit, X==index into chip name (or "not found" if not found).
		}
	}

	// we only print 6 hex characters since a signature is 3 bytes
	sprintf (buffer, "AVR Signature is: 0x%06lX\n", signature); // print signature
	Serial.print (buffer);

	sprintf (buffer, "AVR Part is: %s\n", names[x]); // print CPU name
	Serial.print (buffer);
}

void loop (void)
{
	// nothing
}

It’s a full demo, but all you need is the part that gets you the signature value. If you get 0x1E9801, it’s a MEGA 2560.

I don’t know, however, what this code would do on a DUE… it may crash it. Try and see if this helps.

1 Like

Krupski:
Maybe try this:

// this data borrowed from Nick Gammon's "ATmega fuse calculator"

// Gammon Forum : Electronics : Microprocessors : Atmega Fuse Calculator sketch
const uint64_t sigs = {
0x1E910B,0x1E9207,0x1E930C,0x1E9108,0x1E9206,0x1E930B,
0x1E920A,0x1E930F,0x1E940B,0x1E950F,0x1E940A,0x1E9508,
0x1E960A,0x1E9608,0x1E9703,0x1E9704,0x1E9801,0x1E9802,
0x1E9382,0x1E9482,0x1E9389,0x1E9489,0x1E958A,0x1E9488,
0x1E9587,0x1E9705,0x1E910A,0x1E920D,0x1E9007,0x1E9307,
};

// this data borrowed from Nick Gammon’s “ATmega fuse calculator”
// Gammon Forum : Electronics : Microprocessors : Atmega Fuse Calculator sketch
const char *names = {
“ATtiny24”,“ATtiny44”,“ATtiny84”,“ATtiny25”,“ATtiny45”,“ATtiny85”,
“ATmega48PA”,“ATmega88PA”,“ATmega168PA”,“ATmega328P”,“ATmega164P”,“ATmega324P”,
“ATmega644P”,“ATmega640”,“ATmega1280”,“ATmega1281”,“ATmega2560”,“ATmega2561”,
“At90USB82”,“At90USB162”,“ATmega8U2”,“ATmega16U2”,“ATmega32U2”,“ATmega16U4”,
“ATmega32U4”,“ATmega1284P”,“ATtiny2313A”,“ATtiny4313”,“ATtiny13A”,“ATmega8A”,
“Not found”,
};

// AVR signature reader & chip identifier
// (c) 2016 Roger A. Krupski rakrupski@verizon.net
// Free code - GPL3 license
void setup (void)
{
Serial.begin (115200);
uint8_t x, y, addr;
uint64_t signature = 0;
char buffer[32];

// get AVR signature bytes
// signature bytes are at 0, 2 and 4
for (addr = 0; addr < 3; addr++) { // read the 3 bytes
signature <<= 8; // slide them into the uint64_t
signature |= boot_signature_byte_get (addr * 2);
}

y = (sizeof (sigs) / sizeof (*sigs));
for (x = 0; x < y; x++) { // check through all
if (sigs == signature) { // if there’s a match
break; // exit, X==index into chip name (or “not found” if not found).
}
}

// we only print 6 hex characters since a signature is 3 bytes
sprintf (buffer, “AVR Signature is: 0x%06lX\n”, signature); // print signature
Serial.print (buffer);

sprintf (buffer, “AVR Part is: %s\n”, names); // print CPU name
Serial.print (buffer);
}

void loop (void)
{
// nothing
}




It's a full demo, but all you need is the part that gets you the signature value. If you get 0x1E9801, it's a MEGA 2560.

I don't know, however, what this code would do on a DUE... it may crash it. Try and see if this helps.

There’s one thing missing from the code above.
This:-

#include <avr/boot.h>

But isn’t it only useful at runtime, rather than at compile-time for conditional compilation?

OldSteve:
There’s one thing missing from the code above.
This:-

#include <avr/boot.h>

But isn’t it only useful at runtime, rather than at compile-time for conditional compilation?

Strange. I don’t have <avr/boot.h> in the code and it compiles for me… and I found out why… I have it in my Arduino.h file. Oops… sorry.

To answer your question, yes it works at runtime. I don’t have any experience with the DUE, so I just put this out in case it would help… I wasn’t sure exactly what the OP needed, so I guessed. :slight_smile:

Krupski:
Strange. I don’t have <avr/boot.h> in the code and it compiles for me… and I found out why… I have it in my Arduino.h file. Oops… sorry.
To answer your question, yes it works at runtime. I don’t have any experience with the DUE, so I just put this out in case it would help… I wasn’t sure exactly what the OP needed, so I guessed. :slight_smile:

It’s a handy little utility. I’ve saved a copy for future reference/use. Thanks for putting in the effort.
(And I’ve never used a Due either.)

guix:
What IDE version do you use? There was a bug about the #include directive always being processed, this was fixed few months ago, so try with latest IDE.

Hi,

i was using 1.6.5r2, updating to 1.6.7 fixed the issue. Thanks!

OldSteve:
My list shows the DUE processor defined as “SAM3X8E”, not as “AVR_ATSAM3X8E”.

Have you tried:-

#if defined __SAM3X8E__ // DUE

#include <DueFlashStorage.h>
#endif

you are right, SAM3X8E is the correct label. where did you find that information?

Krupski:
Maybe try this:
[…]
It’s a full demo, but all you need is the part that gets you the signature value. If you get 0x1E9801, it’s a MEGA 2560.

I don’t know, however, what this code would do on a DUE… it may crash it. Try and see if this helps.

its not possible to compile for the mega if the DueFlashStorage library is included, so checking at runtime is not an option.

wergor:
you are right, SAM3X8E is the correct label. where did you find that information?

It might be in a different place for you, now that you've upgraded, but for me using V1.6.5, I originally found it in "\Arduino\libraries\Firmata\Boards.h"
Here's the list that I have:-

Found in "\Arduino\libraries\Firmata\Boards.h":-
----------------------------------------------------------
__AVR_ATmega328P__ : UNO, Arduino Duemilanove, Diecimila, and NG
__AVR_ATmega168__ : Arduino Duemilanove, Diecimila, and NG
__AVR_ATmega8__ : old Arduinos
__AVR_ATmega1280__ : Mega
__AVR_ATmega2560__ : Mega
__SAM3X8E__ : DUE
__AVR_AT90USB162__ : Teensy 1.0
if defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY) : Teensy 2.0
if defined(__MK20DX128__) || defined(__MK20DX256__) : Teensy 3.0 and 3.1
if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) : Teensy++ 1.0 and 2.0
__AVR_ATmega32U4__ : Leonardo
ARDUINO_LINUX : Intel Galileo
if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)|| defined(__AVR_ATmega1284P__) : Sanguino
__AVR_ATmega645__ : Illuminato
__AVR_ATtiny45__
__AVR_ATtiny85__
__AVR_ATtiny24__
__AVR_ATtiny44__
__AVR_ATtiny84__

*** Also see "\Arduino\hardware\arduino\avr\bootloaders\stk500v2\avr_cpunames.h"
1 Like

OldSteve:
It might be in a different place for you, now that you've upgraded, but for me using V1.6.5, I originally found it in "\Arduino\libraries\Firmata\Boards.h"

found it. thanks!