一、列表和列表项简介
列表是 FreeRTOS 中的一个数据结构,列表被用来跟踪 FreeRTOS中的任务(任务当前的状态),列表项就是存放在列表中的项目
列表相当于链表,列表项相当于节点,FreeRTOS 中的列表是一个双向循环链表
列表项间的地址非连续的,列表项的数目随时可以改变
列表项的指向前一个、后一个指针 ,就相当于人的左右手 ,整个列表就相当于N个人互相拉着手,围**成一个圈,**而列表是管理这个圈
二、 列表与列表项
2.1 列表结构体
typedef struct xLIST
{
listFIRST_LIST_INTEGRITY_CHECK_VALUE /* 校验值 */
volatile UBaseType_t uxNumberOfItems; /* 列表中的列表项数量 */
ListItem_t * configLIST_VOLATILE pxIndex /* 用于遍历列表项的指针 */
MiniListItem_t xListEnd /* 末尾列表项 */
listSECOND_LIST_INTEGRITY_CHECK_VALUE /* 校验值 */
} List_t;
成员说明:
|----------------------------------------------------------------------------|----------------------------------------------------------------------------|
| 成员 | 描述 |
| listFIRST_LIST_INTEGRITY_CHECK_VALUE listSECOND_LIST_INTEGRITY_CHECK_VALUE | 具有确定已知常量的宏 FreeRTOS通过检查这两个常量的值,来判断列表的数据在程序运行过程中,是否遭到破坏 ,该功能一般用于调试, 默认是不开启的 |
| uxNumberOfItems | 用于记录列表中列表项的个数(不包含 xListEnd) |
| pxIndex | 用于指向列表中的某个列表项,一般用于遍历列表中的所有列表项 |
| xListEnd | 一个迷你列表项,排在最末尾 |
列表结构示意图:
2.2 列表项结构体
struct xLIST_ITEM
{
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /* 用于检测列表项的数据完整性 */
configLIST_VOLATILE TickType_t xItemValue /* 列表项的值 */
struct xLIST_ITEM * configLIST_VOLATILE pxNext /* 下一个列表项 */
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious /* 上一个列表项 */
void * pvOwner /* 列表项的拥有者 */
struct xLIST * configLIST_VOLATILE pxContainer; /* 列表项所在列表 */
listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /* 用于检测列表项的数据完整性*/
};
typedef struct xLIST_ITEM ListItem_t;
成员说明:
|-------------------------------------------------------------------------------------|----------------------------|
| 成员 | 描述 |
| listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALU | 用于检测列表项的数据完整性 |
| xItemValue | 列表项的值,多用于将列表中的列表项按升序排序 |
| pxNext | 指向列表中列表项的下一个列表项 |
| pxPrevious | 指向列表中列表项的上一个列表项 |
| pvOwner | 用于指向包含列表项的对象(通常是任务控制块) |
| pxContainer | 用于指向列表项所在列表 |
列表项结构示意图:
2.3 迷你列表项(末尾列表项)
迷你列表项也是列表项,但迷你列表项仅用于标记列表的末尾和挂载其他插入列表中的列表项(将要插入的列表项连接在一起)
struct xMINI_LIST_ITEM
{
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /* 用于检测数据完整性 */
configLIST_VOLATILE TickType_t xItemValue; /* 列表项的值 */
struct xLIST_ITEM * configLIST_VOLATILE pxNext; /* 上一个列表项 */
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /* 下一个列表项 */
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;
成员说明:
|-------------------------------------------|--------------------------|
| 成员 | 描述 |
| listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE | 用于检测数据完整性 |
| xItemValue | 列表项的值,多用于按升序对列表中的列表项进行排序 |
| pxNext pxPrevious | 用于指向列表中列表项的下一个列表项和上一个列表项 |
与正常列表项,缺少列表项拥有者、列表项所在列表成员 ,以节省内存开销
迷你列表项结构示意图:
三、列表相关API函数
|-----------------------|---------------|
| 函数 | 描述 |
| vListInitialise() | 初始化列表 |
| vListInitialiseItem() | 初始化列表项 |
| vListInsertEnd() | 列表末尾插入列表项 |
| vListInsert() | 列表插入列表项(升序插入) |
| uxListRemove() | 列表移除列表项 |
3.1 初始化列表:vListInitialise( )
void vListInitialise( List_t * const pxList )
{
/* 初始化时,列表中只有 xListEnd,因此 pxIndex 指向 xListEnd */
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) );
/* xListEnd 的值初始化为最大值,用于列表项升序排序时,排在最后 */
pxList->xListEnd.xItemValue = portMAX_DELAY;
/* 初始化时,列表中只有 xListEnd,因此上一个和下一个列表项都为 xListEnd 本身 */
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );
pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );
/* 初始化时,列表中的列表项数量为 0(不包含 xListEnd) */
pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
/* 检查数据的完整性 */
listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}
参数说明:
|--------|---------|
| 参数 | 说明 |
| pxList | 待初始化的列表 |
列表初始化后的结构示意图:
3.2 列表项初始化:vListInitialiseItem()
void vListInitialiseItem( ListItem_t * const pxItem )
{
/* 初始化时,列表项所在列表设为空 */
pxItem->pxContainer = NULL;
/* 初始化用于检测列表项数据完整性的校验值 */
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
}
其他成员变量根据实际使用情况进行初始化
参数说明:
|--------|----------|
| 参数 | 说明 |
| pxItem | 待初始化的列表项 |
列表初始化后的结构示意图:
3.3 列表插入列表项(升序插入):vListInsert()
函数功能:将待插入列表的列表项按照列表项值升序插入,有序地插入到列表中
void vListInsert( List_t * const pxList,
ListItem_t * const pxNewListItem )
{
/*获取列表项的数值依据数值升序排列 */
ListItem_t * pxIterator;
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
/* 检查参数是否正确 */
listTEST_LIST_INTEGRITY( pxList );
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
/* 如果待插入列表项的值为最大值,插入的位置为列表 xListEnd 前面 */
if( xValueOfInsertion == portMAX_DELAY )
{
pxIterator = pxList->xListEnd.pxPrevious;
}
else
{
/*遍历列表中的列表项,找到插入的位置*/
for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext )
}
}
/* 将待插入的列表项插入指定位置 */
pxNewListItem->pxNext = pxIterator->pxNext;
pxNewListItem->pxNext->pxPrevious = pxNewListItem;
pxNewListItem->pxPrevious = pxIterator;
pxIterator->pxNext = pxNewListItem;
/*更新待插入列表项所在列表 */
pxNewListItem->pxContainer = pxList;
/* 更新列表中列表项的数量 */
( pxList->uxNumberOfItems )++;
}
参数说明:
|---------------|--------|
| 参数 | 说明 |
| pxList | 列表 |
| pxNewListItem | 待插入列表项 |
3.4 列表末尾插入: vListInsertEnd()
函数功能:将待插入列表的列表项插入到列表 pxIndex 指针指向的列表项前面(初始化时:pxIndex指向迷你列表项),是一种无序的插入方法
void vListInsertEnd ( List_t * const pxList , ListItem_t * const pxNewListItem )
{
/* 获取列表 pxIndex 指向的列表项 */
ListItem_t * const pxIndex = pxList->pxIndex;
/* 更新待插入列表项的指针成员变量 */
pxNewListItem->pxNext = pxIndex;
pxNewListItem->pxPrevious = pxIndex->pxPrevious;
/* 更新列表中原本列表项的指针成员变量 */
pxIndex->pxPrevious->pxNext = pxNewListItem;
pxIndex->pxPrevious = pxNewListItem;
/* 更新待插入列表项的所在列表成员变量 */
pxNewListItem->pxContainer = pxList;
/* 更新列表中列表项的数量 */
( pxList->uxNumberOfItems )++;
}
参数说明:
|---------------|--------|
| 参数 | 说明 |
| pxList | 列表 |
| pxNewListItem | 待插入列表项 |
2.5 移出列表项:uxListRemove()
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
List_t * const pxList = pxItemToRemove->pxContainer;
/* 从列表中移除列表项 */
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
/*如果 pxIndex 正指向待移除的列表项 */
if( pxList->pxIndex == pxItemToRemove )
{
/*pxIndex 指向上一个列表项*/
pxList->pxIndex = pxItemToRemove->pxPrevious;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/*将待移除的列表项的所在列表指针清空*/
pxItemToRemove->pxContainer = NULL;
/*更新列表中列表项的数量*/
( pxList->uxNumberOfItems )--;
return pxList->uxNumberOfItems;
}
参数说明:
|----------------|----------------|
| 参数 | 说明 |
| pxItemToRemove | 待移出的列表项 |
| 返回值 | 移除后,列表剩余的列表项数量 |