列表是 FreeRTOS 系统各种功能实现的的基础,本质上是一个双向循环链表。
类型定义
列表类型:
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;列表项类型:
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; // 拥有该节点的TCB
struct xLIST *configLIST_VOLATILE pxContainer; // 属于哪个列表
listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
};
typedef struct xLIST_ITEM ListItem_t;完整性检查
开头和结束的宏定义是为了做完整性检查,
#define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1;
#define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2;展开后是:
typedef struct xLIST
{
TickType_t xListIntegrityValue1;
volatile UBaseType_t uxNumberOfItems;
ListItem_t *configLIST_VOLATILE pxIndex;
MiniListItem_t xListEnd;
TickType_t xListIntegrityValue2;
} List_t;就是给结构体前后设置一个固定值,如果读到的不是这个值,说明结构体被破坏了。
#define listSET_LIST_INTEGRITY_CHECK_1_VALUE(pxList) (pxList)->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
#define listSET_LIST_INTEGRITY_CHECK_2_VALUE(pxList) (pxList)->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE宏函数
// 设置列表项所属的对象,通常为任务
#define listSET_LIST_ITEM_OWNER(pxListItem, pxOwner) ((pxListItem)->pvOwner = (void *)(pxOwner))
// 获取列表项所属的对象,通常为任务
#define listGET_LIST_ITEM_OWNER(pxListItem) ((pxListItem)->pvOwner)
// 设置列表项的值
#define listSET_LIST_ITEM_VALUE(pxListItem, xValue) ((pxListItem)->xItemValue = (xValue))
// 获取列表项的值
#define listGET_LIST_ITEM_VALUE(pxListItem) ((pxListItem)->xItemValue)
/*
* Access macro to retrieve the value of the list item at the head of a given
* list.
*
* \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
* \ingroup LinkedList
*/
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY(pxList) (((pxList)->xListEnd).pxNext->xItemValue)
/*
* Return the list item at the head of the list.
*
* \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY
* \ingroup LinkedList
*/
#define listGET_HEAD_ENTRY(pxList) (((pxList)->xListEnd).pxNext)
// 获取下一个列表项
#define listGET_NEXT(pxListItem) ((pxListItem)->pxNext)
// 获取列表的终止节点
#define listGET_END_MARKER(pxList) ((ListItem_t const *)(&((pxList)->xListEnd)))
// 判断列表是否为空
#define listLIST_IS_EMPTY(pxList) (((pxList)->uxNumberOfItems == (UBaseType_t)0) ? pdTRUE : pdFALSE)
// 获取列表的列表项数量
#define listCURRENT_LIST_LENGTH(pxList) ((pxList)->uxNumberOfItems)初始化列表
最后一项是伪节点(哨兵节点),是为了让链表实现循环,与具体业务无关。
void vListInitialise(List_t *const pxList)
{
// 最后项就是当前项
pxList->pxIndex = (ListItem_t *)&(pxList->xListEnd);
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE(&(pxList->xListEnd));
//列表项的 xItemValue 用于排序,因此最后一项的值要最大
pxList->xListEnd.xItemValue = portMAX_DELAY;
// 最后一项的特性:上一个和下一个都指向自己
pxList->xListEnd.pxNext = (ListItem_t *)&(pxList->xListEnd);
pxList->xListEnd.pxPrevious = (ListItem_t *)&(pxList->xListEnd);
// 如果不使用精简版链表还得初始化下面的
#if (configUSE_MINI_LIST_ITEM == 0)
{
pxList->xListEnd.pvOwner = NULL;
pxList->xListEnd.pxContainer = NULL;
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE(&(pxList->xListEnd));
}
#endif
// 总数为0
pxList->uxNumberOfItems = (UBaseType_t)0U;
// 完整性检查
listSET_LIST_INTEGRITY_CHECK_1_VALUE(pxList);
listSET_LIST_INTEGRITY_CHECK_2_VALUE(pxList);
}插入到列表中
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);
if (xValueOfInsertion == portMAX_DELAY) // 值最大,插入到末尾
{
pxIterator = pxList->xListEnd.pxPrevious; // 伪节点的前一项才是真正的节点
}
else // 根据值找到位置
{
for (pxIterator = (ListItem_t *)&(pxList->xListEnd);
pxIterator->pxNext->xItemValue <= xValueOfInsertion; // 终止节点的next为第一个节点
pxIterator = pxIterator->pxNext)
{
}
}
pxNewListItem->pxNext = pxIterator->pxNext;
pxNewListItem->pxNext->pxPrevious = pxNewListItem;
pxNewListItem->pxPrevious = pxIterator;
pxIterator->pxNext = pxNewListItem;
// 设置父对象
pxNewListItem->pxContainer = pxList;
// 所属列表子项数量+1
(pxList->uxNumberOfItems)++;
}插入到列表尾部
和插入函数相比,少了条件判断。
void vListInsertEnd(List_t *const pxList, ListItem_t *const pxNewListItem)
{
ListItem_t *const pxIndex = pxList->pxIndex;
// 完整性检查
listTEST_LIST_INTEGRITY(pxList);
listTEST_LIST_ITEM_INTEGRITY(pxNewListItem);
pxNewListItem->pxNext = pxIndex; // 指向链表终止节点
pxNewListItem->pxPrevious = pxIndex->pxPrevious;
mtCOVERAGE_TEST_DELAY();
pxIndex->pxPrevious->pxNext = pxNewListItem;
pxIndex->pxPrevious = pxNewListItem;
// 设置父对象
pxNewListItem->pxContainer = pxList;
// 数量+1
(pxList->uxNumberOfItems)++;
}从列表中删除

需要修改:
前一项的后一项
后一项的前一项
UBaseType_t uxListRemove(ListItem_t *const pxItemToRemove)
{
// 获取它的父对象
List_t *const pxList = pxItemToRemove->pxContainer;
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
// 修改当前的列表项
if (pxList->pxIndex == pxItemToRemove)
{
pxList->pxIndex = pxItemToRemove->pxPrevious;
}
//
pxItemToRemove->pxContainer = NULL;
// 所属列表子项数量-1
(pxList->uxNumberOfItems)--;
// 返回列表子项总数
return pxList->uxNumberOfItems;
}