The way I read the ATmega328 datasheet, I expected to find only one flag set:
• Bit 3 – WDRF: Watchdog System Reset Flag
This bit is set if a Watchdog System Reset occurs. The bit is reset by a Power-on Reset, or by writing a logic zero
to the flag.
• Bit 2 – BORF: Brown-out Reset Flag
This bit is set if a Brown-out Reset occurs. The bit is reset by a Power-on Reset, or by writing a logic zero to the
flag.
• Bit 1 – EXTRF: External Reset Flag
This bit is set if an External Reset occurs. The bit is reset by a Power-on Reset, or by writing a logic zero to the flag.
• Bit 0 – PORF: Power-on Reset Flag
This bit is set if a Power-on Reset occurs. The bit is reset only by writing a logic zero to the flag.
To make use of the Reset Flags to identify a reset condition, the user should read and then Reset the MCUSR as
early as possible in the program. If the register is cleared before another reset occurs, the source of the reset can
be found by examining the Reset Flags.
Instead I find that pressing the reset button sets only EXTRF, power on sets BORF and PORF, and if I hold the reset button down while powering on, all three are set.
My question then is how to interpret the flags to determine "the" source of the reset. I'm thinking right-to-left, e.g. if PORF is set, then assume a power-on reset, and disregard the other flags.
I'm testing with the following code, programming with an ICSP (no bootloader), I just have LEDs connected to PORTD.
void setup(void)
{
uint8_t mcusr = MCUSR;
MCUSR = 0;
DDRD = 0xFF;
PORTD = mcusr;
}
void loop(void)
{
}
I didn't think the Arduino core had any bearing on this, but just to verify, I tried the following with WinAVR, and indeed the results are identical.
#include <avr/io.h>
int main(void)
{
uint8_t mcusr = MCUSR;
MCUSR = 0;
DDRD = 0xFF;
PORTD = mcusr;
for (;;);
return 0;
}