xSemaphoreGiveFromISR / xSemaphoreTake
I’m using Eclipse, yagarto gcc, olimex jtag and LPC2388.
My project is using at last 12 tasks and uses binaries somaphores to synchronizate tasks and ISRs.
Apparently the problem appears when the ISR gives the semaphore through xSemaphoreGiveFromISR when the scheduler is currently suspended. In this case the portYIELD_FROM_ISR() does not work. Under this condition the task that is waiting for the somaphore through xSemaphoreTake will never be waked up by the scheduler.
What am I doing wrong?
Task:
…
if( xSemaphoreTake(xI2cSemaphore, portMAX_DELAY )== pdPASS )
{
…
}
…
ISR:
…
xSemaphoreGiveFromISR( xI2cSemaphore, &xHigherPriorityTaskWoken );
if( xHigherPriorityTaskWoken == pdTRUE )
{
portYIELD_FROM_ISR();
}
…
Regards,
Marcus
xSemaphoreGiveFromISR / xSemaphoreTake
There does not appear to be anything wrong with the structure of the code as you have posted it.
If a task is unblocked by an ISR while the scheduler is suspended then the task will be removed from the block list and added to the "pending ready" list. Tasks are removed from the pending ready list and added to the ready list at the point that the scheduler is unsuspended.
Is your I2C semaphore using in just one task and purely for synchornisation with the ISR?
Regards.
xSemaphoreGiveFromISR / xSemaphoreTake
Well, I gonna start explaining what I am doing in this part of project…
I have a IC2 EEPROM memory. Instead of have a Task to manage this memory I decided to create a service that any task can access. This service is composed by two levels.
The first level accesses the EEPROM service through a MUTEX. So if the task want to read or write the EEPROM it must first wait for the resource to be free.
The second level is the I2C access, which is synchronized by a binary semaphore because it depends of an ISR.
The structure is like that:
BOOL E2promRead(…)
{
if( xSemaphoreTake(xE2PROMSemaphore,portMAX_DELAY ) == pdPASS )
{
…
KI2cRead( … );
…
xSemaphoreGive( xE2PROMSemaphore );
return TRUE;
}
}
BOOL KI2cRead( … )
{
if( xSemaphoreTake(xI2cSemaphore, portMAX_DELAY ) == pdPASS )
{
…
}
}
ISR:
…
xSemaphoreGiveFromISR( xI2cSemaphore, &xHigherPriorityTaskWoken );
if( xHigherPriorityTaskWoken == pdTRUE )
{
portYIELD_FROM_ISR();
}
…
A similar structure is used for writing.
Thanks for your imemdiate answer!
Regards
xSemaphoreGiveFromISR / xSemaphoreTake
Out of interest, try making both semaphores binary semaphores (not mutex). It should not make any difference, but…
xSemaphoreGiveFromISR / xSemaphoreTake
Thank you!!!! This problem is solved.
Unfortunately I have one more headache still related to the same subject:
I have a logging task witch uses an xSemaphoreTake to wait for a buffer to be saved. The block time of this xSemaphoreTake is used as a timeout to flush the current buffer. I am using 30 seconds as timeout but the ISR that gives the semaphore is giving it at each 1 second. The problem is that the xSemaphoreTake is ignoring the gives that the ISR is doing until the end of the block time. After these 30 seconds the xSemaphoreTake start to work properly.
Now I have found a work around where I first give this semaphore from the task. So the xSemaphoreTake takes the semaphore and the task flushes an empty buffer. After that everything starts work properly.
Thank you again!
Regards,
Marcus