MCU recover mode

Hi,

I recently bricked a couple of MCUs playing with low power modes. I’m still not sure what happened, but enabling LPM on my board makes JTAG inoperant.

I spent a lot of time trying to save these dead MCUs.

To avoid this situation, I added some kind of recovery mode at boot :

board.c

void board_init(void) …

// Safeguard: Infinite loop if board started with buttons pushed gpio_init(BTN0_PIN, GPIO_IN_PU);

gpio_init(BTN1_PIN, GPIO_IN_PU); if (!gpio_read(BTN0_PIN) || !gpio_read(BTN1_PIN) ) { gpio_set(LED0_PIN); gpio_set(LED1_PIN); while(1){} }

Did I reinvent the wheel ? Do Riot have already mecanisms to delay boot , or other way to protect from bad images ?

Thanks Olivier Fauchon

Hi Oliever,

Which MCUs have you been playing with?

This is a common ‘problem’ that can occur when you indeed enable LPM (or other things like disable debug pins etc). Therefore, most MCUs have certain procedures to keep the MCU halted after a reset, before any code is executed and the MCU gets unreachable. IIRC, ARM Cortex provides a vector-catch operation to halt the MCU after reset. Some IDEs (like Simplicity Studio for EFM32 MCUs) have a special unlock operation.

Your solution isn’t new, but works great to solve/work-around the problem :wink:

Hi Bas,

I use NXP Kinetis KW2xd MCU and OpenOCD + JLink with SWD, for flashing.

I didn’t know there were special procedures for unlocking devices.

I’ll try to use NXP official IDE flash these chips again.

Thanks

Olivier

Hi Olivier, I had the same issue with openOCD and SAM0 MCU in the past. But I was always to recover my chips using JLinkExe tool from Segger. I just erased the whole memory using JLinkExe to unbrick the device and re-run openocd afterwards.You should probably take a look too.

Regards

Hi, Low power modes are indeed a difficulty when debugging. Are you using the Kinetis low power mode PR? https://github.com/RIOT-OS/RIOT/pull/7897 Do you have any feedback that could help getting it ready for merging?

I have had similar issues when experimenting with low power modes. Do you have access to the reset pin on your device? If you have the reset pin connected on the JTAG header, you can use the OpenOCD option reset_config connect_assert_srst, in combination with the reset halt command to make the CPU halt so that you can reload a new firmware.

See https://github.com/RIOT-OS/RIOT/pull/7897/commits/a34d7ac3493e1b18d49c08eeada88725434e7b14 for the config file change (part of #7897) and https://github.com/RIOT-OS/RIOT/pull/10479 for using reset halt from the openocd.sh script.

Best regards, Joakim

Hi Joakim,

At the moment, I’m using your Kinetis LP RIOT branch (gebart:pr/kinetis-pm ). Still testing, but I’ll send you feedback as soon as possible.

Thanks for for you OpenOCD tips.

Olivier Fauchon

Hi Olivier,

I spent a lot of time trying to save these dead MCUs.

Did you manage to recover them?

I was in that situation a couple of times. It sometimes helps to just retry flashing, hammering the reset button. The idea is that you want to hit reset so that the debugger tries to stop the MCU in the (possibly very short) timespan between power-up and going to sleep.

    $ BOARD=xxx make all (to create the binary)     $ while true; do BOARD=xxx make flash-only; done

This will fail on its own. Then just start pushing the reset button/pin often, like a couple of times per second. At this point you don't care if flashing succeeds, just the initial flash erase starts so on the next reboot, the board hard-faults but "grabbable" by the debugger. Once you see that the flasher didn't fail right away but managed to get hold of the mcu and start erasing, you can stop, reset once more and hopefully flash a proper image.

Depending on the user programmer (tool), replacing "make flash-only" with a faster-executing flash erase command speeds up the process.

Hope this helps, Kaspar

Hi,

Thanks all for your recovery methods !

At the moment, I could not yet recover any of the broken parts. I’ll try again later.

Anyway, all these informations are really valuable.

Thx Olivier Fauchon