内核中有很多双向列表,这些列表可以挂接很多列表项,每条列表都有一个确定的尾节点、列表当前指针、列表项个数

/* 列表结构体 */
typedef struct xLIST
{listFIRST_LIST_INTEGRITY_CHECK_VALUE configLIST_VOLATILE UBaseType_t uxNumberOfItems;  /* 列表项个数 */ListItem_t *configLIST_VOLATILE pxIndex;     /* 当前列表项指针 */MiniListItem_t xListEnd;               /* 列表的尾节点 */listSECOND_LIST_INTEGRITY_CHECK_VALUE
}List_t;

列表尾节点中的有效信息包括:列表项的值、next指针、previous指针

/* 迷你列表项结构体 */
struct xMINI_LIST_ITEM
{listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUEconfigLIST_VOLATILE TickType_t xItemValue;        /* 列表项的值 */struct xLIST_ITEM *configLIST_VOLATILE pxNext;           /* next指针指向后一个列表项 */struct xLIST_ITEM *configLIST_VOLATILE pxPrevious;  /* previous指针指向前一个列表项 */
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;

列表项的内容包括:列表项的值、next指针、previous指针、所属TCB指针、正在挂接的列表指针

/* 列表项结构体 */
struct xLIST_ITEM
{listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE configLIST_VOLATILE TickType_t xItemValue;       /* 列表项的值 */struct xLIST_ITEM *configLIST_VOLATILE pxNext;       /* next指针指向后一个列表项 */struct xLIST_ITEM *configLIST_VOLATILE pxPrevious;  /* previous指针指向前一个列表项 */void *pvOwner;                          /* 该指针指向所属TCB */void *configLIST_VOLATILE pvContainer;          /* 指向包含该列表项的列表 */listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
};
typedef struct xLIST_ITEM ListItem_t;

列表会挂接很多列表项,如图所示:

列表初始化时不包含任何列表项

/* 功能:初始化列表pxList:列表指针 */
void vListInitialise(List_t *const pxList)
{/* 列表初始化时只有尾节点,因此将当前指针指向尾节点 */pxList->pxIndex = (ListItem_t *)&(pxList->xListEnd);/* 尾节点的值初始化为0xffffffff */pxList->xListEnd.xItemValue = portMAX_DELAY;/* 列表初始化时只有尾节点,且列表是双向环形链表 */pxList->xListEnd.pxNext = (ListItem_t *)&(pxList->xListEnd);pxList->xListEnd.pxPrevious = (ListItem_t *)&(pxList->xListEnd);/* 列表项的个数初始化为0 */pxList->uxNumberOfItems = (UBaseType_t)0U;listSET_LIST_INTEGRITY_CHECK_1_VALUE(pxList);listSET_LIST_INTEGRITY_CHECK_2_VALUE(pxList);
}

初始化完成后,如图所示:

列表项初始化时不属于任何列表

/* 功能:初始化列表项pxItem:列表项指针 */
void vListInitialiseItem(ListItem_t *const pxItem)
{/* 将列表项所属列表指针初始化为不指向任何列表 */pxItem->pvContainer = NULL;listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE(pxItem);listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE(pxItem);
}

列表初始化后,如图所示:

列表项插入列表的方式有两种,一种是直接插入当前指针指向的位置,另一种是按照列表项值从小到大插入

/* 功能:将列表项插入列表pxList:列表指针pxNewListItem:列表项指针 */
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->pvContainer = (void *)pxList;/* 列表中列表项个数加一 */(pxList->uxNumberOfItems)++;
}/* 功能:将列表项按列表值从小到大插入列表中pxList:列表指针pxNewListItem:列表项指针 */
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; pxIterator = pxIterator->pxNext){}}/* 将列表项插入列表 */pxNewListItem->pxNext = pxIterator->pxNext;pxNewListItem->pxNext->pxPrevious = pxNewListItem;pxNewListItem->pxPrevious = pxIterator;pxIterator->pxNext = pxNewListItem;/* 将列表项所属列表指针指向列表 */pxNewListItem->pvContainer = (void *)pxList;/* 列表中列表项个数加一 */(pxList->uxNumberOfItems)++;
}

