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?
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
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.
...
...
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.