Can't re-flash without reset for larger program

How to reproduce:

  1. Create a large array that uses a lot of RAM.
  2. Have a tight-ish loop that constantly changes the values in that array.
  3. Try to reflash.
  4. Fails.

This seems to be because the 1200 baud trick doesn’t directly reset the chip but rather turns on the watchdog reset and let it reset the chip 120ms later… and if the baud rate changes again then it turns the watchdog timer off… the comments in CDC.cpp note:

// Most OSs do some intermediate steps when configuring ports and DTR can
// twiggle more than once before stabilizing.
// To avoid spurious resets we set the watchdog to 250ms and eventually
// cancel if DTR goes back high.

From what I can tell the problem is where the magic “bootloader mode vs app mode” flag is stored:

volatile uint16_t *const bootKeyPtr = (volatile uint16_t *)0x0800;

This seems to be 2k into RAM (or perhaps lower if the registers and IO ports are mapped into lower RAM, I forget how the addressing scheme works). Either way what is the point of placing this at 2k… why not at the very top of RAM? Or why not reserve a single byte or two of RAM for this flag. No matter where you put it it seems it risks working incorrectly if the RAM isn’t reserved.


Update: Yeah, looks like SRAM runs from 0x100 to 0xAFF in the address range. “google: (0x800-0x100) in base 10”… Looks like memory location 1,792. What is the logic behind this.

I think @dragula96 has also run into this. Seems like as issue a lot of people are going to hit if we hope for some ambitious software.

Update #2: Looks like this is a known issue:

1 Like

Thanks Dreamer3 hopefully we can get some more information on this, good find. Thoughts @bateske ?

Thank you so much @Dreamer3 I suspect this may be the cause of some peoples troubles, good to know and have it documented, thanks for mentioning it.

Any idea around this, I’m assuming your 2 button commit still works around this?

Can we reserve memory at this address somehow?

1 Like

This is tough since the memory location is hard coded in the CDC.cpp file of Arduino core architecture.

Sure, but I’m not sure about the best way - since it would require altering the Arduino core files to change the address (in addition to the bootloader). And I don’t really know how to hack the C boilerplate startup code… this one might be over my head. If it were me I would change CTORS_END to start the stack 1-2 bytes lower in RAM… so you have like 2 bytes of RAM off the top that is NEVER user, and then you move the magic reboot word to that location in RAM.

Someone said you could also have a special variable and tell the compiler where to put it in RAM with a compile time flag, but Arduino doesn’t make it easy to do compile time flags (that I’m aware of).

Any idea around this, I’m assuming your 2 button commit still works around this?

Yes, rebooting to safe mode works.