xSemaphoreGiveFromISR Not Making Task Ready

jtorkelson wrote on Wednesday, April 18, 2018:

I’m using a binary semaphore, I believe correctly, to notify/wake up a task from an ISR, and it appears to not be working. This is FreeRTOS v10.0.1.

My code:

SemaphoreHandle_t SemBytesReceived = 0;

// Init Function
SemBytesReceived = xSemaphoreCreateBinary();
// Init Function

// Inside a task
xSemaphoreTake(SemBytesReceived, portMAX_DELAY)
// Inside a task

// Inside the ISR
static BaseType_t xHigherPriorityTaskWoken;
xSemaphoreGiveFromISR(SemBytesReceived, &xHigherPriorityTaskWoken);
// Inside the ISR

What happens:

  1. When the semaphore is created the semaphore (Queue_t)'s cTxLock value is -1.
  2. When the semaphore is ‘Taken’ in the task, the cTxLock value is locked (set to 0) at queue.c line 1503
  3. When the ISR is generated, and the XSemaphoreGiveFromISR function is called, if the cTxLock value is -1/unlocked, queue.c line 1136 evaluates to true and the task is removed from the waiting list at queue.c line 1169. But if the queue is locked, the task isn’t removed from the waiting list and never wakes up.

Am I using this correctly? The xSemaphoreGiveFromISR macro will return 1, but the xHigherPriorityTaskWoken won’t be set to 1 unless the queue (semaphore) was unlocked.

Thanks

heinbali01 wrote on Thursday, April 19, 2018:

Do you also yield in the ISR?

Here is an example:

    /* Don't make this a static variable, and initialise it to zero. */
BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    xSemaphoreGiveFromISR(SemBytesReceived, &xHigherPriorityTaskWoken);
	portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

Here yielding means that the scheduler will check if a new task should become active.

jtorkelson wrote on Thursday, April 19, 2018:

Yes I am yielding, nominally at least, in that I’m calling the yield function with xHigherPriorityTaskWoken as an argument. But xHigherPriorityTaskWoken is being set to 0 by the GiveFromISR.

However I’m running this in a simulator and am getting inconsistent results… the above description was exactly true “some of the time”. But now I’m seeing something else… The queue should be unlocked after being locked in item 3 above.

Although I’m still seeing the task wake up, I’m not seeing consistency on why it isn’t waking up. Pretty sure if has something to do with my simulator port, just not seeing what it is.

rtel wrote on Thursday, April 19, 2018:

Which simulator are you using?

jtorkelson wrote on Thursday, April 19, 2018:

It’s a simulator we are developing (https://www.virtuoso-software.com/, not yet released, need to talk to you at some point about this by the way Richard.) This is for an active development project, but also translates to a target template, which allows-drag-and-drop addition of a target running FreeRTOS. I can drag-and-drop a target and get up and running flashing an LED or reading a virtual pot with FreeRTOS in less than a minute, but having trouble with the semaphore in this actual development project.

I’m about 99% convinced there’s a bug with the default Windows simulator’s hypervisor. When the semaphore yield implementation releases the mutex with the assumption that the hypervisor is going to immediately hault that thread, it actually keeps executing for some time before the hypervisor can stop it, and I believe that is causing issues. I have a concept to synchronize/interlock to ensure that the thread doesn’t run until the hypervisor has explicitly acknowledged that it’s ready to run again, will share what learn with you if it is of interest. It’s of course possible I’m still doing something wrong, but based on what I’m seeing I’m pretty confident.

rtel wrote on Thursday, April 19, 2018:

I’m not sure which hypervisor you are talking about, but if it helps,
the FreeRTOS Windows port only works if all the threads are tied to the
same CPU core. If you let Windows decide which core to run a thread on
then the threads get spread across all available cores, and the result
is exactly the issue you describe below (tasks don’t stop immediately
they are instructed to, and the whole system breaks down).

jtorkelson wrote on Thursday, April 19, 2018:

Thanks Richard, I’m sure that’s what’s going on.