Optiboot / optiboot

Small and Fast Bootloader for Arduino and other Atmel AVR chips
Other
1.08k stars 396 forks source link

Run bootloader after a software reset #350

Open ghost opened 1 year ago

ghost commented 1 year ago

For a custom board I cannot relay on a hardware reset. The running application will reset the MCU when receives a specific string. My need is to enter the bootloader not only at power on, but also on software reset. I looked at the options here, but I can't find nothing about.

Is there anything ready (perhaps undocumented) or it's like a "feature request" and I have to change the code?

WestfW commented 1 year ago

You can do this, but you need to be careful to:

  1. Disable interrupts and interrupt sources (eg timers) that may be running in the application.
  2. Make sure the MCUSR (reset reason) is zeroed.
  3. Derive the correct start address for optiboot (FLASHEND-BOOTLOADERSIZE. Or maybe derived from reading the fuses?)

There is an example here: https://github.com/Optiboot/optiboot/blob/master/optiboot/examples/demo_reset/demo_reset.ino#L129 (it should still work...)

aviatorhh commented 2 months ago

Can this still be confirmed working by someone? I tried it on an ATmega328P

void reset() {
        typedef void (*do_reboot_t)(void);
        const do_reboot_t do_reboot = (do_reboot_t)((FLASHEND - 511) >> 1);

        cli(); TCCR0A = TCCR1A = TCCR2A = 0; // make sure interrupts are off and timers are reset.
        MCUSR = 0;
        do_reboot();
}

but with no joy. The system seems to hang with a flickering LED (Uno Board). I wanted to run avrdude after a remotely triggered software reset. I tried FLASHEND - 1023 and also 2047 - too lazy to read the fuses at the moment :-)

WestfW commented 2 months ago

Hmm. Doesn't work here either. I'm using a modified ASCIITable sketch for testing, and there are some signs that perhaps the UART ISR is getting called before things are fully initialized, but even with added code that should be making sure that the UART is disabled before the do_reboot(), it still fails.