Timer thread stuck in a vListInsert

Hi everyone,

I’m currently using FreeRTOS V9.0.0 on STM32H7A3. I have encountered an issue with the Timer thread getting stuck in an infinite for-loop in vListInsert.

The problem is that pxNext is pointing to the last element in the list, and its value is less than xValueOfInsertion, causing it to be trapped in the for loop. There are comments in the code explaining four potential causes of this issue.

		/* *** NOTE ***********************************************************
		If you find your application is crashing here then likely causes are
		listed below.  In addition see http://www.freertos.org/FAQHelp.html for
		more tips, and ensure configASSERT() is defined!
		http://www.freertos.org/a00110.html#configASSERT

			1) Stack overflow -
			   see http://www.freertos.org/Stacks-and-stack-overflow-checking.html
			2) Incorrect interrupt priority assignment, especially on Cortex-M
			   parts where numerically high priority values denote low actual
			   interrupt priorities, which can seem counter intuitive.  See
			   http://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition
			   of configMAX_SYSCALL_INTERRUPT_PRIORITY on
			   http://www.freertos.org/a00110.html
			3) Calling an API function from within a critical section or when
			   the scheduler is suspended, or calling an API function that does
			   not end in "FromISR" from an interrupt.
			4) Using a queue or semaphore before it has been initialised or
			   before the scheduler has been started (are interrupts firing
			   before vTaskStartScheduler() has been called?).
		**********************************************************************/

I have gone through all four cases but haven’t been able to prevent this problem from occurring.

configASSERT is defined, and my application doesn’t run into an assert trap when this issue happens.

/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }

I also tried

#define configASSERT( x ) assert(x)

I also set configCHECK_FOR_STACK_OVERFLOW to 2 and add vApplicationStackOverflowHook, and still my application doesn’t run into an assert trap when this issue happens.

void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName )
{
	assert(0);
}

This issue happens when my application wakes up from sleep (stop2 mode), and the timer thread gets stuck in vListInsert <5% after waking up.

I’m not sure how to proceed to resolve this issue. Could someone please help me troubleshoot this problem and suggest what I can do to gather more information to resolve this issue? Thanks!

A couple of troubleshooting ideas:

  1. Try the newest kernel version. It’s backwards compatible, so the upgrade should go very smoothly, with no changes required to your application code. The benefit of newer kernel versions is that they use configASSERT() to check for the very things that can cause your issue.
  2. Try avoiding low-power modes. Typically that means temporarily setting configUSE_TICKLESS_IDLE to zero, but depending on your code it may also mean setting configUSE_IDLE_HOOK to zero. Do you know which of these two low-power strategies you are using?

Hello @ramcal,

As for configASSERT(), many developers prefer to define it as follows:

// FreeRTOSConfig.h :
    void vAssertCalled( const char *pcFile, uint32_t ulLine );
    #define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ );

// main.c :
    volatile const char * pcAssertedFileName;
    volatile uint32_t ulAssertedLine;

    void vAssertCalled( const char * pcFile,
                        uint32_t ulLine )
    {
        volatile uint32_t ulBlockVariable = 0UL;
    
        ulAssertedLine = ulLine;
        pcAssertedFileName = pcFile;
        for( ;; )
        {
            /* Put a break here. */
            __NOP();
        }
    }

That allows you to put a break before another problem occurs. Even disabling interrupts can get your program into another assert or crash.

I would not trust the provided implementation of assert().

About vApplicationStackOverflowHook() : it works in many occasions, but it may happen that a crash comes earlier than the detection of the stack overflow.

void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName )
{
-    assert(0);
+    configASSERT(0);
}

In my applications, I have a command that shows the highest usage of the stack per task. That is my guideline for safely assigning stack memories.

1 Like