今天继续来介绍FreeRTOS中的列表和列表项。主要是介绍列表和列表项的API。
新创建或者定义的列表需要对其做初始化处理,列表的初始化其实就是初始化列表结构体
List_t中的各个成员变量,列表的初始化通过使函数vListInitialise()来完成,此函数在list.c中有定义,函数如下:
void vListInitialise( List_t * const pxList )
{
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); (1)
pxList->xListEnd.xItemValue = portMAX_DELAY; (2)
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); (3)
pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd ); (4)
pxList->uxNumberOfItems = ( UBaseType_t ) 0U; (5)
listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ); (6)
listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ); (7)
}
和列表一样,列表项在使用的时候也需要初始化,列表项初始化由函数vListInitialiseItem()完成。函数如下:
void vListInitialiseItem( ListItem_t * const pxItem )
{
/* Make sure the list item is not recorded as being on a list. */
//初始化pvContainer 为NULL
pxItem->pvContainer = NULL;
/* Write known values into the list item if
configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
//初始化用于完整性检查的变量
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
}
列表项的插入操作通过函数vListInsert()来完成,函数原型为:
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
{
ListItem_t *pxIterator;
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue; (1)
listTEST_LIST_INTEGRITY( pxList ); (2)
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
if( xValueOfInsertion == portMAX_DELAY ) (3)
{
pxIterator = pxList->xListEnd.pxPrevious; (4)
}
else
{
for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); (5)
pxIterator->pxNext->xItemValue <= xValueOfInsertion;
pxIterator = pxIterator->pxNext )
{
//空循环
/* There is nothing to do here, just iterating to the wanted
insertion position. */
}
}
pxNewListItem->pxNext = pxIterator->pxNext; (6)
pxNewListItem->pxNext->pxPrevious = pxNewListItem;
pxNewListItem->pxPrevious = pxIterator;
pxIterator->pxNext = pxNewListItem;
pxNewListItem->pvContainer = ( void * ) pxList; (7)
( pxList->uxNumberOfItems )++; (8)
}
其中形参中的pxList为列表项要插入的列表,pxNewListItem 为要插入的列表项
列表项末尾插入列表项的操作通过函数vListInsertEnd()完成。函数原型如下:
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{
ListItem_t * const pxIndex = pxList->pxIndex;
listTEST_LIST_INTEGRITY( pxList ); (1)
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
pxNewListItem->pxNext = pxIndex; (2)
pxNewListItem->pxPrevious = pxIndex->pxPrevious;
mtCOVERAGE_TEST_DELAY();
pxIndex->pxPrevious->pxNext = pxNewListItem;
pxIndex->pxPrevious = pxNewListItem;
pxNewListItem->pvContainer = ( void * ) pxList; (3)
( pxList->uxNumberOfItems )++; (4)
}
其中形参中的pxList为列表项要插入的列表,pxNewListItem 为要插入的列表项。
有列表项的插入,自然就有列表项的删除,列表项的删除是通过函数uxListRemove()完成的。函数原型如下:
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer; (1)
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; (2)
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
mtCOVERAGE_TEST_DELAY();
if( pxList->pxIndex == pxItemToRemove )
{
pxList->pxIndex = pxItemToRemove->pxPrevious; (3)
}
else
{
mtCOVERAGE_TEST_MARKER();
}
pxItemToRemove->pvContainer = NULL; (4)
( pxList->uxNumberOfItems )--;
return pxList->uxNumberOfItems; (5)
}
其中函数的形参pxItemToRemove 为要删除的列表项,返回值为删除列表项以后列表剩余的列表项数目。
介绍列表结构体的时候说过列表List_t中的成员变量pxIndex是用来遍历列表的,FreeRTOS
提供了一个函数来完成列表的遍历,这个函数是listGET_OWNER_OF_NEXT_ENTRY()。每调用一次这个函数列表的pxIndex变量就会指向下一个列表项,并且返回这个列表项的pxOwner变量值。这个函数本质上是一个宏,这个宏在文件list.h中如下定义:
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ (1)
{ \
List_t * const pxConstList = ( pxList ); \
/* Increment the index to the next item and return the item, ensuring */ \
/* we don't return the marker used at the end of the list. */ \
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ (2)
if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \ (3)
{ \
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ (4)
} \
( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \ (5)
}