cancel
Showing results for 
Search instead for 
Did you mean: 

USB bootloader: Hard Fault when STM32cubeProgrammer connects to STM32L562 DFU

jeroen
Associate III

Processor: STM32L562QEI

Board: proprietary

When connecting STM32CubeProgrammer to my STM32L562QEIx board via USB, I get a Hard Fault interrupt.

The USB interface is initialized with MX_USB_Device_Init() and STM32CubeProgrammer correctly detects it. But as soon as I click on "Connect", the processor enters the Hard Fault handler.

Some investigation shows that HAL_PCD_EP_Transmit() is called with <pBuf> being NULL while <len> = 1204. This leads to a Hard Fault in USB_WritePMA() further down the call tree.

The (DFU) code was generated with STM32CubeMX using "STM32Cube FW_L5 V1.4.0".

The USB hardware interface is OK, when running the application firmware on the board, it presents itself as a virtual COM port over which I am able to communicate (except that when USB is connected to a PC at startup, I may sometime experience Hard Faults as well)

Any thoughts / help is very much appreciated !

Jeroen

1 ACCEPTED SOLUTION

Accepted Solutions
jeroen
Associate III

OK, with help from ST, the cause was finally discovered :

The code generated by STM32CubeMX in usbd_dfu_flash.c is incorrect.

FLASH_If_Read() returns USBD_OK (0x00) while it should return a pointer.

Replacing the return with something like 0x08000000U solved the problem of the crash when STM32CubeProgrammer connects to the target.

BUT, actually all the functions in usbd_dfu_flash.c are empty, so there is no implementation for the flash memory interface!

There is one under STM32Cube_FW_L5_V1.4.0\Projects\STM32L562E-DK\Applications\USB_Device\DFU_Standalone. Copying this code it works a lot better except another BUG which I corrected :

  • in FLASH_If_Erase(), the number of (2K) pages to erase (eraseinitstruct.NbPages) is set to 1 while STM32Cubprogrammer expects to erase 16K per call. After setting eraseinitstruct.NbPages to 8U, it now all works fine

View solution in original post

5 REPLIES 5
jeroen
Associate III

Nobody ever had this problem?

I actually do have a similar problem in the application part of the firmware. When USB is connected to the PC when starting the device, I very often get a hardfault as well. Plugging in USB later works well (COM port on PC, I'm able to send/receive data)

In this particular case the pClassData pointer in "USBD_HandleTypeDef hUsbDeviceFS" is NULL.

Tracing back where this member is set to an appropriate buffer, I discovered that the CTR interrupt flag (in register USB_ISTR) is never set. And thus the (only) chain of functions calls that lead to the setting of pClassData is never called.

I have details about the entire chain but the important thing is that there simply never is an interrupt on the CTR flag (other flags like USB_ISTR.RESET are set and the interrupt handler (PCD_EP_ISR_Handler() in stm32l56xx_hal_pcd.c).

The code I'm using was generated with "STM32Cube FW_L5 V1.4.0", just like the one for the bootloader.

I forgot to mention that the CTR interrupt mask bit is 1, meaning that the interrupt is enabled. It is really the CTR bit itself that never gets set when USB is connected at startup

>>Nobody ever had this problem?

I don't solve problems this way, I solve the problems I encounter, as I encounter them.

Hard Faults are gross failures, and shouldn't be too hard to pin down.

Get a proper Hard Fault Handler that outputs actionable data.

Instrument and check-point the code to sanity check and find bad/NULL pointers.

Check the heap, and if malloc() is returning NULLs.

Check initialization order, make sure structures are properly initialized before interrupts/callbacks might act upon the data therein.

Enable and use assert()s

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
jeroen
Associate III

Hi Tesla,

Pinning down the cause of the hardfault is indeed not the hardest part and I do have a handler that shows me where the error occurred.

If you read my post again, you'll see that I mention which pointer is NULL(in both the DFU and CDC modes) and I even identified the code that is supposed to initialize it.

The problem is that this code, supposed to be called on a specific USB interrupt flag is never called because the flag is never set.

Any thanks for your post, you're the first one to take some time

Jeroen

jeroen
Associate III

OK, with help from ST, the cause was finally discovered :

The code generated by STM32CubeMX in usbd_dfu_flash.c is incorrect.

FLASH_If_Read() returns USBD_OK (0x00) while it should return a pointer.

Replacing the return with something like 0x08000000U solved the problem of the crash when STM32CubeProgrammer connects to the target.

BUT, actually all the functions in usbd_dfu_flash.c are empty, so there is no implementation for the flash memory interface!

There is one under STM32Cube_FW_L5_V1.4.0\Projects\STM32L562E-DK\Applications\USB_Device\DFU_Standalone. Copying this code it works a lot better except another BUG which I corrected :

  • in FLASH_If_Erase(), the number of (2K) pages to erase (eraseinitstruct.NbPages) is set to 1 while STM32Cubprogrammer expects to erase 16K per call. After setting eraseinitstruct.NbPages to 8U, it now all works fine