Issue: Infinite WDT Reset Loop After Software Jump into Bootloader
Summary
When an application forces a jump into Optiboot via software (after clearing MCUSR), Optiboot runs and waits for STK500 traffic. If a timeout occurs, Optiboot correctly triggers a Watchdog Timer (WDT) reset. However, after this reset, Optiboot evaluates the WDRF flag, decides to immediately jump back to the application (APP_START_REASONS), but fails to disable the watchdog before doing so. This traps the application in a rapid ~15ms WDT reset loop unless the application itself explicitly calls wdt_disable() extremely early during initialization.
Scenario Description
Step 1: Application Initiates Jump
The application requests the bootloader by clearing MCUSR and jumping to the bootloader section:
MCUSR = 0;
// Example: jump to (FLASHEND - 511) >> 1
jumpToBootloader();
Step 2: Optiboot Runs
- Optiboot initializes normally (LED flashes).
- Optiboot waits for STK500 protocol communication (usually a 1-second timeout).
Step 3: Timeout Occurs → WDT Reset Triggered
With no upload traffic arriving, the WDT expires. The MCU resets and returns to Optiboot.
Step 4: The Problem
Upon this reset, MCUSR contains WDRF (but not EXTRF). Based on the Optiboot logic, Optiboot decides to skip the bootloader and jump straight to the application. Critical Error: In this specific code path, the watchdog is not reliably disabled before handing control back to the application.
Actual Behavior
Optiboot jumps to the application while the 15ms watchdog is still armed and ticking. The MCU behaves as follows:
- Application starts.
- ~15ms later: WDT triggers a reset.
- Optiboot checks
MCUSR, sees WDRF again, and jumps straight back to the application.
- ~15ms later: WDT triggers a reset.
(Result: Infinite rapid reset loop, observable as a ~15Hz flickering LED)
Expected Behavior
Whenever Optiboot decides to hand control back to the application, it must ensure a pristine environment—this strictly includes disabling the Watchdog Timer, exactly as it does on a normal successful upload or when exiting via other paths.
Root Cause Analysis in Optiboot Source
Optiboot attempts to disable the watchdog via WDTCSR but does not reliably clear WDRF in MCUSR on all code paths that jump to the application. On some AVR hardware states, if WDRF is set in MCUSR, the watchdog remains effectively active even if WDTCSR writes attempt to clear WDE. As a result, Optiboot may hand control back to the application with a still-armed short-period watchdog.
Steps to Reproduce
- Flash an ATmega328P with standard Optiboot.
- Upload a sketch that does NOT implement an early
.init3 watchdog disable routine.
- Trigger a software bootloader jump (
MCUSR = 0; asm("jmp 0x7E00");).
- Wait 1 second for the Optiboot timeout.
- Observe the MCU enter a rapid reset loop (LED pulsing at high frequency).
- Press the physical RESET button (sets
EXTRF). The application will then boot normally because EXTRF fulfills the condition that allows Optiboot to properly disable the WDT.
Suggested Fix
Optiboot must ensure the watchdog is disabled before jumping to the application in all exit paths. Possible remedies:
- Unconditionally clear
WDRF from MCUSR before calling watchdogConfig(WATCHDOG_OFF) and before any direct appstart jump.
- Or, add an explicit
watchdogConfig(WATCHDOG_OFF) sequence that is guaranteed to take effect even when WDRF is present (for example, using the documented sequence to disable WDT on affected AVR devices).
Notes
This issue arises specifically when the bootloader has been reached via a software-initiated jump and then times out waiting for STK500 traffic. Physical RESET (EXTRF) or a normal bootloader upload path do not show the same loop because the reset reason and clearing sequence differ.
Issue: Infinite WDT Reset Loop After Software Jump into Bootloader
Summary
When an application forces a jump into Optiboot via software (after clearing
MCUSR), Optiboot runs and waits for STK500 traffic. If a timeout occurs, Optiboot correctly triggers a Watchdog Timer (WDT) reset. However, after this reset, Optiboot evaluates theWDRFflag, decides to immediately jump back to the application (APP_START_REASONS), but fails to disable the watchdog before doing so. This traps the application in a rapid ~15ms WDT reset loop unless the application itself explicitly callswdt_disable()extremely early during initialization.Scenario Description
Step 1: Application Initiates Jump
The application requests the bootloader by clearing
MCUSRand jumping to the bootloader section:Step 2: Optiboot Runs
Step 3: Timeout Occurs → WDT Reset Triggered
With no upload traffic arriving, the WDT expires. The MCU resets and returns to Optiboot.
Step 4: The Problem
Upon this reset,
MCUSRcontainsWDRF(but notEXTRF). Based on the Optiboot logic, Optiboot decides to skip the bootloader and jump straight to the application. Critical Error: In this specific code path, the watchdog is not reliably disabled before handing control back to the application.Actual Behavior
Optiboot jumps to the application while the 15ms watchdog is still armed and ticking. The MCU behaves as follows:
MCUSR, seesWDRFagain, and jumps straight back to the application.(Result: Infinite rapid reset loop, observable as a ~15Hz flickering LED)
Expected Behavior
Whenever Optiboot decides to hand control back to the application, it must ensure a pristine environment—this strictly includes disabling the Watchdog Timer, exactly as it does on a normal successful upload or when exiting via other paths.
Root Cause Analysis in Optiboot Source
Optiboot attempts to disable the watchdog via
WDTCSRbut does not reliably clearWDRFinMCUSRon all code paths that jump to the application. On some AVR hardware states, ifWDRFis set inMCUSR, the watchdog remains effectively active even ifWDTCSRwrites attempt to clearWDE. As a result, Optiboot may hand control back to the application with a still-armed short-period watchdog.Steps to Reproduce
.init3watchdog disable routine.MCUSR = 0; asm("jmp 0x7E00");).EXTRF). The application will then boot normally becauseEXTRFfulfills the condition that allows Optiboot to properly disable the WDT.Suggested Fix
Optiboot must ensure the watchdog is disabled before jumping to the application in all exit paths. Possible remedies:
WDRFfromMCUSRbefore callingwatchdogConfig(WATCHDOG_OFF)and before any directappstartjump.watchdogConfig(WATCHDOG_OFF)sequence that is guaranteed to take effect even whenWDRFis present (for example, using the documented sequence to disable WDT on affected AVR devices).Notes
This issue arises specifically when the bootloader has been reached via a software-initiated jump and then times out waiting for STK500 traffic. Physical RESET (EXTRF) or a normal bootloader upload path do not show the same loop because the reset reason and clearing sequence differ.