In a CortexM3 SiLabs EZR32, I use FreeRTOS (V7.5.2 provided with the IDE of my microcontroller) and a SPI port sharing five SPI devices : a SRAM, a FLASH, an accelerometer, an RF driver and a 3G Modem.
The firmware periodically accesses to all of those devices.
To protect access to the SPI port, I've used a mutex "xSPIMutex".
So before each acces to an SPI device, I call xSemaphoreTake(xSPIMutex, portMAXDELAY), and after each access I call xSemaphoreGive(xSPIMutex).
SPI port is never used in an interrupt subroutine, but only called from a task.
One of the tasks accessing to the PSI port has a higher priorty for the use of SPI. That's why I added in this task :
vTaskPrioritySet(xTaskGetCurrentTaskHandle(), TASKUSUALPRIORITY + 1);
before any access to the SPI port, and
after each acces.
My problem is that after a few seconds and a few volleys of access to the SPI port, a xSemaphoreGive(xSPIMutex) ends with a uxMutexesHeld = 0 :
- xSemaphoreGive(xSPIMutex) calls xQueueGenericSend
- xQueueGenericSend calls prvCopyDataToQueue
- prvCopyDataToQueue calls xTaskPriorityDisinherit
- xTaskPriorityDisinherit finds a blank pxTCB->uxMutexesHeld so when it calls configASSERT it enters a while(1); loop.
The problem does not occurin the task in which the priority is higher.
Here's a part of FreeRTOSConfig.h :
define configMAXPRIORITIES ( 4 )
define configMINIMALSTACKSIZE (( unsigned short ) 140)
define configTOTALHEAPSIZE (( sizet )(10000))
define configMAXTASKNAMELEN ( 10 )
define configUSETRACEFACILITY ( 0 )
define configUSE16BITTICKS ( 0 )
define configIDLESHOULDYIELD ( 0 )
define configUSEMUTEXES ( 1 )
define configUSERECURSIVEMUTEXES ( 0 )
define configUSECOUNTINGSEMAPHORES ( 0 )
define configUSEALTERNATIVEAPI ( 0 )/* Deprecated! */
define configQUEUEREGISTRYSIZE ( 10 )
define configUSEQUEUE_SETS ( 0 )
I've tried to increase "configQUEUEREGISTRYSIZE" and "configMINIMALSTACKSIZE" with no effect.
"configTOTALHEAPSIZE" can not be higher, as all available RAM seems to be already used.
For each SPI device, I've written a deviceselect() and a deviceunselect() function where I take then give the mutex.
Those functions are called before and after each access to SPI.
Could anyone help me ?
Thank you for any help.
A problem here is that you are using a very old version of FreeRTOS so
its difficult to give a definitive answer. However, it might be
because you are changing the task's priority while it has the mutex.
Mutexes have a built in priority inheritance mechanism which records the
priority of the mutex holder and I'm not sure what would happen if you
were to change the priority while the mutex was held - if nothing else
the there would be an inconsistency in the data structures. The
priority inheritance mechanism would probably make your manual
manipulation of the priority obsolete in any case.
Thank you for this answer.
In fact I already wanted to keep the same priority when I take and give the semaphore. Here's the sequence : I take the semaphore, increase priority, use SPI, decrease priority and give back the semaphore. All other tasks that use this semaphore run with the same priority (I've tried to always be in the same priority when I take and give this semaphore).
Now the problem is not on the SPI semaphore, but on the semaphore which protects the modem accesses.
I've just run my firmware without the priority change. I have the same problem : a xSemaphoreGive generates a null uxMutexesHeld.
Anyway, I've replaced all the FreeRTOS source files of my firmware by all the files of the last FreeRTOS version (V9.0.0, downloaded here : https://sourceforge.net/projects/freertos/?source=typ_redirect).
I have not changed FreeRTOSConfig.h
The project compiles.
The problem is still there.
I've removed the xSemaphore Take and Give for the modem accesses and I've made sure that no other task could access the modem, and... I don't have the problem any more.
It's very strange because the function only sends a simple ASCII command to the modem and what it does is :
manage modem reception
send radio frame (ASCII command to modem)
send command to modem and wait for response
send radio frame (ASCII response of the modem)
xSemaphoreGive(xModemMutex); <- the problem occurs here
Any idea ?
Thank you !
I suppose it could just be some form of data corruption clobbering the
You can find some quite detailed mutex tests in this file:
- see functions such as prvHighPriorityTimeout(),
prvTakeTwoMutexesReturnInSameOrder(), prvLowPriorityMutexTask(), etc.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.