FreeRTOS中与链表相关的操作均在list.h和list.c这两个文件中实现,list.h第一次使用需要在include文件夹下面新建然后添 加到工程freertos/source这个组文件,list.c第一次使用需要在freertos文件夹下面新建然后添加到工程freertos/source这个 组文件。

FreeRTOS 链表的定义:

1
2
3
4
5
6
7
8
9
struct xLIST_ITEM
{
TickType_t xItemValue; /* 辅助值,用于帮助节点做顺序排列 */(1)
struct xLIST_ITEM * pxNext; /* 指向链表下一个节点 */(2)
struct xLIST_ITEM * pxPrevious; /* 指向链表前一个节点 */(3)
void * pvOwner; /* 指向拥有该节点的内核对象,通常是TCB */(4)
void * pvContainer; /* 指向该节点所在的链表 */(5)
};
typedefstruct xLIST_ITEM ListItem_t; /* 节点数据类型重定义 */(6)

链表初始化

链表节点初始化函数在list.c中实现

1
2
3
4
5
6
7
8
9
10
11
void vListInitialiseItem( ListItem_t * const pxItem )
{
/* Make sure the list item is not recorded as being on a list. */
/* 初始化该节点所在的链表为空,表示节点还没有插入任何链表 */
pxItem->pxContainer = 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 );
}

实现链表根节点

链表根节点的数据结构在list.h中定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
* Definition of the type of queue used by the scheduler.
*/
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;

typedefstruct xLIST
{
UBaseType_t uxNumberOfItems; /* 链表节点计数器 */(1)
ListItem_t * pxIndex; /* 链表节点索引指针 */(2)
MiniListItem_t xListEnd; /* 链表最后一个节点 */(3)
} List_t;

链表最后一个节点。我们知道,链表是首尾相连的,是一个圈,首就是尾,尾就是首,这里从字面上 理解就是链表的最后一个节点,实际也就是链表的第一个节点,我们称之为生产者。该生产者的数据类型是一个精简的节点,也 在list.h中定义,具体实现见

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct xMINI_LIST_ITEM
{
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
configLIST_VOLATILE TickType_t xItemValue;
struct xLIST_ITEM * configLIST_VOLATILE pxNext;
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;

struct xMINI_LIST_ITEM
{
TickType_t xItemValue; /* 辅助值,用于帮助节点做升序排列 */
struct xLIST_ITEM * pxNext; /* 指向链表下一个节点 */
struct xLIST_ITEM * pxPrevious; /* 指向链表前一个节点 */
};
typedefstruct xMINI_LIST_ITEM MiniListItem_t; /* 精简节点数据类型重定义 */

链表根节点初始化

链表节点初始化函数在list.c中实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
void vListInitialise( List_t * const pxList )
{
/* The list structure contains a list item which is used to mark the
* end of the list. To initialise the list the list end is inserted
* as the only list entry. */
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */

/* The list end value is the highest possible value in the list to
* ensure it remains at the end of the list. */
pxList->xListEnd.xItemValue = portMAX_DELAY;

/* The list end next and previous pointers point to itself so we know
* when the list is empty. */
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */

pxList->uxNumberOfItems = ( UBaseType_t ) 0U;

/* Write known values into the list if
* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}

void vListInitialise( List_t * const pxList )
{
/* 将链表索引指针指向最后一个节点 */(1)
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );

/* 将链表最后一个节点的辅助排序的值设置为最大,确保该节点就是链表的最后节点 */(2)
pxList->xListEnd.xItemValue = portMAX_DELAY;

/* 将最后一个节点的pxNext和pxPrevious指针均指向节点自身,表示链表为空 */(3)
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );
pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );

/* 初始化链表节点计数器的值为0,表示链表为空 */(4)
pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
}