FreeRTOS节点带参宏函数
这些宏共同构成了 FreeRTOS 中高效、简洁的链表操作接口。它们被广泛用于任务调度、延时管理、事件处理等核心模块中。通过内联宏的方式,既保证了代码的紧凑性,又避免了函数调用的开销,符合嵌入式实时系统对性能和资源的要求。
·
下面将对给出的所有宏定义进行详细解释。这些宏是 FreeRTOS 内核中用于操作双向链表的常用工具,通常定义在 list.h 文件中。它们用于管理任务控制块(TCB)的列表,如就绪列表、阻塞列表等。
1. listSET_LIST_ITEM_OWNER( pxListItem, pxOwner )
#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) \
((pxListItem)->pvOwner = (void*)(pxOwner))
- 作用:设置列表项的“拥有者”。在 FreeRTOS 中,每个列表项通常属于一个任务,拥有者就是指向任务 TCB 的指针。
- 参数:
pxListItem:指向ListItem_t结构体的指针。pxOwner:要设置的拥有者指针,通常是TCB_t*。
- 展开:将
pxOwner强制转换为void*并赋值给列表项的pvOwner成员。 - 用途:用于将列表项与具体的任务关联起来,当从列表中取出项时,可以通过
pvOwner获得对应的任务控制块。
2. listGET_LIST_ITEM_OWNER( pxListItem )
#define listGET_LIST_ITEM_OWNER( pxListItem ) \
( ( pxListItem )->pvOwner )
- 作用:获取列表项所拥有的对象(通常是 TCB)。
- 参数:
pxListItem指向列表项的指针。 - 展开:直接返回
pvOwner成员的值。 - 用途:在遍历列表时,通过此项获得对应的任务 TCB。
3. listSET_LIST_ITEM_VALUE( pxListItem, xValue )
#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) \
( ( pxListItem )->xItemValue = ( xValue ) )
- 作用:设置列表项的排序辅助值(通常用于优先级或超时时间)。
- 参数:
pxListItem:指向列表项的指针。xValue:要设置的TickType_t类型的值。
- 用途:列表项在链表中按
xItemValue升序排列,这个值决定了节点在列表中的位置。例如,在就绪列表中,值可以是任务优先级;在阻塞列表中,值可以是任务的唤醒时间。
4. listGET_LIST_ITEM_VALUE( pxListItem )
#define listGET_LIST_ITEM_VALUE( pxListItem ) \
( ( pxListItem )->xItemValue )
- 作用:获取列表项的排序辅助值。
- 参数:
pxListItem指向列表项的指针。 - 展开:返回
xItemValue。 - 用途:读取某个列表项的排序值,比如获取任务的优先级或阻塞超时时间。
5. listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList )
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) \
( ( ( pxList )->xListEnd ).pxNext->xItemValue )
- 作用:获取链表头部(第一个实际节点)的排序辅助值。
- 参数:
pxList指向链表根节点List_t的指针。 - 展开:
(pxList)->xListEnd:获取链表的哨兵节点(xListEnd)。.pxNext:哨兵节点的pxNext指向链表的第一个实际节点。->xItemValue:获取该节点的排序值。
- 用途:常用于获取就绪列表中的最高优先级任务的优先级值(因为就绪列表按优先级升序排列,头部是优先级最高的任务)。
6. listGET_HEAD_ENTRY( pxList )
#define listGET_HEAD_ENTRY( pxList ) \
( ( ( pxList )->xListEnd ).pxNext )
- 作用:获取链表的第一个实际节点(头节点)。
- 参数:
pxList指向链表根节点的指针。 - 展开:返回
(pxList)->xListEnd.pxNext,即哨兵节点指向的第一个实际节点。 - 用途:在需要遍历列表时获取起始节点。
7. listGET_NEXT( pxListItem )
#define listGET_NEXT( pxListItem ) \
( ( pxListItem )->pxNext )
- 作用:获取给定节点的下一个节点。
- 参数:
pxListItem指向当前列表项的指针。 - 展开:返回
pxNext成员。 - 用途:用于遍历链表时移动到下一节点。
8. listGET_END_MARKER( pxList )
#define listGET_END_MARKER( pxList ) \
( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )
- 作用:获取链表的哨兵节点(结束标记节点)。
- 参数:
pxList指向链表根节点的指针。 - 用途:通常用于判断是否遍历到链表末尾(
pxCurrent == listGET_END_MARKER(pxList))。哨兵节点不包含实际数据,仅用于标识链表的结尾。
9. listLIST_IS_EMPTY( pxList )
#define listLIST_IS_EMPTY( pxList ) \
( ( BaseType_t ) ( ( pxList )->uxNumberOfItems == ( BaseType_t ) 0 ) )
- 作用:判断链表是否为空。
- 参数:
pxList指向链表根节点的指针。 - 展开:比较
uxNumberOfItems(节点计数器)是否等于 0,结果强制转换为BaseType_t(通常为int)。 - 用途:快速判断某个就绪列表或阻塞列表是否为空。
10. listCURRENT_LIST_LENGTH( pxList )
#define listCURRENT_LIST_LENGTH( pxList ) \
( ( pxList )->uxNumberOfItems )
- 作用:获取链表当前的节点数量。
- 参数:
pxList指向链表根节点的指针。 - 展开:返回
uxNumberOfItems成员。 - 用途:获取某个列表中的任务数量,例如就绪列表中优先级为 x 的任务个数。
11. listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \
{ \
List_t * const pxConstList = ( pxList ); \
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \
{ \
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
} \
( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \
}
- 作用:获取下一个列表项所拥有的对象(即 TCB),并自动推进列表索引,实现循环遍历(round-robin)。
- 参数:
pxTCB:输出参数,用于接收 TCB 指针。pxList:指向链表根节点的指针。
- 详细分解:
List_t * const pxConstList = ( pxList );
将传入的链表指针保存到一个局部常量指针中,防止宏展开时多次解引用带来的副作用。( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;
将列表的当前索引指针向前移动一个节点。pxIndex是一个遍历指针,初始时通常指向哨兵节点xListEnd,第一次调用后会指向第一个实际节点。if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) )
判断移动后的pxIndex是否指向了哨兵节点(xListEnd)。如果是,说明已经遍历到链表末尾(即绕了一圈)。( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;
在哨兵节点的情况下,再次将pxIndex向前移动一个节点。因为哨兵节点的pxNext指向链表的第一个实际节点,所以这一步使得pxIndex重新指向第一个实际节点,实现了循环回绕。( pxTCB ) = ( pxConstList )->pxIndex->pvOwner;
从当前pxIndex指向的列表项中取出pvOwner(即 TCB 指针),赋值给pxTCB。
- 用途:这是 FreeRTOS 中实现 轮询调度(Round-Robin) 的核心宏。当多个相同优先级的任务处于就绪状态时,调度器会依次选择它们来运行。每次调用此宏,都会从列表中取出下一个任务的 TCB,并自动循环。宏中的
if语句正是为了在到达列表末尾时跳回开头,实现循环遍历。
总结
这些宏共同构成了 FreeRTOS 中高效、简洁的链表操作接口。它们被广泛用于任务调度、延时管理、事件处理等核心模块中。通过内联宏的方式,既保证了代码的紧凑性,又避免了函数调用的开销,符合嵌入式实时系统对性能和资源的要求。
更多推荐



所有评论(0)