新闻  |   论坛  |   博客  |   在线研讨会
FreeRTOS队列管理--中断中的使用
mayer | 2009-06-21 12:54:58    阅读:9651   发布文章

FreeRTOS队列管理--中断中的使用

 

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

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

#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;
}

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

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客
站长统计