从列表中移除列表项

/* 功能:将列表项从当前所在的列表中移除pxItemToRemove:列表项返回值:移除该列表项后所在列表中列表项的个数 */
UBaseType_t uxListRemove(ListItem_t *const pxItemToRemove)
{/* 列表项所在列表指针 */List_t *const pxList = (List_t *)pxItemToRemove->pvContainer;/* 将列表项从列表中移除 */pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;mtCOVERAGE_TEST_DELAY();/* 列表当前指针指向该列表项,则将列表当前指针改为指向前一个列表项 */if(pxList->pxIndex == pxItemToRemove){pxList->pxIndex = pxItemToRemove->pxPrevious;}else{mtCOVERAGE_TEST_MARKER();}/* 该列表项不属于任何列表 */pxItemToRemove->pvContainer = NULL;/* 列表中列表项个数减一 */(pxList->uxNumberOfItems)--;/* 返回列表项个数 */return pxList->uxNumberOfItems;
}

列表还提供了一些其他的接口

/* 设置列表项所属TCB */
#define listSET_LIST_ITEM_OWNER(pxListItem, pxOwner)    ((pxListItem)->pvOwner = (void *)(pxOwner))/* 获取列表项所属TCB */
#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)/* 获取列表头部列表项的值 */
#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)/* 将当前列表项指针指向下一个列表项,返回所属TCB */
#define listGET_OWNER_OF_NEXT_ENTRY(pxTCB, pxList)                              \
{                                                                               \List_t *const pxConstList = (pxList);                                     \(pxConstList)->pxIndex = (pxConstList)->pxIndex->pxNext;                 \if((void *)(pxConstList)->pxIndex == (void *)&((pxConstList)->xListEnd))   \{                                                                          \(pxConstList)->pxIndex = (pxConstList)->pxIndex->pxNext;             \}                                                                          \(pxTCB) = (pxConstList)->pxIndex->pvOwner;                                  \
}/* 获取列表首节点所属TCB */
#define listGET_OWNER_OF_HEAD_ENTRY(pxList)  ((&((pxList)->xListEnd))->pxNext->pvOwner)/* 判断列表项是否属于指定列表 */
#define listIS_CONTAINED_WITHIN(pxList, pxListItem) ((BaseType_t)((pxListItem)->pvContainer == (void *)(pxList)))/* 获取列表项所在列表 */
#define listLIST_ITEM_CONTAINER(pxListItem) ((pxListItem)->pvContainer)/* 判断列表是否已经初始化(尾节点列表项值为最大可能值0xffffffff) */
#define listLIST_IS_INITIALISED(pxList) ((pxList)->xListEnd.xItemValue == portMAX_DELAY)

