Skip to main content
Graduate II
October 23, 2025
Solved

HARDFAULT STM32G0 ThreadX

  • October 23, 2025
  • 3 replies
  • 748 views

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.

    This topic has been closed for replies.
    Best answer by fernandogamax

    It looks like I’ve found the problem: it’s a microcontroller bug related to prefetch. To prevent these random hard faults, we need to disable it.

    https://www.st.com/resource/en/errata_sheet/es0547-stm32g0b0cekereve-device-errata-stmicroelectronics.pdf 


    3 replies

    Technical Moderator
    October 24, 2025

    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

    Graduate II
    October 24, 2025

    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?"

     

    Graduate II
    October 24, 2025

    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.

    Graduate II
    October 24, 2025
    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."
    Graduate II
    October 27, 2025


    I’ve changed the code so that a division by 0 can never occur, although, as I mentioned earlier, this case never actually happened in my tests.

    When I use this code, a hard fault occurs:

    ----------------------------------------------------------------------------------------------------------

    uint32_t decena_millar = (uint32_t)((numero_entero / 10000) % 10);

    uint32_t unidad_millar = (uint32_t)((numero_entero / 1000) % 10);

    uint32_t centena = (uint32_t)((numero_entero / 100) % 10);

    uint32_t decena = (uint32_t)((numero_entero / 10) % 10);

    uint32_t unidad = (uint32_t)( numero_entero % 10);

    ----------------------------------------------------------------------------------------------------------

    When I use this other code, no hard fault occurs:

    ----------------------------------------------------------------------------------------------------------

    uint32_t decena_millar = (uint32_t)((numero_entero / 10000));

    decena_millar=decena_millar% 10;

    uint32_t unidad_millar = (uint32_t)((numero_entero / 1000));

    unidad_millar=unidad_millar%10;

    uint32_t centena = (uint32_t)((numero_entero / 100));

    centena=centena%10;

    uint32_t decena = (uint32_t)((numero_entero / 10));

    decena=decena%10;

    uint32_t unidad = (uint32_t)( numero_entero );

    unidad=unidad%10;

    -----------------------------------------------------------------------------------------------

    It doesn’t make sense—I think the problem hasn’t been solved; it’s just been moved somewhere else.

    Another thing I’m thinking about: a few months ago I migrated the project from STM32CubeIDE 1.12.1 to STM32CubeIDE 1.18.0. We’re seeing that before this migration we never encountered this issue. Could that be the problem?

    Any ideas?

    fernandogamaxAuthorAnswer
    Graduate II
    October 28, 2025

    It looks like I’ve found the problem: it’s a microcontroller bug related to prefetch. To prevent these random hard faults, we need to disable it.

    https://www.st.com/resource/en/errata_sheet/es0547-stm32g0b0cekereve-device-errata-stmicroelectronics.pdf