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

Shouldn't check_start_application clear *DBL_TAP_PTR on BOD reset, also? #88

Open
JetForMe opened this issue Mar 11, 2020 · 10 comments · May be fixed by #89
Open

Shouldn't check_start_application clear *DBL_TAP_PTR on BOD reset, also? #88

JetForMe opened this issue Mar 11, 2020 · 10 comments · May be fixed by #89

Comments

@JetForMe
Copy link

I've been experiencing an issue where poor power rails cause the bootloader to be entered spontaneously. You can simulate this by applying power to a Feather M0 by holding the ends of two wires together to complete the path to the positive power supply, and then rub them to make a series of interrupted power spikes.1

I think this is triggering the brown-out detection circuitry, and setting the RESET_CONTROLLER->RCAUSE.bit.BODxx bit(s), rather than RESET_CONTROLLER->RCAUSE.bit.POR. The code, as written in main.c interprets this as the user pressing the reset button, and it enters the boot loader.

Ignoring SINGLE_RESET, I think more robust code might look like this. I have not tested this as I currently have no way to load the boot loader:

    if (RESET_CONTROLLER->RCAUSE.bit.POR            //  If power-on reset
        || RESET_CONTROLLER->RCAUSE.bit.BOD12       //  or either brown-out
        || RESET_CONTROLLER->RCAUSE.bit.BOD33 ) {   //  reset, clear *DBL_TAP_PTR
        *DBL_TAP_PTR = 0;
    } else if (RESET_CONTROLLER->RCAUSE.bit.EXT     //  If user pressed reset button
                && *DBL_TAP_PTR == DBL_TAP_MAGIC) { //  AND it’s the second time through
        *DBL_TAP_PTR = 0;
        return; // stay in bootloader
    } else {                                        //  This should probably check RESET_CONTROLLER->RCAUSE.bit.EXT, too
        if (*DBL_TAP_PTR != DBL_TAP_MAGIC_QUICK_BOOT) {
            *DBL_TAP_PTR = DBL_TAP_MAGIC;
            delay(500);
        }
        *DBL_TAP_PTR = 0;
    }

This change should do a couple of things: treat power-on and brown-out-detect resets the same, and only count a /RESET assertion as the second press.

I’m not sure if the SAM51 has different BOD bits.


Footnotes

  1. In my case, I have an Adafruit solar lipo charger. When the battery is depleted and the sun is just beginning to shine on the panel, the power provided to the load can be spotty.

@JetForMe
Copy link
Author

I took a chance and flashed this bootloader onto a chip, and bricked it. I've ordered an ATMEL-ICE, should be here tomorrow. Not sure if I loaded it incorrectly (I used the resulting .ino file), or if this code doesn't work.

@mmoskal
Copy link
Member

mmoskal commented Mar 12, 2020

I generally had good luck using Particle Debugger (with openocd).

@JetForMe
Copy link
Author

Thanks. I'll order one of those, too. The ATMEL-ICE is already on its way.

@dhalbert
Copy link
Collaborator

dhalbert commented Mar 13, 2020

Most of us at Adafruit use J-Links. This one is inexpensive: https://www.adafruit.com/product/3571 (out of stock now, but do a websearch for other suppliers). This breakout is also useful: https://www.adafruit.com/product/2743

@JetForMe
Copy link
Author

What openocd configuration file and invocation do you typically use to program a Feather M0?

@mmoskal
Copy link
Member

mmoskal commented Mar 13, 2020

The following should work:

openocd -f interface/cmsis-dap.cfg -f target/at91samdXX.cfg -c 'program binary.elf verify reset exit'

Note that for bootloader it becomes much more tricky if the write protection is enabled. There are some scripts in this repo to disable it with openocd but it is a bit of a hit and miss for me.

@JetForMe
Copy link
Author

JetForMe commented Mar 14, 2020

Thank you for your help so far. I’m running into this error, not sure if you can help. Google seems to turn up surprisingly little around this.

$ openocd -f interface/cmsis-dap.cfg -f target/at91samdXX.cfg -c 'program build/feather_m0/bootloader-feather_m0-v3.7.0-73-g5ebe947a4384.elf verify reset exit'
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select <transport>'.
none separate
adapter speed: 400 kHz
cortex_m reset_config sysresetreq
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: JTAG Supported
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : CMSIS-DAP: FW Version = 01.00.0021
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 1 TDO = 1 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : clock speed 400 kHz
Info : SWD DPIDR 0x0bb11477
Info : at91samd.cpu: hardware has 4 breakpoints, 2 watchpoints
target halted due to debug-request, current mode: Thread 
xPSR: 0xc1000000 pc: 0x000006d0 msp: 0x000007c0
** Programming Started **
auto erase enabled
Error: Couldn't find part corresponding to DID 00000000
Error: auto_probe failed
** Programming Failed **
shutdown command invoked

