Hardfaults in external flash loader when clicking disconnect in STM32CubeProgrammer
A year ago I made an external flash loader and that works (https://github.com/STMicroelectronics/stm32-external-loader/pull/13). I now ported the loader to the STM32H735IG. I use a serial port to print debug messages at certain points. While the flash loader works I do get hardfaults(in the loader, not the application) under certain conditions:
If I connect in STM32CubeProgrammer and then open memory viewer to 0x90000000 and then click disconnect. It doesn't occur when I did not open the memory viewer to 0x90000000 since that doesn't lead to an init of the loader. The flash loader will properly flash the internal and external flash and optionally runs the MCU. So it works, but I do see a hardfault error printed:
Init()
HardFault_Handler
CFSR = 0x00000000
HFSR = 0x80000000
DFSR = 0x0000000B
MMFAR = 0x00000000
BFAR = 0x00000000
AFSR = 0x00000000
So HFSR[31/]DEBUGEVT is active.
And DFSR/Debug Fault Status Register is non-zero. I did not find any documentation about this register for the Cortex-M7. In core_cm7.h I found this means the following bits are set to 1 (and in https://www.keil.com/dd/vtr/4143/7607.htm I found their meaning):
- HALTED is set when the processor is halted.
- BKPT is set when a software breakpoint is encountered.
- VCATCH is set when a vector catch is triggered.
What this means exactly I don't know. I do have interrupts enabled at some points, maybe that is the cause?
In STM32CubeIDE after clicking debug the flash loader will properly flash the internal and external flash and start the debug session. So it works, but I do see a hardfault error printed:
STM32H735IGT6_MT25TL256.stldr flash loader V1.01 Beta 1
Init()
SectorErase
STM32H735IGT6_MT25TL256.stldr flash loader V1.01 Beta 1
Init()
Write
Write
Write
Write
Write
Write
Write
Write
Write
Write
Write
Write
Write
Write
Write
Write
STM32H735IGT6_MT25TL256.stldr flash loader V1.01 Beta 1
Init()
HardFault_Handler
CFSR = 0x00000000
HFSR = 0x80000000
DFSR = 0x0000000B
MMFAR = 0x00000000
BFAR = 0x000000
The hardfault occurs when either closing the connection in STM32CubeProgrammer or when "Run after programming is called".
Also flashing a second time in STM32CubeProgrammer I get errors if I don't disconnect and reconnect first:
11:30:06 : File download complete
11:30:06 : Time elapsed during download operation: 00:00:06.430
11:30:06 : Verifying ...
11:30:06 : Read progress:
11:30:08 : Download verified successfully
11:31:12 : Memory Programming ...
11:31:12 : Opening and parsing file: SKF-MF-Dismount-HMI.elf
11:31:12 : File : SKF-MF-Dismount-HMI.elf
11:31:12 : Size : 806.88 KB
11:31:12 : Address : 0x08000000
11:31:12 : Erasing memory corresponding to segment 0:
11:31:12 : Erasing internal memory sectors [0 1]
11:31:14 : Error: failed to erase memory
11:31:14 : Error: failed to erase memory
This problem occurs in the internal flash.
I use standalone STM32CubeProgrammer version 2.15.0. STM32CubeIDE uses STM32CubeProgrammer version 2.11.0.
Can someone tell me what causes the hardfault error? Is it a problem or is this actually desired behavior?
Can someone tell me what causes second flashing to fail?
Edit:
I discovered more. I have the same error in my application if I reinitialize OSPI. It crashes in HAL_OSPIM_Config().
Calling HAL_OSPI_DeInit() and then MX_OCTOSPI1_Init() causes a crash. I do reset the peripheral clocks at the bottom of OCTOSPI1_MspInit using __HAL_RCC_OSPI1_FORCE_RESET() and __HAL_RCC_OSPI1_RELEASE_RESET(). But I guess HAL_OSPIM_Config has to be de-initialized first.
It specifically crashes at:
/***************** Deactivation of previous configuration *****************/
CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[instance].NCSPort-1U)], OCTOSPIM_PCR_NCSEN);
It appears the problem doesn't occur in my application if I initialize OSPI1 before OSPI2. But it still occurs in the flash loader. I found this topic that seems to be related: https://community.st.com/t5/stm32-mcus-products/stm32-cube-h7-hal-ospim-config-corrupts-previous-port/m-p/126073
Ospi2 is HyperRAM and it is memory mapped. If I initialize OSPI2 first, but do not enable memory mapping the error doesn't occur. So the problem occurs in HAL_OSPIM_Config after OSPI2 is memory mapped. I think a similar thing happens in the flash loader but in this case it is OSPI1 that is memory mapped when the error occurs. HAL_OSPIM_Config doesn't like to be called when at least one OSPI is memory mapped.
