How to debug to resolve configASSERT( pxQueue->uxItemSize == 0 ); loop error?

dear friends,

My program is getting stuck in
configASSERT( pxQueue->uxItemSize == 0 );
in xQueueSemaphoreTake call.

I know it is memory corruption, but is there a way to diagnose it ? it has suddenly occurred, the code was running good before.
And this doesnt happen on every reboot, some time it runs perfectly, but some time it gets hang in sema call.

I tried looking for RTOS heap, xPortGetFreeHeapSize() return around 9K heap free available. I also tried increase task stack size, but that didnt help either.

Kindly help me troubleshoot this problem

Not a direct answer, and as it only happens on some reboots probably not the source, but that assert checks the object passed into the function is a semaphore, and not a queue. Semaphores being implemented using queues.

Memory corruption issues are very difficult to track down. The most likely causes are:

  1. Stack overflow. You tried increasing stack sizes. Take a look at this link FreeRTOS - stacks and stack overflow checking for more idea for debugging the stack.
  2. Buffer overflow. This could be as simple as string operations without a NULL terminator or other more complicated issues where a pointer offset is miscalculated. If it is a “stray pointer” type bug then it will likely tied to a specific function. The memory corruption could also be happening all the time but due to inconsistent initialization sequences, you may not notice the affect in every case.

I recommend trying to operate with static memory allocation in an effort to place all the memory objects in memory in a consistent pattern. This hopefully will have the effect of making the failure more consistent and observable. If you can get the corruption consistent, you can set data watch breakpoints on specific addresses (assuming a debugger). This will allow your code to halt as soon as the corruption occurs. The trick is getting the corruption to happen in a specific location so you can set the watch.

Good Luck

Is this a standard port or a custom port? Frequent causes for your problem on custom ports are misconfigured timer and/or service interrupt priorities as well as wrong implementations of the critical section. Also ensure that your isrs comply with the FreeRTOS API requirements (ie isrs must only use xxxFromISR() flavors of APIs and must run < max syscall pri if they use those APIs).

Finally, ensure that all objects you use (queues, semaphores etc) were created properly before being accessed.

Hey @jjulich Thanks for responding,

i have implemented stack overflow hook, and it doesnt display any stack oveflow. There is not much dynamic memory handling in the code.

what i deduced from debugging is that my semaphore content is getting changed, i am unable to see the source where it gets changed.

SO i found out the issue,

SO as happens to be i few task defined, for example
xTaskCreate ( task1, … );
xTaskCreate ( task2, … );
xTaskCreate ( task3, … );
xTaskCreate ( task4, … );

the problem that i was facing was when executing code in task3. i tried disabling task below task3 and it didnt work, task1 is very imp, so i couldnt disable it, but when i increased task stack depth from 100 to 200 for all, task1 started giving me stack overflow. so then again increased stackdepth to 400 and the issue was resolved.

so my question is the semaphore is global variable, and is defined before task1, the fault was raised by task3 when call semaphore, but increasing task1 stack how does it solve issue? what i am missing here

i cannot upload but i am sharing the content of FreeRTOS.h file


#define configUSE_PREEMPTION                     1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION  1
#define configCPU_CLOCK_HZ                       ( 80000000UL )
#define configTICK_RATE_HZ                       ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES                     ( 8 )
#define configMINIMAL_STACK_SIZE                 ( ( unsigned short ) 200 )
#define configMAX_TASK_NAME_LEN                  ( 12 )
#define configUSE_16_BIT_TICKS                   0
#define configIDLE_SHOULD_YIELD                  1
#define configUSE_TASK_NOTIFICATIONS             1
#define configUSE_MUTEXES                        1
#define configUSE_RECURSIVE_MUTEXES              1
#define configUSE_COUNTING_SEMAPHORES            1
#define configQUEUE_REGISTRY_SIZE                0
#define configUSE_QUEUE_SETS                     0
#define configUSE_TIME_SLICING                   1
#define configUSE_NEWLIB_REENTRANT               0
#define configENABLE_BACKWARD_COMPATIBILITY      1
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS  0
#define configUSE_APPLICATION_TASK_TAG           0

/* Memory allocation related definitions. */
#define configSUPPORT_STATIC_ALLOCATION          0
#define configSUPPORT_DYNAMIC_ALLOCATION         1
#define configTOTAL_HEAP_SIZE                    ( ( size_t ) 24576 )
#define configAPPLICATION_ALLOCATED_HEAP         0

