关于FreeRTOS的信号量、队列

FreeRTOS的队列是基础,其它的,比如信号量等都是基于队列实现的。

1 #define queueQUEUE_TYPE_BASE                ( 0U )
2 #define queueQUEUE_TYPE_MUTEX                 ( 1U )
3 #define queueQUEUE_TYPE_COUNTING_SEMAPHORE    ( 2U )
4 #define queueQUEUE_TYPE_BINARY_SEMAPHORE    ( 3U )
5 #define queueQUEUE_TYPE_RECURSIVE_MUTEX        ( 4U )

信号量包括二值信号量、计数信号量、递归信号量、互斥信号量。

对于二值信号量,对存在优先级反转的问题。

比如任务3、2、1的优先级从高到低,任务3和1通过二值信号量控制访问某个资源,若任务1先锁定该资源,则任务3访问该资源时,会因为得不到资源而阻塞。此时,若任务2运行条件具备,任务2会打断任务1而执行,从而呈现低优先级的任务2优先于高优先级的任务3运行的情景,即优先级反转了。

由于二值信号量的这个问题,于是有了互斥信号量,互斥信号量与二值信号量的区别在于,互斥信号量具有优先级继承的特性。即在任务3获取互斥信号量的时候,若无法获取互斥信号量,则会判断一下当前获取互斥信号量的任务优先级是否比自己低,若是,则将该任务的优先级提高到和自己一样。

queue定义如下,头pcHead和尾pcTail均为指向字节量,pcWriteTo指向第一个成员地址,pcReadFrom指向最后一个成员地址,xTasksWaitingToSend等待向队列发送数据的任务列表,该任务同时也会在挂起(等待时间为无限)或延时列表(等待时间为有限)中。uxMessagesWaiting队列成员个数,虽然名字有个waiting。

 1 typedef struct QueueDefinition
 2 {
 3     signed char *pcHead;                /*< Points to the beginning of the queue storage area. */
 4     signed char *pcTail;                /*< Points to the byte at the end of the queue storage area.  Once more byte is allocated than necessary to store the queue items, this is used as a marker. */
 5 
 6     signed char *pcWriteTo;                /*< Points to the free next place in the storage area. */
 7     signed char *pcReadFrom;            /*< Points to the last place that a queued item was read from. */
 8 
 9     xList xTasksWaitingToSend;                /*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */
10     xList xTasksWaitingToReceive;            /*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */
11 
12     volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */
13     unsigned portBASE_TYPE uxLength;        /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
14     unsigned portBASE_TYPE uxItemSize;        /*< The size of each items that the queue will hold. */
15 
16     volatile signed portBASE_TYPE xRxLock;    /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */
17     volatile signed portBASE_TYPE xTxLock;    /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */
18 
19     #if ( configUSE_TRACE_FACILITY == 1 )
20         unsigned char ucQueueNumber;
21         unsigned char ucQueueType;
22     #endif
23 
24 } xQUEUE;

任务控制块中有两个列表成员,其中事件列表就是用于队列阻塞时用的。

xGenericListItem是用于将任务串成列表的列表成员,后续该任务加入就绪任务列表还是其他任务列表,都是将该列表成员插入进任务列表。

xEventListItem用于记录该任务是否在等待事件,比如是否向队列发送数据但队列已满、是否从队列读取数据但队列是空的,且设置了等待时间或无限等待。例如,若是向队列发送数据但队列已满,则该任务的xEventListItem会插入该队列的xTasksWaitingToSend列表中;同时将xGenericListItem从就绪任务列表删除,插入到挂起任务队列(若等待时间是无限)或延时任务队列(若等待时间是有限)(该过程由vTaskPlaceOnEventList完成)。若是队列非满了,则会将任务的xEventListItem从xTasksWaitingToSend中移除;同时,将任务的xGenericListItem从挂起任务队列或延时任务队列中移除,并添加到就绪队列中(该过程由xTaskRemoveFromEventList完成)。

大幅度发

猜你喜欢

转载自www.cnblogs.com/yanhc/p/12675967.html