Bootloader resetting important registers.
The Arduino IDE lasted about five minutes before I reverted to my usual
editor and makefiles, but Geany seems a nice lightweight IDE if you want
one. Martin Oldfield wrote a useful set of Makefiles integrated with the
Arduino libraries, but someone else is now maintaing them
(
https://github.com/sudar/Arduino-Makefile).
Getting the reset flags for the ATmega 328 is relatively straightforward,
but I've never used a 2560. Optiboot 5.0 has the code:
void appStart(uint8_t rstFlags) {
// save the reset flags in the designated register
// This can be saved in a main program by putting code in .init0 (which
// executes before normal c init code) to save R2 to a global variable.
__asm__ __volatile__ ("mov r2, %0\n" :: "r" (rstFlags));
watchdogConfig(WATCHDOG_OFF);
__asm__ __volatile__ (
#ifdef VIRTUAL_BOOT_PARTITION
// Jump to WDT vector
"ldi r30,4\n"
"clr r31\n"
#else
// Jump to RST vector
"clr r30\n"
"clr r31\n"
#endif
"ijmp\n"
);
}
Which means that if storage is allocated in the main program, the reset
flags can be read with the following function:
/**
** @note
** Storage for the contents of the MCUSR (which must be cleared during system
** initialization to ensure that continuous watchdog resetting doesn't occur;
** see
http://www.nongnu.org/avr-libc/user-manual/group__avr__watchdog.html for
** details). This can be used to investigate the cause of a reset on reboot.
*/
uint8_t MCUSR_value __attribute__ ((section (".noinit")));
/** The Optiboot version number, if available */
uint16_t VERSION_value __attribute__ ((section (".noinit")));
/* Backup and clear the MCUSR register early in the AVR boot process */
void store_mcusr(void) \
__attribute__ ((naked)) \
__attribute__ ((section(".init3")));
/**
** Park the MCUSR register value and the Optiboot version
** number somewhere accessible
**
** @remark No parameters
** @return Nothing
** @note Optiboot 5 moves the MCUSR value to register R2, so
** store_mcusr() must be run before main(), which is done
** by placing it in one of avr-gcc's .init sections.
** Note that the Optiboot version number is available only
** in recent Optiboot code.
**
** @internal s t o r e _ m c u s r
*/
void store_mcusr(void)
{
/* Disable the WDT in case it's just forced a reset */
wdt_disable();
MCUSR = 0x0; /* Also zeroed in optiboot */
__asm__ __volatile__ (
"mov %0, r2\n"
: "=r" (MCUSR_value)
:);
__asm__ __volatile__ (
"ldi r31, 0x7f\n"
"ldi r30, 0xfe\n"
"lpm %A0, Z+\n"
"lpm %B0, Z\n"
: "=r" (VERSION_value)
:);
return;
}
and somewhere in main() we then have:
#ifdef DEBUG
Serial.print(F("Optiboot version: 0x"));
Serial.println(VERSION_value, HEX);
/* Report the MCUSR register value */
Serial.print(F("Reset type: "));
switch (MCUSR_value & 0xff) {
case 1:
Serial.println(F("Power On"));
break;
case 2:
Serial.println(F("External"));
break;
case 4:
Serial.println(F("Brownout"));
break;
case 8:
Serial.println(F("Watchdog"));
break;
default:
Serial.println(F("Unknown"));
Serial.print(F("MCUSR register : 0x"));
Serial.println(MCUSR_value, HEX);
break;
}
#endif
Will