More efficient ISR queue handling

nobody wrote on Monday, February 28, 2005:

Hi,

I’m running RTOS on a PIC18F8525.
I got serious problems when reading serial data from a magnet-cardreader at 38400 baud through a queue.
There was too much overhead from the taskswitching, and thus I lost data.

The problem was that the serialISR called taskYIELD if the queue contents changed for example from 5 to 6 items.

I modified my serialISR code to test if the queue was emtpy before sending the serial data to the queue, and then at the end of the serialISR only perform a taskYIELD if the queue had been empty and the cQueueSendFromISR sent a taskwoken signal.
this solved my problem by preventing unneccesary calls to taskYIELD.

The idea is that the queue cannot block a task if the queue is not empty, so adding another item to the queue cannot unblock any task since no task is blocked.

I now solved the problem by adding an additional test to the cQueueSendFromISR in queue.c as follows:

if( pxQueue->ucMessagesWaiting < pxQueue->ucLength )
{
    prvCopyQueueData( pxQueue, pvItemToQueue );
        // If the queue contains more than 1 item, the receiving task cannot be sleeping/waiting for input,
        // because there already WAS data on the queue.
        // If the queue just received its first item, this could wake a task.
    if( pxQueue->ucMessagesWaiting == 1 )
    {        // Just sent first item to the queue, thus it is possible a task has been woken
            /* If the queue is locked we do not alter the event list.  This will
            be done when the queue is unlocked later. */
        if( pxQueue->cTxLock == queueUNLOCKED )
        {

This will only allow the cQueueuSendFromISR to return a taskwoken=TRUE if the contents of the queue just changed from empty to 1 item.

The same thing goes for cQueueReceiveFromISR, which should only be allowed to unblock a task if the contents change from full to full minus 1

Greetings

Paul van der Hulst

rtel wrote on Tuesday, March 01, 2005:

Hi,

<snip>
> The idea is that the queue cannot block a task if the queue is not empty, so
> adding another item to the queue cannot unblock any task since no task
> is blocked.

Good idea.

I might like to incorporate this into the main code, but will have to think it over for a while.  There may be some permutation where problems could exist - for example, more than one task waiting on the same queue (which is possible but not necessarily desirable).  The queues have to be a generic mechanism.

How the serial port drivers operate is an application level design decision - for example the relative priorities of the tasks effect when a switch will occur, how characters should be buffered, etc.  Please note that, as stated in the PIC18 docs on the WEB site "The supplied serial port drivers are written to test some of the real time kernel features - and they are not intended to represent an optimised solution."

Thanks for you valuable feedback.

Regards.

nobody wrote on Wednesday, March 09, 2005:

The ISR queue functions already only return taskwoken=true if there was a task waiting on the event list of the queue being posted to / received from.  What is the difference with checking if the queue was empty/full?