1
0
mirror of https://github.com/Optiboot/optiboot.git synced 2025-07-03 05:42:30 +03:00

Add test_reset example demonstrating/testing reset cause determination

This commit is contained in:
WestfW
2015-05-25 22:54:45 -07:00
parent 51ee0789fd
commit 50ad43feb9

View File

@ -0,0 +1,82 @@
/*
* test_reset
* May 2015 by Bill Westfield (WestfW)
* Released to the public domain.
*
* This sketch demonstrates retrival of the Reset Cause register (MCUSR) of the AVR.
* Normally, MCUSR itself is destroyed by the use of a bootloader, but Optiboot v4.6
* and later save the contents in register r2, where it can be accessed by an
* application.
*/
#include <avr/wdt.h>
/*
* First, we need a variable to hold the reset cause that can be written before
* early sketch initialization (that might change r2), and won't be reset by the
* various initialization code.
* avr-gcc provides for this via the ".noinit" section.
*/
uint8_t resetFlags __attribute__ ((section(".noinit")));
/*
* Next, we need to put some code to save reset cause from the bootload (in r2)
* to the variable. Again, avr-gcc provides special code sections for this.
*/
void resetFlagsInit(void) __attribute__ ((naked))
__attribute__ ((section (".init0")));
void resetFlagsInit(void)
{
/*
* save the reset flags passed from the bootloader
* This is a "simple" matter of storing (STS) r2 in the special variable
* that we have created. We use assembler to access the right variable.
*/
__asm__ __volatile__ ("sts %0, r2\n" : "=m" (resetFlags) :);
}
void setup() {
Serial.begin(9600); // Initialize serial port
}
void loop() {
Serial.println("Reset flag test");
while (Serial.read() < 0)
; // wait for some type-in
Serial.print("Have reset flag value 0x");
Serial.print(resetFlags, HEX);
/*
* check for the usual bits. Note that the symnbols defined in wdt.h are
* bit numbers, so they have to be shifted before comparison.
*/
switch (resetFlags) {
case 1<<WDRF:
Serial.println(" (Watchdog)\n");
break;
case 1<<BORF:
Serial.println(" (Brownout)\n");
break;
case 1<<EXTRF:
Serial.println(" (External Reset)\n");
break;
case 1<<PORF:
case ((1<<PORF) | (1<<BORF)):
// A poweron can frequently result in both PORF and BORF being set, as the
// power switch bounces or the voltage rises slowly.
Serial.println(" (PowerOn)\n");
break;
default:
// Multiple bits can be set under various circumstances. For example, the
// "hold down reset while powering up" trick used to recover from certain
// problems can leave both PORF and EXTRF set.
Serial.println(" (Unknown)\n");
break;
}
/*
* Now we'll let the Watchdog reset the chip, and see if that cause is reported
* correctly. Older versions of optiboot could not easily distinguish between
* WDRF and EXTRF resets, since the WDT was used inside the bootloader.
*/
wdt_enable(WDTO_1S);
}