Skip to main content
RKnoe
Associate
June 21, 2019
Question

STM32L412 hardfault while using minimal CubeIDE example.

  • June 21, 2019
  • 13 replies
  • 9919 views

I try to set up an USB CDC project for a STM32L412KB Nucleo32 board using CubeIDE.

I activated the USB connection and the USB middleware with the default USB CDC setup.

If I run this code, it ends in the hardfault handler with INVSTATE raised during the USB_EnableGlobalInt(hpcd) call (HAL_PCD_Start() at stm32l4xx_hal_pcd.c:1,014 0x8000d26).

The next items on the call stacks are: <signal handler called>() at 0xfffffff9, 0x0, <signal handler called>() at 0xfffffff1   and finally HardFault_Handler() at stm32l4xx_it.c:88 0x800432a.

Currently I ran out of ideas on what to do. USB CDC worked in projects set up for the STM32F072 and F103 - should we change from the L4 to another MCU?

This topic has been closed for replies.

13 replies

bitlischieber
Associate III
June 21, 2019

I had recently a similar issue. In my case the debug messages where activated and tried to printf() the messages in to the void.

Have you tried to deactivate the debug messages or redirect printf() to a serial port?

 #ifdef __GNUC__
 /* With GCC, small printf (option LD Linker->Libraries->Small printf
 set to 'Yes') calls __io_putchar() */
 #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
 #else
 #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
 #endif /* __GNUC__ */
 
 /**
 * @brief Retargets the C library printf function to the USART.
 * @param None
 * @retval None
 */
 PUTCHAR_PROTOTYPE
 {
 /* Place your implementation of fputc here */
 /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
 HAL_UART_Transmit(&huart6, (uint8_t *)&ch, 1, 0xFFFF);
 
 return ch;
 }

RKnoe
RKnoeAuthor
Associate
June 21, 2019

Thank you very much for your answer! I would never expected something like this - but unfortunately, this doesn't seems to be the answer.

