Appearance
数据结构
数据类型
portCHAR: char
portSHORT: short
portLONG: long
portTickType: unsigned short int, unsigned int用于系统计时器, 具体要看文件FreeRTOSConfig.h文件中宏configUSE_16_BIT_TICKS为1时为16位, 0为32位
portBASE_TYPE: long, 根据处理器架构界定
前缀
c: char
s: short
l: long
x: portBASE_TYPE
u: 无符号类型
p: 指针
函数名
包括前缀, 文件名, 函数名
宏
宏的前缀是文件名
信号量的函数是一个宏定义, 但是是遵循函数名的命名方法
列表和列表项
列表和列表项, 实际上就是链表和链表项
单链表: 本身包含一个节点指针, 指向后一个节点, 还可以包含一些私有信息, 通常内嵌一个节点, 会使用链表把零散的数据串联, 通常会设置一个根节点
双向链表: 有两个节点指针
c
struct xLIST_ITEM
{
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if config USE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1.辅助值 */
configLIST_VOLATILE TickType_t xItemValue; /*< The value being listed. In most cases this is used to sort the list in ascending order. */
struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. 指向后一个节 点*/
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. 指向前一 个节点*/
void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. 指向拥有该节点的对象, 通常是PCB*/
struct xLIST * configLIST_VOLATILE pxContainer; /*< Pointer to the list in which this list item is placed (if any). */
listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
};
typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */
c
struct xLIST_ITEM
{
TickType_t xItemValue; //辅助值
struct xLIST_ITEN * pxNext; //指向下一个节点
struct xLIST_ITEN * pxPrevious; //指向上一个节点
void * pvOwner; //指向拥有该节点的内核对象
void * pvCountainer; //指向节点所在的链表
};
typedef struct xLIST_ITEM ListItem_t;
//结尾节点
struct xMINI_LIST_ITEM
{
TickType_t xItemValue; //辅助值, 帮助节点升序排列
struct xLIST_ITEM * pxNext; //指向上一个节点
struct xLIST_ITEM * pxPrevious; //指向下一个节点
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;
//初始化最开始的链表
typedef struct xLIST
{
UBaseType_t uxNumberOfItem; //节点计数器
ListItem_t * pxIndex; //链表节点索引
MiniListItem_t xListEnd; //最后一个节点
}List_t;
定义三中节点
初始化根节点
c
//根节点初始化函数
void vListInitialist(List_t * const pxList)
{
pxList->pxIndex = (ListItem_t *) & (pxList->xListEnd); //索引指向最后一个节点
pxList->xListEnd.xItemValue = portMAX_DELAY;//最后一个节点的数字指向最大
pxList->xListEnd.pxNext = (ListItem_t *) &(pxList->xListEnd);//最后节点pxNext和pxPrevious指向自身
pxList->xListEnd.pxPrevious = (ListItem_t *) &(pxList->xListEnd);
pxList->uxNumberOfItem = (UBaseType_t)0U; //设置节点的数量为0
}
c
//把一个空的链表插入到尾部
void vListInsertEnd(List_t * const pxList, ListItem_t * const pxNewListItem)
{
ListItem_t * const pxIndex = pxList->pxIndex; //获得最后一个节点的指针, 转换为ListItem类型
pxNewListItem->pxNext = pxIndex; //新节点最后指向末尾的节点
pxNewListItem->pxPrevious = pxIndex->pxPrevious; //前一个节点指向末尾结点的前一个节点
pxIndex->pxPrevious->pxNext = pxNewListItem; //之前的倒数第二个节点指向自己
pxIndex->pxPrevious = pxNewListItem; //末尾结点前一个节点指向自己
(pxList->uxNumberOfItem)++;
}
按照值的大小进行插入
c
//按照数字的大小进行插入
void vListInsert(List_t * const pxList, ListItem_t * const pxNewListItem)
{
ListItem_t * pxIterator;
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue; //获取节点的数字
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->pvCountainer = (void *)pxList;
(pxList->uxNumberOfItem)++;
}
c
//移除一个链表
UBaseType_t uxListRemove(ListItem_t * const pxItemToRemov)
{
//获取链表的节点
List_t * const pxList = (List_t *)pxItemToRemov->pvCountainer;
pxItemToRemov->pxNext->pxPrevious = pxItemToRemov->pxPrevious;
pxItemToRemov->pxPrevious->pxNext = pxItemToRemov->pxNext;
if(pxList->pxIndex == pxItemToRemov)
{
//如果删除的最后的节点把他设置为现在数字最大的节点(前一个)
pxList->pxIndex = pxItemToRemov->pxPrevious;
}
pxItemToRemov->pvCountainer = NULL;
(pxList->uxNumberOfItem)--;
return pxList->uxNumberOfItem;
}
- 一些宏定义
c
//初始化节点拥有者
#define liseSET_LIST_ITEM_OWNER(pxListItem, pxOwner) ((pxListItem->pvOwner)=(void *)(pxOwner))
//获得节点的拥有者
#define listGET_ITEM_ITEM_OWNER(pxListItem) (pxListItem->pvOwner)
//初始化节点的排序辅助值
#define liseSET_LIST_ITEM_VALUE(pxListItem, xValue) ((pxListItem)->xItemValue)=xValue
//获取链表根节点的计数器值
#define liseGET_LIST_ITEM_VALUE(pxListItem) (pxListItem->xItemValue)
//获取链表的入口节点计数器的值
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY(pxList) (((pxList)->xListEnd).pxNext->xItemValue)
//获取入口节点
#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 ) ((BaseType_t)((pxList)->uxNumberOfItems==(UBaseType_t)0))
//获取连接数
#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems )
/* 获取链表节点的OWNER,即TCB */
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \
{ \
List_t * const pxConstList = ( pxList ); \
/* 节点索引指向链表第一个节点调整节点索引指针,指向下一个节点,
如果当前链表有N个节点,当第N次调用该函数时,pxInedex则指向第N个节点 */\
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
/* 当前链表为空 */ \
if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \
{ \
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
} \
/* 获取节点的OWNER,即TCB */ \
( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \
}
#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner )