cancel
Showing results for 
Search instead for 
Did you mean: 

HardFault on STM32F765

Luiz Roque
Associate II

Hi,

My code is generating a HardFault condition, is not every single time it pass the main loop, but after the first 5s it stops.

The Hardfault not happen every time in the same line, that is what have been so difficult to track down, but it always stops at the address 0x4df94710.

The code is apparent to be fine, I think something is corrupting my stack.

Can someone help me.

0690X000009YoaXQAS.png

Some times happen other hardfault, like:

0690X000009YoamQAC.png

11 REPLIES 11
Trevor Jones
Senior

can you check the call stack ?

generally I guess you have an interrupt where the buffer pointer is not within bounds

Register content at fault would be helpful. Precise suggests it is the read/load failing.

Would be less difficult to track down if your Hard Fault handler output some useful data vs while(1)

Stack checks aren't hard to implement either.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Luiz Roque
Associate II

Hi, guys, here are the registers at the fault.

0690X000009Z28xQAC.png

Is it something related to my stack been corrupted? How can I track it down?

Ok, that's a subset of the registers, the index is in R4 from the prior disassembly, but it is halfway through some code that is doing materially the same thing.

You'd perhaps fill the stack with a known pattern you can see in registers later, or check in a data dump of the stack area.

Determine which interrupts you have firing. Perhaps output a character to the terminal at entry/exit from those interrupts to identify any pattern to the failure.

Check your (excessive) use of auto/local variables in these interrupts and callbacks, and functions called inside them.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Luiz Roque
Associate II

Hi, the only interrupt a use is a DMA interrupt, to get values from GPIO PortD register and send them to memory, is a big amount of data, like 10240 bytes.

Now the code is throwing even more the hard fault I don't now why.

I use a PWM to generate the dma request to get the data from GPIO PortD, after get the data I perform a FFT, at this time every single time I get a hard fault, apparently I don't see any errors in the code, here is the hard fault and the code.

The FFT function is in the CalcProcedure function.

uint16_t timeout = 0;
  while(1)
  {
	MX_DMA2_Init();
	HAL_Delay(1);
	completeTransferGPIOD = FALSE;
	timeout = 0;
	HAL_TIM_PWM_Start(&htim1_Channel1_GPIOD, TIM_CHANNEL_1);
	while (!(completeTransferGPIOD))
	{
		__NOP();
		__NOP();
		__NOP();
		__NOP();
		timeout++;
		if (timeout == 15000)
		{
			timeout = 0;
			break;
		}
	}
	HAL_TIM_PWM_Stop(&htim1_Channel1_GPIOD, TIM_CHANNEL_1);
//	__HAL_TIM_DISABLE_DMA(&htim1_Channel1_GPIOD, TIM_DMA_CC1);
//	__HAL_DMA_DISABLE(&hdma2Handle1);
    stopDMA();
//	HAL_NVIC_DisableIRQ(DMA2_Stream1_IRQn);
	HAL_Delay(5);
	ConvertData();
	LED_Toggle(LED_GREEN);
//	voltageESU.len = 1024;
	buffer_len = 8000;
    CalcProcedure(buffer_len);
	HAL_Delay(100);
  }

And the FFT Function

#if (FFT1)
    for (uint16_t i = 0; i < 1024; i++)
	{
		voltageFFT[i].real = (float) voltageESU.voltage[i];
		voltageFFT[i].imag = 0;
	}
	reverteBit(voltageESU.len);
	fft(voltageESU.len);
	for (uint16_t i = 0; i < 1024; i++)
	{
		square = (double) voltageFFT[i].real*voltageFFT[i].real +
				 (double) voltageFFT[i].imag*voltageFFT[i].imag;
		voltageESU.voltageFFT[i] = (uint32_t) sqrt(square);
		if (voltageESU.voltageFFT[i] >= FFTMax)
			FFTMax = voltageESU.voltageFFT[i];
	}
#endif
 
#if (FFT1)
void reverteBit(int N)
{
	static int c;
	static int temp1;
	static int temp2;
	static int temp3;
	static complex c_temp;
 
	temp1 = 0;
	temp2 = N/2;
	temp3 = 0;
	for (c=1; c < (N-1); c++)
	{
		temp1 = temp2;
		while (temp3 >= temp1)
		{
			temp3 = temp3 - temp1;
			temp1 = temp1/2;
		}
		temp3 = temp3 + temp1;
		if (c < temp3)
		{
			c_temp = voltageFFT[c];
			if (temp3 <= N-1)
			{
				voltageFFT[c] = voltageFFT[temp3];
				voltageFFT[temp3] = c_temp;
			}
		}
	}
}
 