I tried running the fuse repair (had to modify the dbgtool.js file to find my openocd). I ran this twice with identical output (i.e. it doesn't seem to actually write fuses), and I still get the same result as above when I try to flash the device. It’s at least partly talking to the Feather M0 BLE, as it doesn't get this far if I disconnect it.

I have an Atmel-ICE connected:

ICE Pin Feather M0 Pin
1 Vcc
2 SWDIO
3 gnd
4 SWCLK
5 - 9 n/c
10 nReset
$ scripts/dbgtool.js fuses
File: fuses
pkgDir: /Users/rmann/Library/Arduino15/packages/arduino/
Starting /usr/local/Cellar/open-ocd/0.10.0/bin/openocd -d2 -s /usr/local/Cellar/open-ocd/0.10.0//share/openocd/scripts/ -f interface/cmsis-dap.cfg -f target/at91samdXX.cfg -f scripts/fuses.tcl
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
debug_level: 2
Info : auto-selecting first available session transport "swd". To override use 'transport select <transport>'.
none separate
adapter speed: 400 kHz
cortex_m reset_config sysresetreq
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: JTAG Supported
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : CMSIS-DAP: FW Version = 01.00.0021
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 1 TDO = 1 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : clock speed 400 kHz
Info : SWD DPIDR 0x0bb11477
Info : at91samd.cpu: hardware has 4 breakpoints, 2 watchpoints
Fuses:
0
0
*** Updating fuses! ***
7
0
shutdown command invoked

@JetForMe
Copy link
Author

Update: I was trying this with my bricked Feather M0 BLE. I tried it with a Feather M0 Basic, and it seems to have worked. So, I'm not sure what's going on.

Initial programming attempt:

$ openocd -f interface/cmsis-dap.cfg -f target/at91samdXX.cfg -c 'program build/feather_m0/bootloader-feather_m0-v3.7.0-73-g5ebe947a4384.elf verify reset exit'
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select <transport>'.
none separate
adapter speed: 400 kHz
cortex_m reset_config sysresetreq
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: JTAG Supported
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : CMSIS-DAP: FW Version = 01.00.0021
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 1 TDO = 1 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : clock speed 400 kHz
Info : SWD DPIDR 0x0bc11477
Info : at91samd.cpu: hardware has 4 breakpoints, 2 watchpoints
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x00000288 msp: 0x20002dd8
** Programming Started **
auto erase enabled
Info : SAMD MCU: SAMD21G18A (256KB Flash, 32KB RAM)
Info : Padding image section 1 with 268 bytes
Error: SAMD: NVM lock error
Error: Failed to erase row containing 00000000
Error: SAMD: failed to erase sector 0
Error: failed erasing sectors 0 to 0
** Programming Failed **
shutdown command invoked

Successful fuse change:

$ scripts/dbgtool.js fuses
File: fuses
pkgDir: /Users/rmann/Library/Arduino15/packages/arduino/
Starting /usr/local/Cellar/open-ocd/0.10.0/bin/openocd -d2 -s /usr/local/Cellar/open-ocd/0.10.0//share/openocd/scripts/ -f interface/cmsis-dap.cfg -f target/at91samdXX.cfg -f scripts/fuses.tcl
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
debug_level: 2
Info : auto-selecting first available session transport "swd". To override use 'transport select <transport>'.
none separate
adapter speed: 400 kHz
cortex_m reset_config sysresetreq
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: JTAG Supported
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : CMSIS-DAP: FW Version = 01.00.0021
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 1 TDO = 1 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : clock speed 400 kHz
Info : SWD DPIDR 0x0bc11477
Info : at91samd.cpu: hardware has 4 breakpoints, 2 watchpoints
Fuses:
d800c772
ffff005d
*** Updating fuses! ***
d800c777
ffff005d
shutdown command invoked

Successful flash:

$ openocd -f interface/cmsis-dap.cfg -f target/at91samdXX.cfg -c 'program build/feather_m0/bootloader-feather_m0-v3.7.0-73-g5ebe947a4384.elf verify reset exit'
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select <transport>'.
none separate
adapter speed: 400 kHz
cortex_m reset_config sysresetreq
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: JTAG Supported
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : CMSIS-DAP: FW Version = 01.00.0021
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 1 TDO = 1 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : clock speed 400 kHz
Info : SWD DPIDR 0x0bc11477
Info : at91samd.cpu: hardware has 4 breakpoints, 2 watchpoints
target halted due to debug-request, current mode: Thread 
xPSR: 0x81000000 pc: 0x00000288 msp: 0x20002dd8
** Programming Started **
auto erase enabled
Info : SAMD MCU: SAMD21G18A (256KB Flash, 32KB RAM)
Info : Padding image section 1 with 268 bytes
wrote 16384 bytes from file build/feather_m0/bootloader-feather_m0-v3.7.0-73-g5ebe947a4384.elf in 1.649708s (9.699 KiB/s)
** Programming Finished **
** Verify Started **
verified 7924 bytes in 0.793008s (9.758 KiB/s)
** Verified OK **
** Resetting Target **
shutdown command invoked

@JetForMe
Copy link
Author

Oh, and the most important news: My proposed fix above seems to work. I'll make a PR.

JetForMe added a commit to latencyzero/uf2-samdx1 that referenced this issue Mar 14, 2020
… double-click reset to invoke boot loader. Works for SAMD21, not sure about SAMD51.
@JetForMe
Copy link
Author

Well, dammit. It seems this was not enough to fix the issue. It's much harder to reproduce now, but the bootloader is still spuriously triggered with poor startup power.

matsujirushi pushed a commit to Seeed-Studio/uf2-samdx1 that referenced this issue May 25, 2020
add m4 hallowing & m4sk + fixes UART defs on pygamer/pybadge
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants