Multiple calls xQueueSendFromISR

guillep2k wrote on Monday, January 23, 2006:

Hi. I am using FreeRTOS in a LPC2138 board. Since I’ve been having some problems with interrupts, I’ve been wondering: what happens if my ISR, using xQueueSendFromISR, is executed two consecutive times with no other code in between? It will call xQueueSendFromISR with xTaskPreviouslyWoken in both executions, and perhaps the first time it got a pdTRUE. This is -I think- equivalent to calling xQueueSendFromISR twice in the same ISR execution with xTaskPreviouslyWoken == pdFALSE in both calls.

Guille

rtel wrote on Monday, January 23, 2006:

I think this depends on how your interrupt is executed twice.

xTaskPreviouslyWoken is an (optional) method of ensuring that an interrupt only wakes one task per interrupt - if this is the behaviour you want.

As an example, assume you have a serial port interrupt that processes received characters and there happens to be two characters in the buffer when the interrupt fires.  There are also two tasks waiting on the queue for characters to be available:

If your ISR contains a loop as

ISR_Function()
{
____xTaskPreviouslyWoken = false;

____while( buffer_not_empty )
____{
________GetNextCharFromBuffer();
________PostCharToQueue();
____}
}

then the loop will execute twice.  The first time xTaskPreviouslyWoken will be false, so posting to the queue will wake the task higher priority of the two waiting tasks.  The next time round the loop (to get the second character from the buffer) xTaskPreviouslyWoken will be true, so the second task will not be woken but remain suspended on the queue.  Now there is one task woken and two characters available in the queue so it assumed that the single task will read both characters from the queue.

Now if you write your ISR as

ISR_Function()
{
____xTaskPreviouslyWoken = false;

____GetNextCharFromBuffer();
____PostCharToQueue();
}

Only one character is taken out of the buffer each time the ISR fires - so as there are two characters in the buffer the ISR will fire twice.  Each time it fires xTaskPreviouslyWoken is set to false, resulting in one task being woken on the first ISR execution and the other task being woken on the second execution.

Now you will have two tasks reading the characters.  Whether this is want you want or not is completely application dependent.  A task may read a single character then sleep - allowing the other task to ready the other character.  Conversely a task may read both characters, meaning the queue is empty when the second task runs.

Of coarse none of this matters if you only have a single task waiting on the queue at a time - which would be normal in most applications.  Otherwise it is best to check the return value of xQueueReceive to see if a character was actually read from the queue.

Regards.

guillep2k wrote on Monday, January 23, 2006:

Thank you, Richard.