xTaskPriorityDisinherit fails with assert

I am ussing FreeRTOS 8.2.1 and have created a Mutex using xSemaphoreCreateMutex. This Mutex is being used as follows,

Thread1 (low priority and low frequency periodic task):

  • xSemaphoreTake(handle, portMAX_DELAY) //This task should not proceed if it doesn’t have the mutex
  • do some processing using shared resource
  • xSemaphoreGive(handle)

Thread2 (high priority and high frequency periodic task):

  • some processing without shared resource
  • xSemaphoreTake(handle, timeout) // do not wait for mutex indefinitely
  • if mutex is taken successfully
    • some processing using shared resource
    • xSemaphoreGive(handle)

I am receiving assertion pxTCB == pxcurrentTCB failed in function xTaskPriorityDisinherit

Looking at the way we are using this Mutex, this should not happen. Any thoughts?

That code looks like it should work, but if you check the stack trace you might be able to figure out who is giving up the mutex when it didn’t have it.

Even with a delay of portMAX_DELAY, I always check the return value of the take to make sure it was successful, and my most typical usage would be something like:

    if(xSemaphortTake(handle, delay)) {
         // Code for handling the successful take

As this structure provides a positive guard for the usage. Sometime this structure doesn’t fit what the program is doing, but I still will always check the success.

The assertion you are hitting is indicating that someone who doesn’t currently own the mutex is trying to give it.

It is also possible you have an interrupt priority issue that cause program problems, 8.2.1 may be old enough that it may be missing some of the checks.

Yes - would recommend updating to a newer version then ensuring configASSERT() is defined. If you are using a Cortex-M the later the version the more programmatic checks there are. In any case I would recommend reading through this: https://www.freertos.org/FAQHelp.html

Just a quick note to say thanks! I did not know that. I thought xSemaphoreGive() would return pdFAIL for that case. And two of my own APIs were affected. My functions spi_close() and i2c_close() are written to tolerate a user calling them unnecessarily. I had comments in each one that said “we don’t need to bother verifying that the current task is the mutex owner since FreeRTOS verifies that for us”. Oops!