Mutex cannot be 'given', although has the value of '0'

I need two tasks to use a single ethernet interface in the device I am working with (MPC5748G from NXP). I decided to use a mutex to control the access to the resource. I quickly figured out that the mutex cannot be given by xSemaphoreGive(), although its value is ‘0’ just before the function call.
Debugging showed that an assert is thrown by xQueueGenericSend() in queue.c, precisely speaking the application freezes on this piece of code in devassert.h :
static inline void DevAssert(volatile bool x) { if(x) { } else { BKPT_ASM; for(;;) {} } }

I don’t understand why this happens, the configSUPPORT_DYNAMIC_ALLOCATION is set to 1, so creating a dynamic mutex should work.

main.c:

    #include "../include/CANfuncs.h"

    SemaphoreHandle_t ethernet_sem;
    int main(void)
    {
      /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
      #ifdef PEX_RTOS_INIT
        PEX_RTOS_INIT();                   /* Initialization of the selected RTOS. Macro is defined by the RTOS component. */
      #endif

    CLOCK_SYS_Init(g_clockManConfigsArr, (uint8_t)CLOCK_MANAGER_CONFIG_CNT, g_clockManCallbacksArr, (uint8_t)CLOCK_MANAGER_CALLBACK_CNT);
    CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_AGREEMENT);

    /* Initialize pins */
    PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr);

    ethernet_sem = xSemaphoreCreateMutex();

	xTaskCreate(vTestTask, "testTask", 256U,NULL, 3, NULL);
	vTaskStartScheduler();

	#ifdef PEX_RTOS_START
	PEX_RTOS_START();                
	#endif		
	for(;;) {
	 if(exit_code != 0) {
  		break;
		}
	}
	  return exit_code;
	}

CANfuncs.c:

 void vTestTask(void* pvParameters){
  for(;;){
    	vTaskDelay( 4000 / portTICK_PERIOD_MS );
    	/* show the value of a semaphore for the debug */
    	UBaseType_t semaphore_val1;
    	semaphore_val1 = uxSemaphoreGetCount(ethernet_sem);

    	if(xSemaphoreTake(ethernet_sem, portMAX_DELAY) == pdTRUE ){
    	     retval = UDPStringSend();
	         semaphore_val1 = uxSemaphoreGetCount(ethernet_sem);  //Mutex here is '0'
    	     xSemaphoreGive(ethernet_sem);    //Crashes here!
    	    }
       };
  }

Does anybody see anything wrong in the code above? I would be grateful for any tips or advice

Which line is causing the assert failure?

xSemaphoreGive() causes the assert failure.

I think the question is which line in the semaphore code is asserting.

The code looks right (assuming CANfuncs.c has an extern SemahoreHandle_t ethernet_sem; statement). It could be memory corruption breaking the mutex.

the CANfuncs.c doesn’t have the ethernet_sem variable as ‘extern’ - maybe that is the problem.
I managed to compile the code tough and even got the value of the semaphore with GetCount(), so I just didn’t assume that the variable is wrongly declared…

Telling us your code is getting stuck in this line is not helpful because it is called from every configASSERT() statement in the kernel code. We need to know which call to configASSRT() is causing you to enter the for( ;; ) loop. Please see the documentation for the configASSERT() macro: https://www.freertos.org/a00110.html#configASSERT

It has to have the variable declared somehow, perhaps in a header file that is included.

If it isn’t extern, then it will have its own copy of the handle, which would then be NULL, so it should fail earlier

Hello peter1,

You may already notice this idea… I think that it is better for you to change back the definition of configASSERT() like the followings even if the definition is provided by NXP.

Not good (the following code of your FreeRTOSConfig.h is my guess):

static inline void DevAssert(volatile bool x);
#define configASSERT(x) DevAssert((bool)(x))

Better:

#define configASSERT(x) do{ if(x) { } else { BKPT_ASM; for( ;; ) {} } }while(0)

This change makes you and the debugger to catch up the just asserted line.

Best regards,
NoMaY

thanks for all of the replies.

I added the declaration of the variable as extern, however the problem is still there.
The assert is thrown from the xQueueGenericSend() in the queue.c. This function is called directly after xSemaphoreGive() .
Precisely this line is problematic:

configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );

here, the pvItemToQueue is 0, and the uxItemSize of pxQueue is 1073776744. In this way the whole expression evaluates to 0 ( not (TRUE and TRUE)) and an assert is thrown.

Unfortuntelly I don’t know how to approach the problem further - should the pvItemToQueue be different from 0, or is the size of the item in the queue wrong?

uxItemSize is wrong, it should be 0 for a semaphore/mutex. This likely indicates that somewhere in your program you are corrupting memory by writing outside an array or with a wrong pointer or the like.

1 Like

Thanks to all the tips I decided to change use a static mutex.
I set the configSUPPORT_STATIC_ALLOCATION to 1, provided the default vApplicationGetIdleTaskMemory() and vApplicationGetTimerTaskMemory() functions (I used the default example from here, even though I don’t fully understand the consequences) and created a static mutex. I changed the mutex initialization to this:

SemaphoreHandle_t ethernet_sem;
StaticSemaphore_t xStaticEthernetSemaphoreBuffer;
int main(){
    ....
   ethernet_sem = xSemaphoreCreateMutexStatic( &xStaticEthernetSemaphoreBuffer );
   ....
}

and left the other part of the code as it was.

Unfortunatelly it still doesn’t work.
The semaphore gets created, with a value of 1 and can get taken. It can also be given, so the code does a single iteration.
However this time xSemaphoreTake() returns a semaphore that has a value of 1073776000. Suprisingly the xSemaphoreGive() returns no error. However, in the second iteration, when the same semaphore has to be taken it returns an error. Precisely speaking xQueueSemaphoreTake() fails on configASSERT( pxQueue->uxItemSize == 0 );, because the ItemSize is again not 0.

Does it mean that I corrupted some memory again? How can this happen if I am using a static call for a semaphore initialization?

However this time xSemaphoreTake() returns a semaphore that has a value of 1073776000.

Which means that the memory is already corrupted. Is it possible for you to put a data breakpoint at the location of pxQueue->uxItemSize after your semaphore is created?

How can this happen if I am using a static call for a semaphore initialization?

Most probably, some other piece of code is corrupting the memory.

Thanks.

Do you have configASSERT() defined and also stack overflow checking enabled (for development/debugging) ?
In the original post the test task stack size is only 256, which might be too small…
Stack overflows are a common source of memory corruption.

1 Like

When you create the semaphore does the call actually succeed?

   ethernet_sem = xSemaphoreCreateMutex();

   if( ethernet_sem != NULL )
   {
       /* The semaphore was created successfully and
       can be used. */
   }

Jacob

Are you sure the linker script and C startup code are correct for your device? If you declare a variables such as:

volatile uint32_t ulInitialisedGlobal = 0x11111111UL;
static volatile uint32_t ulInitialisedStaticGlobal = 0x22222222UL;
volatile uint32_t ulUnInitialisedGlobal;
static volatile uint32_t ulUnInitialisedStaticGlobal;

where the semaphore is declared, then stop the program in the debugger on entry to main and view these variables - do they all contain the expected values? If not then there is something wrong before main() is even called.

That was it, the stack designed for this task was too small. I changed it to 2048 and now it works.
Thanks for all the help!