How to limit compile/run to 328P?

If you say that code is written for a Nano or an Uno, that no longer limits it to the 328P processor - because, for example, there's also the Nano ESP32, 33 IOT, 33 BLE, Every, and RP2040.

Is there a compiler directive that would cause the IDE to error out, and refuse to compile, if the selected board's processor is not the 328P?

Similarly, is there a way the code itself in runtime can detect what processor it's running on? The 328P is supposed to have a signature of 1E950F. Can my code read that?

Not sure why you want to do that. See if this helps.

Your code, if written for ATmega328x, can read only the signature of certain types of AVR-based processors.

Certain symbols are defined based on the Arduino board selection, and your code can check for the correct value. Unfortunately you have to know what that value is. Some examples from the Timer1 library follow:

// interrupt service routine that wraps a user defined function supplied by attachInterrupt
#if defined (__AVR_ATtiny85__)
ISR(TIMER1_COMPA_vect)
{
  Timer1.isrCallback();
}
#elif defined(__AVR__)
ISR(TIMER1_OVF_vect)
{
  Timer1.isrCallback();
}
#elif defined(__arm__) && defined(TEENSYDUINO) && (defined(KINETISK) || defined(KINETISL))
void ftm1_isr(void)
{
  uint32_t sc = FTM1_SC;
  #ifdef KINETISL
  if (sc & 0x80) FTM1_SC = sc;
  #else
  if (sc & 0x80) FTM1_SC = sc & 0x7F;
  #endif
  Timer1.isrCallback();
}
#elif defined(__arm__) && defined(TEENSYDUINO) && defined(__IMXRT1062__)
void TimerOne::isr(void)
{
  FLEXPWM1_SM3STS = FLEXPWM_SMSTS_RF;
  Timer1.isrCallback();
}

#endif
1 Like

If I put in the code this test:

#if !(defined(__AVR_ATmega328P__))

what could I put after it to cause the compile to abort, with an error message?

Each of those boards will have a different name, that can be checked in the code:

#if !defined(__AVR_ATmega328P__) || !defined(ARDUINO_AVR_NANO)
#error "wrong board type"
#endif

Nano ESP32 is ARDUINO_NANO_ESP32
33 IOT is ARDUINO_SAMD_NANO_33_IOT
Nano Every is ARDUINO_AVR_NANO_EVERY

The name comes from appending the name given in the board.txt file as the build.board to "ARDUINO_".

Ok, I guess we were typing at the same time. So just the simple #error aborts the compile. Thank very much.

Edit: Well, I don't want to test the board. I want to test the processor. Anyway, I can experiment and see what works for 328P.

Yes.

If you eneable Show verbose output dring compilation under file → preferences* in the IDE you can find all defines that influence the compilation; search for -D.

E.g. for a Nano on of the line is:

C:\Users\bugge\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR -IC:\Users\bugge\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino -IC:\Users\bugge\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\variants\eightanaloginputs C:\Users\bugge\AppData\Local\arduino\sketches\FAFFEC072F2A06E1568EBB7D1D709EE1\sketch\sketch_mar8a.ino.cpp -o nul

In your code you can use something like

#ifndef ARDUINO_AVR_NANO
#error Nano only
#endif

void setup() {
}

void loop() {
}

The result when you compile for a Nano 33 BLE

...
...
C:\Users\bugge\AppData\Local\Temp\.arduinoIDE-unsaved202528-15252-1gb24kb.0ljg\sketch_mar8a\sketch_mar8a.ino:2:2: error: #error Nano only
 #error Nano only
  ^~~~~
exit status 1

Compilation error: #error Nano only

For the runtime test, I found this code from Kevin Darrah:

// Dump the signature block from an Uno, Nano or Pro Mini
// to help detect counterfeit Atmega328P chips.
// See https://www.youtube.com/watch?v=eeDC1m7ANJI
// for how to interpret the output.
// Thanks to Kevin Darrah for this code and the video.

#include <avr/boot.h>
#define SIGRD 5
void setup() {
  Serial.begin(9600);
  Serial.println("");
  Serial.println("boot sig dump");
  int newLineIndex = 0;
  for (uint8_t i = 0; i <= 0x1F; i += 1) {
    Serial.print(boot_signature_byte_get(i), HEX);
    Serial.print("\t");
    newLineIndex++;
    if (newLineIndex == 8) {
      Serial.println("");
      newLineIndex = 0;
    }
  }
  Serial.println();
}

void loop() {
}

I wouldn't need the whole block, just the three signature bytes. Anyway, this looks pretty straightforward. However, I don't know what would happen if I tried this on a processor on which it doesn't work. So I think the compile test may be the best option.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.