I set up __io_putchar and verified that it is usable by printing in the main loop (and disabling MX_USB_DEVICE_Init()), but if I enable this function the program still ends in the hardfault handler :(

bitlischieber
Associate III
June 24, 2019

Have you tried to set the linkers min. heap size to at least 0x1000?

According to ST support "the default heap size is usually not big enough".

RKnoe
RKnoeAuthor
Associate
June 24, 2019

I tried it with even 0x2000 for stack and heap (which would have be a tremendous waste of RAM) - and it didn't work.

But this time I noticed the solution when single-stepping through the USB initialization:

USB_EnableGlobalInt() has been called by HAL_PCD_Init() and it results in the hardfault handler if it is called again in HAL_PCD_Start. If I comment out the second call, the initialization runs through and at least I get reenumeration attempts. Is there a way to notice ST of this problem and possible fix?

lizerd
Associate III
July 20, 2019

Hi.

Did you ever find the solution to this problem ?

I have the exact same problem on the STM32L412CB (Rev A) chip.

Your error explanation is spot on the same problem that I have.

I have tested 10 diffrent setups, and all have the same problem.

When I do the same setup on a STM32L452RE there is no problem what so ever.

Hope you have any new info

The Cube FW is STM32Cube FW_L4 V1.14.0

Best // Mike

Tesla DeLorean
Guru
July 20, 2019

Some output from a Hard Fault Handler would be helpful.

For GNU/GCC based tools make sure the initial stack pointer is even, ie 0x20020000 and not 0x2001FFFF

For Keil make sure stack allocation is bigger in startup.s at least 0x1000

Make sure the RAM regions are correctly placed/sized, especially when moving between parts.

HardFault_Handler\
 PROC
 EXPORT HardFault_Handler [WEAK]
 
 TST lr, #4 ; Determine correct stack
 ITE EQ
 MRSEQ R0, MSP ; Read MSP (Main)
 MRSNE R0, PSP ; Read PSP (Process)
 
 MOV R1, R4 ; Registers R4-R6
 MOV R2, R5
 MOV R3, R6 ; sourcer32@gmail.com
 
 EXTERN hard_fault_handler_c
 B hard_fault_handler_c
 ENDP

void hard_fault_handler_c(unsigned int * hardfault_args, unsigned int r4, unsigned int r5, unsigned int r6)
{
 printf ("\n[Hard Fault]\n"); // After Joseph Yiu
 
 printf ("r0 = %08X, r1 = %08X, r2 = %08X, r3 = %08X\n",
 hardfault_args[0], hardfault_args[1], hardfault_args[2], hardfault_args[3]);
 printf ("r4 = %08X, r5 = %08X, r6 = %08X, sp = %08X\n",
 r4, r5, r6, (unsigned int)&hardfault_args[8]);
 printf ("r12= %08X, lr = %08X, pc = %08X, psr= %08X\n",
 hardfault_args[4], hardfault_args[5], hardfault_args[6], hardfault_args[7]);
 
 if (__CORTEX_M >= 3)
		printf ("bfar=%08X, cfsr=%08X, hfsr=%08X, dfsr=%08X, afsr=%08X\n",
			*((volatile unsigned int *)(0xE000ED38)),
			*((volatile unsigned int *)(0xE000ED28)),
			*((volatile unsigned int *)(0xE000ED2C)),
			*((volatile unsigned int *)(0xE000ED30)),
			*((volatile unsigned int *)(0xE000ED3C)) );
 
 while(1);
}

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Tesla DeLorean
Guru
January 9, 2020

Note to self, Cortex-M0(+) startup.s code for Keil

HardFault_Handler\
 PROC
 EXPORT HardFault_Handler
 EXTERN hard_fault_handler_c
 
 MOV R1, LR
 LDR R0, =hard_fault_handler_c
 MOV LR, R0
 MOVS R0, #4 ; Determine correct stack
 TST R0, R1
 MRS R0, MSP ; Read MSP (Main)
 BEQ .+6 ; BEQ 2, MRS R0,PSP 4
 MRS R0, PSP ; Read PSP (Process)
 
 MOV R1, R4 ; Registers R4-R6, as parameters 2-4 of the function called
 MOV R2, R5
 MOV R3, R6 ; sourcer32@gmail.com
 
 BX LR
 ENDP

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
lizerd
Associate III
July 20, 2019

Hi.

I do not have any way to print the printf output right now.

So I checked with TrueStudio (Stm32CubeIDE)

I have tested this with both Truestudio 9.3 and Stm32CubeIDE with the same result.

I set the breakpoint at the position before the error accrue, and each picture is an step in assembly.

0690X000009Ywi5QAC.png

next

0690X000009YwiAQAS.png

next

0690X000009YwiFQAS.png

next

0690X000009YwiKQAS.png

next

0690X000009YwiPQAS.png

Hard fault

and assembly code at the error

0690X000009YwiZQAS.png I do not know ow to follow this, becuas from my perspective it looks well and fine before the error hits.

Hope there is a way to solve this.

btw, Thanks Clive for all your help, indirect (others post) and direct :)

waclawek.jan
Super User
July 20, 2019

> each picture is an step in assembly.

I'd say, you used "step over" rather than "step into" (I don't use eclipsoids so I don't know exactly which key does what). In other words, IMO you run the USB_DevConnect routine, and failed somewhere there.

Learn how to "step into" and step until the fault occurs.

JW

lizerd
Associate III
July 20, 2019

Hi JW.

I am not a eclips guy my self, so I am no expert.

But I used "run to line" for each "step"

0690X000009YwioQAC.png

I culd not find another way to do it (Assembly step).

waclawek.jan
Super User
July 20, 2019

0690X000009YwiyQAC.png

(picture courtesy of @SToma​ )

lizerd
Associate III
July 21, 2019

hi all.

thanks for the hint Jan, but when I do singel step, it works fine until I push resume.

So I can single step trough the whole thing and it is fine, but when I let the processor run freely again it ends up in HardFault.

So I am not any wiser from that unfortunately.

I have really been trying to figure this out, and solve how to implement clive's HardFault data.

What I can not figure out is how to make the compiler/MCU the added HardFualt addition in startup.s