/* Hook function related definitions. */
#define configUSE_IDLE_HOOK                      1
#define configUSE_TICK_HOOK                      0
#define configCHECK_FOR_STACK_OVERFLOW           2
#define configUSE_MALLOC_FAILED_HOOK             0
#define configUSE_DAEMON_TASK_STARTUP_HOOK       0

/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS            0 
#define configUSE_TRACE_FACILITY                 0
#define configUSE_STATS_FORMATTING_FUNCTIONS     0

/* Co-routine related definitions. */
#define configUSE_CO_ROUTINES                    0
#define configMAX_CO_ROUTINE_PRIORITIES          ( 2 )

/* Software timer related definitions. */
#define configUSE_TIMERS                         1
#define configTIMER_TASK_PRIORITY                ( 3 ) 
#define configTIMER_QUEUE_LENGTH                 10
#define configTIMER_TASK_STACK_DEPTH             200

/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet                 1
#define INCLUDE_uxTaskPriorityGet                1
#define INCLUDE_vTaskDelete                      1
#define INCLUDE_vTaskSuspend                     1
#define INCLUDE_vTaskDelayUntil                  1
#define INCLUDE_vTaskDelay                       1
#define INCLUDE_xTaskGetSchedulerState           1
#define INCLUDE_xTaskGetCurrentTaskHandle        1
#define INCLUDE_uxTaskGetStackHighWaterMark      1
#define INCLUDE_xTaskGetIdleTaskHandle           0
#define INCLUDE_eTaskGetState                    0
#define INCLUDE_xEventGroupSetBitFromISR         1
#define INCLUDE_xTimerPendFunctionCall           1
#define INCLUDE_xTaskAbortDelay                  1
#define INCLUDE_xTaskGetHandle                   1
#define INCLUDE_xTaskResumeFromISR               1
#define INCLUDE_xQueueGetMutexHolder             1

/* Definition assert() function. */
#define configASSERT(x)                          if((x)==0) { taskDISABLE_INTERRUPTS(); for( ;; ); }   

/* Tickless Idle Mode */
#define configUSE_TICKLESS_IDLE                  0

/* Additional settings can be defined in the property Settings > User settings > Definitions of the FreeRTOS component */

/* Run time stats gathering definitions. */
#ifdef __ICCARM__
	/* The #ifdef just prevents this C specific syntax from being included in
	assembly files. */
	void vMainConfigureTimerForRunTimeStats( void );
	unsigned long ulMainGetRunTimeCounterValue( void );
#endif
#ifdef __GNUC__
	/* The #ifdef just prevents this C specific syntax from being included in
	assembly files. */
	void vMainConfigureTimerForRunTimeStats( void );
	unsigned long ulMainGetRunTimeCounterValue( void );
#endif

/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
  #define configPRIO_BITS                         __NVIC_PRIO_BITS
#else
  #define configPRIO_BITS                         4
#endif

/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY  (0x0F)

/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY	 (0x01)

/* Interrupt priorities used by the kernel port layer itself.  These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#ifndef configKERNEL_INTERRUPT_PRIORITY
  #define configKERNEL_INTERRUPT_PRIORITY         (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8-configPRIO_BITS))  
#endif
  
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#ifndef configMAX_SYSCALL_INTERRUPT_PRIORITY
  #define configMAX_SYSCALL_INTERRUPT_PRIORITY    (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8-configPRIO_BITS))
#endif

/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler                             SVC_Handler
#define xPortPendSVHandler                          PendSV_Handler
#define xPortSysTickHandler                         SysTick_Handler

It is the very nature of concurrent software that problem causes and symptoms appear completly unrelated. In order to figure out what exact control flow eventually led from your root cause to the failure, we would need to see and study the code and runtime behavior - obviously the stack of your misconfigured task was close to a dynamically allocated semaphore, so some time after the memory before your task overtrampled the semaphore structure, other code that tried to access the semaphore failed. Yet if the root cause is known, there is generally no point in pinpointing the exact chain of events. The important lesson to learn is to develop an eye for the nature of such sequences and to be able to identify and the “usual suspects” even in places completly unrelated to the symptom failure. It will save you shiploads of debugging time.

You may find a tool like Percepio Tracealyzer helpful in this situation. It will generate a trace of all the FreeRTOS operations in sequential order and this could help you determine the sequence that causes trouble.