Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remote reboot #180

Closed
Pavel-vo opened this issue Mar 11, 2016 · 16 comments
Closed

Remote reboot #180

Pavel-vo opened this issue Mar 11, 2016 · 16 comments
Labels
Discussion More conversation than actual bug or change. Duplicate There's already an open issue for this bug Priority-Low Type-Enhancement

Comments

@Pavel-vo
Copy link

Hi,

I want to upload arduino sketch over the air.
My arduino's (pro mini 8M) rx tx pins connected to bluetooth HC-05. I've made software, witch handle avrdude's events and sends special command (e.g. RESET\n). When arduino receive this command, it must reboot and wait new sketch. It works well with 1 wire connected to the RESET pin. But when I do the same without a wire, but with watchdog and when I call wdt_enable(WDTO_15MS); I don't see flashing of onboard LED. Program just restart without entering to stk500 command mode.
It would be perfect if I had something like this:

go_to_bootloader_this_time();
wdt_enable(WDTO_15MS);

But I don't know how to set MCUSR flag correct and come over this expression in optiboot.c file.

...
if (ch & (_BV(WDRF) | _BV(BORF) | _BV(PORF)))
      appStart(ch);
...

Do you have any ideas?

@majekw
Copy link
Contributor

majekw commented Mar 11, 2016

You'll need to clear MCUSR and jump to bootloader directly without using watchdog.

Something like that (should work, not tested):

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

MCUSR=0;
do_reboot();

@Pavel-vo
Copy link
Author

What is the address (FLASHEND-511)>>1?

@Pavel-vo
Copy link
Author

When I call do_reboot(); I can see led blinking which signal entering of bootloader. I see that the firmware uploading process has started, but not finished. It stops on the first <STK_PROG_PAGE...> command, and got reply <STK_INSYNC>, but it should be <STK_INSYNC, STK_OK>.
A few seconds later avrdude reports

avrdude: stk500_recv(): programmer is not responding

I'v tried different serial rates - 19200 and 57600, result is the same.
What can it be?

@majekw
Copy link
Contributor

majekw commented Mar 11, 2016

What is the address (FLASHEND-511)>>1?

Optiboot typically (on Atmega328) fits in last 512 bytes of memory, so FLASHEND-511 is first location of bootloader. Because AVR use word adressing, so that's why it's divided by two (>>1).

About you issue: Optiboot assumes few things to minimize size. I think it could be problem with enabled interrupts. If I'm right, placing cli() (or noInterrupts() in Arduino) before do_reboot() should fix this.

@Pavel-vo
Copy link
Author

Great, cli() and noInterrupts() both help. Thank you.

@Pavel-vo
Copy link
Author

I guess the first location of bootloader address must be saved somewhere. I want to make general solution for other arduino boards. Is it possible to read it from the memory or get constant pointed to the address?

@majekw
Copy link
Contributor

majekw commented Mar 11, 2016

Nice to hear that it works :-)

About location: you could always read fuses and interpret it for every chip - hardcore way :-)

But for standard Optiboot (without VIRTUAL_BOOT_PARTITION and BIGBOOT for smaller chips) it could be much easier: just check in #ifdef for RAMPZ and use 1023 for chips with it, and 511 otherwise.
Similar to this: https://github.com/majekw/optiboot/blob/supermaster/optiboot/examples/flash_program/optiboot.h#L80-L86

@WestfW
Copy link
Member

WestfW commented Mar 12, 2016

You can derive the bootloader start address from the fuse bits (which can be read by an application.)
Except that different fuse bits mean different sizes depending on which chip you have, and I don't see any standard mechanism (say, via #defines in ioXX.h) for doing the conversions.

Note that there are still ATmega328 Arduino boards that use the older (2k) bootloader...

@Pavel-vo
Copy link
Author

Thanks for your help!
Jump to bootloader is even better than reset for my project, because it's easier to control bluetooth module power by arduino pin.

@Pavel-vo
Copy link
Author

Please tell me, that it's not possible to get optiboot baudrate from code? I just want to be sure.

@miketedeschi
Copy link

I am also trying to remotely upload sketches (without physical access to the slave AVR). I tried the jump to bootloader code (suggested by @majekw ) which seems to partially work but the bootloader flashing LEDs blink way too rapidly, and I cannot upload, almost like the bootloader is running in hyperspeed. (maybe because the chip is really a 328PB running a bootloader claiming to be a 328p, i dunno)

I believe I have a safe solution that will allow a watchdog to reset into the bootloader, but I am stuck on manually setting the MCUSR flags in the application, if that's possible.

if (!(ch & _BV(EXTRF))) appStart();

With the above modification (taken from post 3 here) the only thing that matters is the external reset flag. The key is being able to set the _BV(EXTRF flag manually within the application when a special packet is received over the RS485 link. This would effectively "fake" an external reset (for the next boot only) since my bootloader no longer cares if the watchdog was used.

@WestfW
Copy link
Member

WestfW commented Nov 28, 2016

You can't set bits in MCUSR from a program; you can only clear them.

@miketedeschi
Copy link

You can't set bits in MCUSR from a program; you can only clear them.
well that explains why I can't find out how to do it, thank you.

there must be a way to use the watchdog to get into the bootloader to upload a sketch. I guess I will look into using GPIO registers or eeprom, unless someone else sees some glaring problem there too.

@WestfW WestfW added Discussion More conversation than actual bug or change. Priority-Low Type-Enhancement Duplicate There's already an open issue for this bug labels Dec 19, 2016
@WestfW
Copy link
Member

WestfW commented Jul 27, 2018

With v7, you can now set MCUSR to zero and jump to the bootloader start address.
See examples/test_reset.ino
You do need to be careful to disable interrupts and reset some timer registers to the default values, or things may behave strangely, and I've still occasionally seen odd behavior that I'm going to claim is the fault of the application for not cleaning up, rather than optiboot.

@WestfW WestfW closed this as completed Jul 27, 2018
@nuxeh
Copy link

nuxeh commented Mar 24, 2023

With v7, you can now set MCUSR to zero and jump to the bootloader start address.

I have tried this (for a similar bluetooth flashing scenario as the original issue) and it works very well.

I set MCUSR to zero prior to jumping to the bootloader, but the only issue I have remaining is that optiboot doesn't exit after successfully flashing. I have the flash-on-data option enabled, so the LED continuously flashes, and it continuously sends mostly zeroes over serial. Superficially the reason might appear to be that the watchdog reset which should run the sketch never happens, somehow, though I can't think why.

Any ideas?

EDIT: may be relevant that I'm running master (55d1e6b) and using the TIMEOUT=4 build option.
UPDATE: also tried master with no timeout option, and v8.0, with the same effect
UPDATE: using the watchdog disable at sketch start (from the reset example), not setting MCUSR to zero, but keeping the value set by the example code at startup (MCUSR = ~(1 << WDRF)) seems to work, though no idea why.

@WestfW
Copy link
Member

WestfW commented Mar 25, 2023

Did you do the whole "reset peripherals and disable interrupts before jumping to the bootloader" (that would include disabling the watchdog, if you had turned it on.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Discussion More conversation than actual bug or change. Duplicate There's already an open issue for this bug Priority-Low Type-Enhancement
Projects
None yet
Development

No branches or pull requests

5 participants