cancel
Showing results for 
Search instead for 
Did you mean: 

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

TPier
Associate III

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

1 ACCEPTED SOLUTION

Accepted Solutions
TPier
Associate III

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

View solution in original post

9 REPLIES 9
Pavel A.
Evangelist III

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

No use of floating point.

Thanks for this clarification.

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

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

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 ...

The 2 first points have been checked.

  • Every buffer for DMA is statically allocated.
  • The buffer alignment with 32-bytes boundaries is well observed for large buffer, but not for short ones (e.g. register operation on I2C bus). Is this alignment rule absolute ?

For the 2 last points, it is not clear to me. I need to look for some more info.

TPier
Associate III

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 ?

TPier
Associate III

Actually, where is the the "PendSV_Handler" defined ?

TPier
Associate III

Forget this. Apologizes

TPier
Associate III

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