cancel
Showing results for 
Search instead for 
Did you mean: 

HARDFAULT STM32G0 ThreadX

fernandogamax
Associate III

I’m working with an STM32G0 running ThreadX (Azure RTOS).
The system UART is configured in circular DMA mode with an IDLE event interrupt for data reception.

Symptoms
Intermittently, after hundreds of successful receptions, the system enters HardFault_Handler.
The fault always occurs at the same point in the code (on a C division instruction, inside a function unrelated to DMA).

The register values at the HardFault are shown in Image 1.

When it runs without triggering a hard fault, the registers are:
xPSR = 0x01000000 and CONTROL = 2.

When the hard fault occurs, these registers are:
xPSR = 0x00000000 and CONTROL = 0.

The failure does not depend on the received data.

The thread stack (PSP) has sufficient space.

I believe the intermittent HardFault is not related to the operation itself:
If I modify the code—adding new instructions or removing code—sometimes it reproduces, and other times it still reproduces but in different parts of the code.

Question
What can I do to determine the root cause of this hard fault? I can’t figure out what the problem is.

8 REPLIES 8
Saket_Om
ST Employee

Hello @fernandogamax 

Please follow the instruction in the article below to debug your HardFault:

How to debug a HardFault on an Arm® Cortex®-M STM3... - STMicroelectronics Community

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om
fernandogamax
Associate III

Hello @Saket_Om
I have followed the steps you indicated. I'm working with an M0+ STM32G0B0, so I cannot access the hardfault analyzer.

r0 0x0
r1 0x0
r2 0x0
r3 0x2000437b
r4 0x0
r5 0x24
r6 0x1c
r7 0x20004360
r8 0x0
r9 0x0
r10 0x0
r11 0x0
r12 0x1
sp 0x20004360
lr 0x8040291
pc 0x80402a0
xpsr 0x0
msp 0x20023fc8
psp 0x20004360
primask 0x0
basepri 0x0
faultmask 0x0
control 0x0

 

centesimas=(int)parte_decimal%((int)multipliccador2/10);
0804029a: adds r3, r7, r6
0804029c: ldrb r4, [r3, #0]
0804029e: adds r3, r7, r5
080402a0: ldrh r3, [r3, #0]


The instruction ldrh r3, [r3, #0] is using an odd address in r3 (0x2000437b). Could this be the cause of the hardfault? But what is causing this in the first place?"

 

Look at surrounding code. The misaligned 16 bit read is the problem. Is that from a pointer? You need to do a more guarded read where you get individual bytes to construct the word.

Is this code processing/parsing data sent to you?

Don't cast *uint8_t pointers to *uint16_t or *uint32_t ones.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
In the function where the hardfault occurs, no pointers are used.
 
 
void G7SL_pinta_float(float dato,uint8_t numero_decimales)
{
int temp, temp1,numero_entero;
uint8_t signo = EN_GS7_SIGNO_POSITIVO;
uint32_t unidad = 0, decena = 0, centena = 0, unidad_millar = 0, decena_millar = 0,parte_decimal = 0,decimas = 0, centesimas = 0;
uint32_t multipliccador1,multipliccador2;
uint32_t digito_pintar=0;
if(dato < -0.01){
signo = EN_GS7_SIGNO_NEGATIVO;
}
switch (numero_decimales)
{
case 0:multipliccador1=10;multipliccador2=1;break;
case 1:multipliccador1=100;multipliccador2=10;break;
case 2:multipliccador1=1000;multipliccador2=100;break;
default:multipliccador1=10000;multipliccador2=1000;break;
}
//Pasamos el float a un valor entero tomando dos decimales y en valor absoluto.
temp = abs((int)(dato *(int)multipliccador1));
//Pamos el valor entero teniendo en cuenta dos decimales a un valor entero con un solo decimal.
temp1 = temp / 10;
//Comprobamos si tenemos que redondear
if((temp-(temp1*10))>5)
{
    temp1 = temp1 + 1;
}
parte_decimal = temp1%(int)multipliccador2;
//parte_decimal = temp1*multipliccador2;
numero_entero = temp1/(int)multipliccador2;
decena_millar = (numero_entero%100000)/10000;
unidad_millar = (numero_entero%10000)/1000;
centena = (numero_entero%1000)/100;
decena = (numero_entero%100)/10;
unidad = (numero_entero%10)/1;
decimas=(int)parte_decimal/((int)multipliccador2/10);
centesimas=(int)parte_decimal%((int)multipliccador2/10);//->hardfault
 
}
 
I've been dealing with this problem for a long time. When I modify the code, the error might not reappear, or it might appear in another area of the code. It's random because, before the hardfault jumps, that piece of code may have executed 1000 times without the hardfault occurring."

Add code to make sure you aren't dividing by zero.

Determine what is generating the code that makes R3 odd, and what it's reading.

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

fernandogamax_0-1761315401246.png

fernandogamax_1-1761315651782.png

fernandogamax_2-1761315774667.png

Division by 0 is not the cause. It seems it could be due to alignment? If it's due to alignment, the function where the fault occurs cannot be the cause.

>>Division by 0 is not the cause

You've got a couple of issues, when multipliccador2 is 1 it's going to do a modulo zero here which is a divide by zero

decimas=(int)parte_decimal/((int)multipliccador2/10);

centesimas=(int)parte_decimal%((int)multipliccador2/10);

You can perhaps reorder this?

decimas=(parte_decimal / multipliccador2) /10;

Or handle the numero_decimales == 0 case differently?

if (((int)multipliccador2/10) == 0) puts("Hazard!");

if (numero_decimales)
{
 decimas=(int)parte_decimal/((int)multipliccador2/10);
 centesimas=(int)parte_decimal%((int)multipliccador2/10);
}

Also not clear where this code came from, which WILL fault if the pointer is misaligned.

080402a0: ldrh r3, [r3, #0]

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

You’re right about that. I’ve already fixed it. I was saying that’s not the problem, because when the hardfault occurs, I check the variables and none of them are causing a division by zero.