freeRTOS 队列3 上锁解锁

本文介绍RTOS中队列加锁与解锁的具体实现方法。详细解释了如何通过修改队列的锁状态来防止中断服务例程访问队列,并在解锁时检查等待任务列表,将已等待的任务标记为就绪。
/*
 * Macro to mark a queue as locked.  Locking a queue prevents an ISR from
 * accessing the queue event lists.
 */
#define prvLockQueue( pxQueue )                                \
    taskENTER_CRITICAL();                                    \
    {                                                        \
        if( ( pxQueue )->cRxLock == queueUNLOCKED )            \
        {                                                    \
            ( pxQueue )->cRxLock = queueLOCKED_UNMODIFIED;    \
        }                                                    \
        if( ( pxQueue )->cTxLock == queueUNLOCKED )            \
        {                                                    \
            ( pxQueue )->cTxLock = queueLOCKED_UNMODIFIED;    \
        }                                                    \
    }                                                        \
    taskEXIT_CRITICAL()
/*-----------------------------------------------------------*/
/* Constants used with the cRxLock and cTxLock structure members. */
#define queueUNLOCKED                     ( ( int8_t ) -1 )
#define queueLOCKED_UNMODIFIED            ( ( int8_t ) 0 )
  1 static void prvUnlockQueue( Queue_t * const pxQueue )
  2 {
  3     /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
  4 
  5     /* The lock counts contains the number of extra data items placed or
  6     removed from the queue while the queue was locked.  When a queue is
  7     locked items can be added or removed, but the event lists cannot be
  8     updated. 上锁计数器在队列上锁之后进行计数统计,但事件队列中两个列表(WaitToSend/Rcv)的那些任务的事件列表项不会更新变动*/
  9     taskENTER_CRITICAL();
 10     {
 11         int8_t cTxLock = pxQueue->cTxLock;
 12 
 13         /* See if data was added to the queue while it was locked. 【】*/
 14         while( cTxLock > queueLOCKED_UNMODIFIED )
 15         {
 16             /* Data was posted while the queue was locked.  Are any tasks
 17             blocked waiting for data to become available? */
 18             #if ( configUSE_QUEUE_SETS == 1 )
 19             { 57             }
 58             #else /* configUSE_QUEUE_SETS */
 59             {
 60                 /* Tasks that are removed from the event list will get added to
 61                 the pending ready list as the scheduler is still suspended. */
 62                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
 63                 {
 64                     if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )  
//将任务从列表xTaskWaitToRcv中移除
65 { 66 /* The task waiting has a higher priority so record that 67 a context switch is required. */ 68 vTaskMissedYield(); //就一句 xYieldPending = pdTRUE; 69 } 70 else 71 { 72 mtCOVERAGE_TEST_MARKER(); 73 } 74 } 75 else 76 { 77 break; 78 } 79 } 80 #endif /* configUSE_QUEUE_SETS */ 81 82 --cTxLock; 83 } 84 85 pxQueue->cTxLock = queueUNLOCKED; 86 } 87 taskEXIT_CRITICAL(); 88 89 /* Do the same for the Rx lock. */ 90 taskENTER_CRITICAL(); 91 { 92 int8_t cRxLock = pxQueue->cRxLock; 93 94 while( cRxLock > queueLOCKED_UNMODIFIED ) 95 { 96 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) 97 { 98 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) 99 { 100 vTaskMissedYield(); 101 } 102 else 103 { 104 mtCOVERAGE_TEST_MARKER(); 105 } 106 107 --cRxLock; 108 } 109 else 110 { 111 break; 112 } 113 } 114 115 pxQueue->cRxLock = queueUNLOCKED; 116 } 117 taskEXIT_CRITICAL(); 118 } 119 /*-----------------------------------------------------------*/

解锁过程:

先处理 TxLock,

while(根据TxLock的值,看看队列上锁期间是否有“入队操作”,如果有)

{

  则观察事件等待列表,有任务在等待则,

       将这个任务从事件等待列表WaitToRcv中踢掉,加入就绪列表 或 Pending就绪列表(函数TaskRemoveFromEventList的操作)

       置位PendSV准备切换任务,之后TxLock值减一。

}

修改 TxLock 为 queueUNLOCKED。

RxLock类似。

留白

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值