与标准的队列函数相比,中断中的队列收发相对要简洁,运行需要的时间相对来说要短。在中断服务程序中接收与发送队列,不需要进行临界段的处理,同时这些函数会直接返回而不会等待。在中断中收发队列不会导致任务的切换,但是会返回一个标志来提醒用户进行任务切换。



与标准的队列函数相似,中断中的队列操作也是由两个底层的函数实现,具体的操作则由宏来定义:



#define
xQueueSendToFrontFromISR( pxQueue, pvItemToQueue,
pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( pxQueue,
pvItemToQueue, pxHigherPriorityTaskWoken, queueSEND_TO_FRONT )



#define xQueueSendToBackFromISR( pxQueue, pvItemToQueue,
pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( pxQueue,
pvItemToQueue, pxHigherPriorityTaskWoken, queueSEND_TO_BACK )



#define xQueueSendFromISR( pxQueue, pvItemToQueue,
pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( pxQueue,
pvItemToQueue, pxHigherPriorityTaskWoken, queueSEND_TO_BACK )


 


xQueueGenericSendFromISR为所有中断中队列发送的实现函数



signed portBASE_TYPE
xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const
pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken,
portBASE_TYPE xCopyPosition )

{

signed portBASE_TYPE xReturn;

unsigned portBASE_TYPE uxSavedInterruptStatus;



    /* Similar to xQueueGenericSend, except we don't block if there is no room

    in the queue.  Also we don't directly wake a task that was blocked on a

    queue read, instead we return a flag to say whether a context switch is

    required or not (i.e. has a task with a higher priority than us been woken

    by this    post). */



    uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();

    {

        if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )    /*有空闲的空间,则复制数据到队列*/

        {

            traceQUEUE_SEND_FROM_ISR( pxQueue );

            prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );



            /* If the queue is locked we do not alter the event list.  This will

            be done when the queue is unlocked later. */



            if( pxQueue->xTxLock == queueUNLOCKED )    /*没有上锁,则把任务从等待队列中移除*/

            {

                if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )

                {

                    if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )    /*说明移除的任务有更高的优先级*/

                    {

                        /* The task waiting has a higher priority so record that a

                        context    switch is required. */



                        *pxHigherPriorityTaskWoken = pdTRUE;    /*返回任务切换标志,使得中断服务程序需要进行任务切换*/

                    }

                }

            }

            else

            {



                /* Increment the lock count so the task that unlocks the queue

                knows that data was posted while it was locked. */


                /*因为队列被上锁了,不能进行任务移除操作,增加xTxLock的值

                   当进行与上锁操作所对应的解锁时,会根据此值多次的移除任务*/




                ++( pxQueue->xTxLock );

            }

            xReturn = pdPASS;

        }

        else    /*队列满,不等待直接返回*/

        {

            traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );

            xReturn = errQUEUE_FULL;

        }

    }

    portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );

    return xReturn;

}



/*-----------------------------------------------------------*/




中断中队列接收的实现与上面发送的实现相对应,由函数xQueueReceiveFromISR来完成



signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken )



{

signed portBASE_TYPE xReturn;

unsigned portBASE_TYPE uxSavedInterruptStatus;



    uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();

    {

        /* We cannot block from an ISR, so check there is data available. */

        if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )    /*队列非空,则把数据复制出来*/

        {

            traceQUEUE_RECEIVE_FROM_ISR( pxQueue );

            prvCopyDataFromQueue( pxQueue, pvBuffer );

            --( pxQueue->uxMessagesWaiting );



            /* If the queue is locked we will not modify the event list.  Instead

            we update the lock count so the task that unlocks the queue will know

            that an ISR has removed data while the queue was locked. */



            if( pxQueue->xRxLock == queueUNLOCKED )

            {

                if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )

                {

                    if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )   
/*说明移除的任务有更高的优先级*/

                    {



                        /* The task waiting has a higher priority than us so

                        force a context switch. */



                        *pxTaskWoken = pdTRUE;

                    }

                }

            }

            else

            {



                /* Increment the lock count so the task that unlocks the queue

                knows that data was removed while it was locked. */



                /*因为队列被上锁了,不能进行任务移除操作,增加xRxLock的值

                   当进行与上锁操作所对应的解锁时,会根据此值多次的移除任务*/




                ++( pxQueue->xRxLock );

            }

            xReturn = pdPASS;

        }

        else    /*队列为空,不等待直接返回*/

        {

            xReturn = pdFAIL;

            traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );

        }

    }

    portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );

    return xReturn;

}



/*-----------------------------------------------------------*/


相关网址:http://www.openrtos.cn/article/12.php