blackmagic-debug / blackmagic

In application debugger for ARM Cortex microcontrollers.
GNU General Public License v3.0
3.2k stars 764 forks source link

hard fault on deep sleep with STM32G0 with DBGEN clock enabled #1003

Closed mmoskal closed 2 years ago

mmoskal commented 2 years ago

After I flash my STM32G030 the first WFI with deep sleep enabled causes Hard Fault (I think on wake up). This is fixed by power-cycling the board (but not by pulsing the NRST line).

This wasn't the case when the L4 driver was used and started happening with the G0 driver. I found that the culprit is enabling DBGMCU clock in APBENR1. The code seems to disable it afterwards, but it somehow doesn't work. The hard fault only happens after flashing (not after just connecting to debugger). Seems like a really strange behavior.

@fabalthazar do you know when enabling that clock is needed? I can't find any docs in reference manual on that.

fabalthazar commented 2 years ago

Thanks for your feedback. Enabling the DBG peripheral's clock is needed in order to write into DBG_CR which aims at keeping clocks running for debugging purposes. You can try not enabling DBGMCU clock and you should see the write into DBG_CR having no effect. And thus no debug possible in deep sleep state. When you say "the code seems to disable it afterwards", you means the driver code or your application one?

mmoskal commented 2 years ago

Thank you for explanation, I should have known this :)

It seems the problem is that flashing process resets the device, which stops the DBG clock.

The #1004 PR fixes it for me.

esden commented 2 years ago

As I don't have test hardware yet. If there is a second person that can cross check #1004 I will be happy to merge it.

fabalthazar commented 2 years ago

I would be happy to reproduce the fault. @mmoskal Can you provide the steps to reproduce the hard fault or any hint to help me understand what happens? Questions than come to my mind:

Currently, I don't understand how your patch prevents a hard fault. I tend to think that if DBGMCU clock has been disabled, at worse the writes into DBG_CR and DBG_APB_FZ1 will have no effect. I may miss something.

mmoskal commented 2 years ago

I flash from gdb using load command. I think it resets the MCU when it's done or does something else that disables the DBG clock, but does not reset the DBG registers. This means that the restoring of DBG registers doesn't work without first enabling DBG clock (which #1004 does).

I'm building from this repo https://github.com/microsoft/jacdac-msr-modules I'm using STOP1 power mode https://github.com/microsoft/jacdac-stm32x0/blob/main/stm32/rtc.c#L331 I'm entering it using WFI instruction and exit is either via RTC alarm or EXTI (though I don't think I ever get to the EXTI case)

I'm flashing and detaching the BMP. The program starts and crashes. Afterwards even toggling the NRST line doesn't seem to clear the DBG registers and I get hard fault after wakeup from deep sleep. I'm not using hosted.

esden commented 2 years ago

@mmoskal what exact STM32G0 are you using? I am trying to reproduce your results with the MB1454B STM32G0-SO8-DISCO board, that features the STM32G031J6M6U chip. And I am getting the vFlashErase error when I try to use load to flash a test firmware. It might be some timeout issue, or something related to the reduced pin count. I will keep investigating, but it would be good to know what chip you are using as you said that you are able to use load.

mmoskal commented 2 years ago

Typically STM32G030F6 though I was also successful with STM32G030J6. J6 has a bunch of pins connected to SWD pads so maybe that’s the problem?

esden commented 2 years ago

Thanks for the info. It turns out the issue was the fact that the dev board ST-Link was unpowered but still in circuit. After removing the DUT from the dev board flashing the firmware work fine.