FreeRTOS列表相关推荐

  1. 【STM32】FreeRTOS列表和列表项详解

    00. 目录 文章目录 00. 目录 01. 概述 02. 列表 03. 列表项 04. 列表相关宏 05. 列表相关函数 5.1 初始化列表 5.2 初始化列表项 5.3 列表项插入函数 5.4 列 ...

  2. 【STM32】FreeRTOS列表应用示例

    00. 目录 文章目录 00. 目录 01. 概述 02. 任务设计 03. 相关设置 04. 程序设计 05. 实验结果 06. 附录 07. 参考 01. 概述 掌握FreeRTOS中列表和列表项 ...

  3. 【STM32】FreeRTOS 列表和列表项

    文章目录 main.c main.c

  4. FreeRTOS内核实现01:列表与列表项实现

    目录 1. FreeRTOS编程风格 1.1 数据类型 1.2 变量名 1.3 函数名 1.4 宏 2. FreeRTOS列表实现分析 2.1 列表项数据类型 2.2 迷你列表项数据类型 2.3 列表 ...

  5. 【连载】从单片机到操作系统⑥——FreeRTOS任务切换机制详解

    大家晚上好,我是杰杰,最近挺忙的,好久没有更新了,今天周末就吐血更新一下吧! 前言 FreeRTOS是一个是实时内核,任务是程序执行的最小单位,也是调度器处理的基本单位,移植了FreeRTOS,则避免 ...

  6. 正点原子FreeRTOS(上)

    更多干货推荐可以去牛客网看看,他们现在的IT题库内容很丰富,属于国内做的很好的了,而且是课程+刷题+面经+求职+讨论区分享,一站式求职学习网站,最最最重要的里面的资源全部免费!!!点击进入------ ...

  7. HAL库版FreeRTOS(上)

    目录 FreeRTOS 简介 初识FreeRTOS 什么是FreeRTOS? 为什么选择FreeRTOS? FreeRTOS 的特点 商业许可 磨刀不误砍柴工 查找资料 FreeRTOS 官方文档 C ...

  8. FreeRTOS任务相关API函数---查询/改变某个任务的优先级+获取全部/某个任务状态信息

    本文是<ALIENTEK STM32F429 FreeRTOS 开发教程>第十一章学习笔记 第一章笔记–FreeRTOS简介与源码下载 第二章笔记–FreeRTOS在STM32F4上移植 ...

  9. FreeRTOS任务创建

    本文是<ALIENTEK STM32F429 FreeRTOS 开发教程>第八章学习笔记-1 第一章笔记–FreeRTOS简介与源码下载 第二章笔记–FreeRTOS在STM32F4上移植 ...

最新文章

  1. IIS 的负载均衡【IIS7.0以上才可以使用】---- Application Request Routing(ARR)
  2. 排序算法系列:Shell 排序算法
  3. CSS3 总结(一)
  4. Elasticsearch7.15.2 ik中文分词器 定制化分词器之扩展词库(远程)
  5. js请求后台接口返回的图片并转为base64
  6. CSS和CSS3中的伪元素和伪类(总结)
  7. XML非法字符的处理
  8. extern ,extern C 与 __cplusplus
  9. 使用python学习数学建模
  10. java lambda函数_Java中的Lambda函数
  11. c 语言鼠标钩子,线程钩子(鼠标钩子) | C/C++程序员之家
  12. 登录harbor时的SSL异常: x509: certificate is valid for ingress.local
  13. 看完即会,抓取微信小程序数据包教程
  14. html京东下拉菜单设置,实现京东导航栏的下拉框
  15. UI设计色彩模式选择
  16. java二重积分_《University Calculus》-chaper13-多重积分-二重积分的计算
  17. 燕十八PHP高性能架构班教学视频教程
  18. 各种神奇网站集合(持更)
  19. iOS开发——项目篇—高仿百思不得姐
  20. 10种排序算法比较(直接插入排序、希尔排序、冒泡排序、快速排序、简单选择排序、堆排序、归并排序、基数排序、折半插入排序、2路插入排序)

热门文章

  1. QSettings生成以及解析配置文件
  2. Qt工作笔记-QGraphics框架中,给图像中的点连线【获取场景中的数据】【有坑】
  3. java题-如何递归遍历一个文件夹下的所有文件
  4. HTML期末作业-宠物网
  5. c语言打印删除空格,新人提问:如何将输出时每行最后一个空格删除
  6. firefox使用掘金插件_久等了,这款知名浏览器下载插件终于上线Chrome版本!
  7. nodejs获得服务器响应,轻松创建nodejs服务器(6):作出响应
  8. mysql21_mysql2
  9. python property函数_Python内置函数property()如何使用
  10. qq空间登陆 cookie_把这篇 Session、Cookie、Token看完,和面试官随便谈人生