Skip to main content
Visitor II
April 14, 2023
Solved

FreeRTOS on STM32F767: hard fault when all the tasks in the Blocked State

  • April 14, 2023
  • 5 replies
  • 5619 views

Hi

I created a project from STM32CubeMX for the STM32F767ZI MCU:

  • FreeRTOS 10.2.1 CMSIS v2
  • 6 tasks (1 main + 5 bus: CAN, 2 x I2C, QuadSPI, USART)
  • 1 message queue per task.
  • 1 timer to pace the system
  • use of DMA and global interrupt active for every bus (CAN does not use DMA)

After initialization, every task waits for message in its dedicated message queue. When the latest task blocks on reading its queue, a hard fault is generated:

The processor has escalated a configurable-priority exception to hardfault.

The HFSR.FORCED is set to 1.

The forced fault is not always the same. Here are the observed fault (for same code however !):

  • A coprocessor access error has occurred (CFSR.NOCP)
  • The processor has attempted to execute an undefined instruction (CFSR.UNDEFINSTR).

with PC=0x0 and LR=0x01

The exception is always raised after the following code (excerpt from xQueueReceive()):

if( xTaskResumeAll() == pdFALSE )
{
 /* Set a PendSV to request a context switch. */
 portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
 __DSB();
 __ISB();
}

The Idle task is never entered !

I have a limited knowledge of the Cortex M7 Interrupt system. I must dive into it. Meanwhile, how can I investigate such a problem ? Any support is welcome.

Thanks

Some more info about FreeRTOS config:

 #define configENABLE_FPU 0
 #define configENABLE_MPU 0
 
 #define configUSE_PREEMPTION 1
 #define configSUPPORT_STATIC_ALLOCATION 1
 #define configSUPPORT_DYNAMIC_ALLOCATION 1
 #define configUSE_IDLE_HOOK 1
 #define configUSE_TICK_HOOK 0
 #define configCPU_CLOCK_HZ ( SystemCoreClock )
 #define configTICK_RATE_HZ ((TickType_t)1000)
 #define configMAX_PRIORITIES ( 56 )
 #define configMINIMAL_STACK_SIZE ((uint16_t)128)
 #define configTOTAL_HEAP_SIZE ((size_t)15360)
 #define configMAX_TASK_NAME_LEN ( 16 )
 #define configUSE_TRACE_FACILITY 1
 #define configUSE_16_BIT_TICKS 0
 #define configIDLE_SHOULD_YIELD 0
 #define configUSE_MUTEXES 1
 #define configQUEUE_REGISTRY_SIZE 8
 #define configUSE_RECURSIVE_MUTEXES 1
 #define configUSE_COUNTING_SEMAPHORES 1
 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
 #define configRECORD_STACK_HIGH_ADDRESS 1

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

    Found the error : in the xPortPendSVHandler() call, I could observe that the LR register was set to a spurious value (0x00000001) while popping the core registers for the Idle task. From there, it was easy to identify a stack overflow issue.

    Thanks to @Pavel A.​ and to @Community member​ for your support. Best regards

    5 replies

    Super User
    April 14, 2023

    Do you use floating point? If so, define configENABLE_FPU 1

    TPierAuthor
    Visitor II
    April 14, 2023

    No use of floating point.

    Thanks for this clarification.

    Graduate II
    April 14, 2023

    On CM7 with DMA, watch for a) Cache Coherency and b) Life/Scope of buffer

    Look if you use stack or auto/local variables for DMA buffers

    Look at buffer alignment, caching is on 32-byte boundaries.

    Use ByAddr cache management to limit action.

    Avoid DCacheInvalidate unless necessary and watch for serious side-effects

    TPierAuthor
    Visitor II
    April 14, 2023

    Waw ! Thanks for all those points to check !

    I did not look at the DMA side since any communication worked fine. I'll do and come back with more info ...

    TPierAuthor
    Visitor II
    April 14, 2023

    I temporarily avoid the hard fault by creating an additional task that is always active (endless loop). This plays the role of the Idle task.

    What could prevent to use the default Idle task ?

    TPierAuthor
    Visitor II
    April 17, 2023

    Actually, where is the the "PendSV_Handler" defined ?

    TPierAuthor
    Visitor II
    April 17, 2023

    Forget this. Apologizes

    TPierAuthorAnswer
    Visitor II
    April 17, 2023

    Found the error : in the xPortPendSVHandler() call, I could observe that the LR register was set to a spurious value (0x00000001) while popping the core registers for the Idle task. From there, it was easy to identify a stack overflow issue.

    Thanks to @Pavel A.​ and to @Community member​ for your support. Best regards