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
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…
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):
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:
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.
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:
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.
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.
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.