void fft(int N)
{
	estagios = 0;
	ka = 0;
	indiceWD = 2;
	temp1 = 0; temp2 = 0;
	a_fft = 0; b_fft = 0; c_fft = 0; d_fft = 0;
	angulo = 0;
 
	estagios = log2(N);
 
	for(c_fft = 1; c_fft <= estagios; c_fft++)
	{
		temp2 = N/c_fft;
		if (indiceWD < 3000)
		{
			for(temp1 = 0; temp1 < indiceWD; temp1++)
			{
				for(temp2=0; temp2 < (N/indiceWD); temp2++)
				{
					a_fft = temp1 + (temp2*indiceWD);
					d_fft = indiceWD/2;
					if(temp1 >= d_fft)
					{
						b_fft = a_fft - d_fft;
 
						angulo = (double) temp1*2*PI/indiceWD;
						fftAux1.real = (float) cos(angulo);
						fftAux1.imag = (float) -sin(angulo);
 
						fftAux2.real = ((voltageFFT[a_fft].real*fftAux1.real) - (voltageFFT[a_fft].imag*fftAux1.imag));
						fftAux2.imag = ((voltageFFT[a_fft].real*fftAux1.imag) + (fftAux1.real*voltageFFT[a_fft].imag));
 
						Xf[a_fft].real = (voltageFFT[b_fft].real + fftAux2.real);
						Xf[a_fft].imag = (voltageFFT[b_fft].imag + fftAux2.imag);
					}
					else
					{
						b_fft = a_fft + d_fft;
 
						angulo = (double) temp1*2*PI/indiceWD;
						fftAux1.real = (float) cos(angulo);
						fftAux1.imag = (float) -sin(angulo);
 
						fftAux2.real = ((voltageFFT[b_fft].real*fftAux1.real) - (voltageFFT[b_fft].imag*fftAux1.imag));
						fftAux2.imag = ((voltageFFT[b_fft].real*fftAux1.imag) + (fftAux1.real*voltageFFT[b_fft].imag));
 
						Xf[a_fft].real = (voltageFFT[a_fft].real + fftAux2.real);
						Xf[a_fft].imag = (voltageFFT[a_fft].imag + fftAux2.imag);
					}
				}
			}
		}
		else
			break;
 
		for(ka=0;ka < N;ka++)
		{
			voltageFFT[ka] = Xf[ka];
		}
		indiceWD = indiceWD * 2;
	}
}

How can I track it down base in the hardfault?

Thank you0690X00000A9dcRQAR.png

Luiz Roque
Associate II

I thing maybe is some related with the RCC or system clock, or even my HSE clock, because some times I'm getting hardfault during HAL_Delay, or during clock init. Liked the photo below.

0690X00000A9dfGQAR.png

Looks to be branching to an invalid address (pc via r2), perhaps clash of stack/heap

I use my own handler,

https://community.st.com/s/global-search/after%20joseph

https://community.st.com/s/question/0D50X0000Az372YSQQ/stm32l412-hardfault-while-using-minimal-cubeide-example

Figure flow of code with instrumentation, and sanity check pointer, stack and heap.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
T J
Lead

generally it is an 'out of bounds' issue or power supply noise.

I would suggest its one of these lines, causing the problem:

a_fft = temp1 + (temp2*indiceWD);

could you check this value before you execute these lines ?

  1.  
  2. Xf[a_fft].real = (voltageFFT[b_fft].real + fftAux2.real);
  3. Xf[a_fft].imag = (voltageFFT[b_fft].imag + fftAux2.imag);

then this line,

b_fft = a_fft + d_fft;

could cause it on these lines,

4. fftAux2.real = ((voltageFFT[b_fft].real*fftAux1.real) - (voltageFFT[b_fft].imag*fftAux1.imag));

5. fftAux2.imag = ((voltageFFT[b_fft].real*fftAux1.imag) + (fftAux1.real*voltageFFT[b_fft].imag));

I would check if a_fft and b_fft and voltageESU.len are within your array size. before you use them...

all the new linux core has hardset bounds or serious bounds checking.

The PWM would be asynchronous to the systick,

I guess that the PWM/DMA interrupt has priority over the systick, so thats why you can go into hardfault during systick.

do you have a call-stack view ?

should be able to backtrack the function that is causing the hardfault.

easily checked by commenting out lines that use the a_fft b_fft or d_fft or voltageESU.len indexing.

anyhow, if its not those variables, generally it is an index out of bounds in my experience.

if you are getting a hardfault after reset, in clock init, then you may have insufficient capacitance on your PCB,

can you check the voltage rails on the processor ? and the Vcap pins ? do you have a scope ?

dont visit here very often, good luck

Luiz Roque
Associate II

Hi, I did not understand, can you be more specific?

I looked up at links you sent, the only thing I found useful is to set my own hardfault handler, but how is this apply to my case? Since the code do not go to the hardfault , it goes to an invalid address.

I set a big min stack and heap

/* Highest address of the user mode stack */
_estack = 0x20080000;    /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x8000;      /* required amount of heap  */
_Min_Stack_Size = 0x29000; /* required amount of stack */
 
/* Specify the memory areas */
MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 512K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 1024K
}