Because I use Truestudio the code sample for the assembly code did not work,

So I found a example on https://nathan.vertile.com/blog/2016/05/04/stm32-hardfault-debugging/

/**
 * My code in startup_stm32l412xx.s
 *
*/
	.section .text.Reset_Handler
	.weak HardFault_Handler
	.type HardFault_Handler, %function
HardFault_Handler:
 movs r0,#4
 movs r1, lr
 tst r0, r1
 beq _MSP
 mrs r0, psp
 b _HALT
_MSP:
 mrs r0, msp
_HALT:
 ldr r1,[r0,#20]
 b hard_fault_handler_c
 bkpt #0
 
.size HardFault_Handler, .-HardFault_Handler
// My code in stm32l4xx_it.c
 
void hard_fault_handler_c(unsigned long *hardfault_args)
{
 volatile unsigned long stacked_r0 ;
 volatile unsigned long stacked_r1 ;
 volatile unsigned long stacked_r2 ;
 volatile unsigned long stacked_r3 ;
 volatile unsigned long stacked_r12 ;
 volatile unsigned long stacked_lr ;
 volatile unsigned long stacked_pc ;
 volatile unsigned long stacked_psr ;
 volatile unsigned long _CFSR ;
 volatile unsigned long _HFSR ;
 volatile unsigned long _DFSR ;
 volatile unsigned long _AFSR ;
 volatile unsigned long _BFAR ;
 volatile unsigned long _MMAR ;
 
 stacked_r0 = ((unsigned long)hardfault_args[0]) ;
 stacked_r1 = ((unsigned long)hardfault_args[1]) ;
 stacked_r2 = ((unsigned long)hardfault_args[2]) ;
 stacked_r3 = ((unsigned long)hardfault_args[3]) ;
 stacked_r12 = ((unsigned long)hardfault_args[4]) ;
 stacked_lr = ((unsigned long)hardfault_args[5]) ;
 stacked_pc = ((unsigned long)hardfault_args[6]) ;
 stacked_psr = ((unsigned long)hardfault_args[7]) ;
 
 // Configurable Fault Status Register
 // Consists of MMSR, BFSR and UFSR
 _CFSR = (*((volatile unsigned long *)(0xE000ED28))) ;
 
 // Hard Fault Status Register
 _HFSR = (*((volatile unsigned long *)(0xE000ED2C))) ;
 
 // Debug Fault Status Register
 _DFSR = (*((volatile unsigned long *)(0xE000ED30))) ;
 
 // Auxiliary Fault Status Register
 _AFSR = (*((volatile unsigned long *)(0xE000ED3C))) ;
 
 // Read the Fault Address Registers. These may not contain valid values.
 // Check BFARVALID/MMARVALID to see if they are valid values
 // MemManage Fault Address Register
 _MMAR = (*((volatile unsigned long *)(0xE000ED34))) ;
 // Bus Fault Address Register
 _BFAR = (*((volatile unsigned long *)(0xE000ED38))) ;
 
 __asm("BKPT #0\n") ; // Break into the debugger
}

but this do not work, ??

what I found in Truestudio was the problem window.

0690X000009Yx88QAC.png

It reports an hard fault and gives some info, unfortunately I do not understand what it means.

The wired thing is, I downloaded the tryout of Crossworks and it works with the board if I create an MDK-ARM V5 project in CubeMX and import it into crossworks and just run. It works. So there is no problem with the MCU or the board.

:see_no_evil_monkey:

Tesla DeLorean
Guru
July 21, 2019

Remove the WEAK settings in startup.s and comment out whatever is currently in stm32fxyz_it.c ?

I think I've posted GNU/GCC syntax code previously, blindly this should suffice..

..
 TST lr, #4 /* Determine correct stack */
 ITE EQ
 MRSEQ R0, MSP /* Read MSP (Main) */
 MRSNE R0, PSP /* Read PSP (Process) */
 
 MOV R1, R4 /* Registers R4-R6 */
 MOV R2, R5
 MOV R3, R6 /* sourcer32@gmail.com */
 
 B hard_fault_handler_c
 

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..