FreeRTOS学习笔记-基于stm32(5)列表和列表项

一、列表与列表项简介

        列表是FreeRTOS中的一种数据结构,类似双向循环链表。用来跟踪FreeRTOS中的任务。列表项就是存放在列表中的项目。

二、列表

列表结构体:

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;

①、首尾两个校验值是通过宏定义的已知常量,通过检测这两个值来判断列表的数据在运行过程中是否正确。该功能一般用于调试,默认关闭;

②、uxNumberOfItems 用于记录列表中列表项的个数;

③、pxIndex 用来指向列表中的某个列表项,一般用来遍历列表;

④、xListEnd 是末尾列表项

⑤、列表示意图:

                                        

三、列表项

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;                                       //列表项的拥有者
	void * configLIST_VOLATILE pvContainer;               //列表项所在的列表
	listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE            //校验项
typedef struct xLIST_ITEM ListItem_t;

①、首尾校验项默认关闭;

②、xItemValue 为列表项的一个值,用来对列表项进行排序;

③、pxNext、pxPrevious 前后指针;

④、pvOwner 用来指向任务控制块;

⑤、pvContainer 用来指向列表,例如就绪列表、阻塞列表、挂起列表;

⑥、列表项示意图:

                                    

四、mini列表项

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;

与列表项类似,固定在列表项的结尾。

mini列表项示意图:

                                          

 五、列表与列表项相关API函数

1、列表初始化

void vListInitialise( List_t * const pxList )
{
//列表中只有 xListEnd ,因此 pxIndex 指向 xListEnd 
    pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );

//列表的末尾项因为排在最后,所以要给最大值0xFFFFFFFF
    pxList->xListEnd.xItemValue = portMAX_DELAY;

//列表中只有 xListEnd ,因此上一个与下一个都指向自身
    pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );
    pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );

//列表中没有列表项(mini列表项不算),因此赋值为0
    pxList->uxNumberOfItems = ( UBaseType_t ) 0U;

//检测完整性代码,默认关闭
    listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
    listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}

2、列表项初始化 

void vListInitialiseItem( ListItem_t * const pxItem )
{
//初始化列表项所在列表为空
    pxItem->pvContainer = NULL; //初始化 pvContainer 为 NULL

//初始化用于完整性检查的变量,如果开启了这个功能的话。
    listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
    listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
}

        列表项其他成员会在插入时进行设置。 

3、插入列表项

        void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem );

        用于将插入列表的列表项按照 xItemValue 的大小升序进行排列,有序的插入到列表中。

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 );
    
    //如果新插入的 xItemValue 与末尾列表项 xItemValue 值相等,那么让它插入到末尾列表项的上一个
    if( xValueOfInsertion == portMAX_DELAY )
    {
        pxIterator = pxList->xListEnd.pxPrevious;
    }
    else
    {

    //末尾列表项赋值给新定义的列表项 pxIterator,然后遍历列表,判断 xItemValue 的值是否大于 xValueOfInsertion。如果大于则退出循环,找到插入的位置
        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 )++;
}

        插入列表项实例: 

4、末尾插入列表项

        类似于双向链表插入到末尾,无序插入,只与 pxIndex 指向的列表项有关,只插入到 pxIndex 指向的列表项的前面。

void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{
    //新建一个 pxIndex 指向列表 pxIndex 指向的列表项,默认为末尾列表项
    ListItem_t * const pxIndex = pxList->pxIndex;

    listTEST_LIST_INTEGRITY( pxList );
    listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );

    //将待插列表项插入到 pxIndex 的前面
    pxNewListItem->pxNext = pxIndex;
    pxNewListItem->pxPrevious = pxIndex->pxPrevious;

    mtCOVERAGE_TEST_DELAY();

    pxIndex->pxPrevious->pxNext = pxNewListItem;
    pxIndex->pxPrevious = pxNewListItem;

    //更新待插列表项所在列表
    pxNewListItem->pvContainer = ( void * ) pxList;

    //更新列表中所含列表项的数值
    ( pxList->uxNumberOfItems )++;
}

5、移除列表项

        用于将列表项移除其所在列表。返回值为所在列表剩余的列表项

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();

    //如果 pxIndex 正好指向待移除的列表项
    if( pxList->pxIndex == pxItemToRemove )
    {
        // 让 pxIndex 指向上一个列表项
        pxList->pxIndex = pxItemToRemove->pxPrevious;
    }
    else
    {
        mtCOVERAGE_TEST_MARKER();
    }

    //将待移除的列表项所在列表指针清空
    pxItemToRemove->pvContainer = NULL;

    //更新列表中列表项数量
    ( pxList->uxNumberOfItems )--;

    //返回剩余数量
    return pxList->uxNumberOfItems;
}

六、实例

        该实例执行列表的相关操作并将每次执行完操作后列表项指针所指地址打印出来。

1、定义列表与列表项

List_t      TestList;  //定义测试列表
ListItem_t  ListItem1; //定义测试列表项1
ListItem_t  ListItem2; //定义测试列表项2
ListItem_t  ListItem3; //定义测试列表项3

2、初始化列表与列表项

    vListInitialise( &TestList );
    vListInitialiseItem( &ListItem1 );
    vListInitialiseItem( &ListItem2 );
    vListInitialiseItem( &ListItem3 );
    ListItem1.xItemValue=40;
    ListItem1.xItemValue=60;
    ListItem1.xItemValue=50;

3、插入与删除列表项

    vListInsert(&TestList,&ListItem1);		//插入列表项ListItem1
	printf("/******************添加列表项ListItem1*****************/\r\n");
	printf("项目                              地址				    \r\n");
	printf("TestList->xListEnd->pxNext        %#x					\r\n",(int)(TestList.xListEnd.pxNext));
	printf("ListItem1->pxNext                 %#x					\r\n",(int)(ListItem1.pxNext));
	printf("/*******************前后向连接分割线********************/\r\n");
	printf("TestList->xListEnd->pxPrevious    %#x					\r\n",(int)(TestList.xListEnd.pxPrevious));
	printf("ListItem1->pxPrevious             %#x					\r\n",(int)(ListItem1.pxPrevious));
	printf("/************************结束**************************/\r\n");
    
    vListInsert(&TestList,&ListItem2);	//插入列表项ListItem2
	printf("/******************添加列表项ListItem2*****************/\r\n");
	printf("项目                              地址				    \r\n");
	printf("TestList->xListEnd->pxNext        %#x					\r\n",(int)(TestList.xListEnd.pxNext));
	printf("ListItem1->pxNext                 %#x					\r\n",(int)(ListItem1.pxNext));
	printf("ListItem2->pxNext                 %#x					\r\n",(int)(ListItem2.pxNext));
	printf("/*******************前后向连接分割线********************/\r\n");
	printf("TestList->xListEnd->pxPrevious    %#x					\r\n",(int)(TestList.xListEnd.pxPrevious));
	printf("ListItem1->pxPrevious             %#x					\r\n",(int)(ListItem1.pxPrevious));
	printf("ListItem2->pxPrevious             %#x					\r\n",(int)(ListItem2.pxPrevious));
	printf("/************************结束**************************/\r\n");
    
    vListInsert(&TestList,&ListItem3);	//插入列表项ListItem3
	printf("/******************添加列表项ListItem3*****************/\r\n");
	printf("项目                              地址				    \r\n");
	printf("TestList->xListEnd->pxNext        %#x					\r\n",(int)(TestList.xListEnd.pxNext));
	printf("ListItem1->pxNext                 %#x					\r\n",(int)(ListItem1.pxNext));
	printf("ListItem3->pxNext                 %#x					\r\n",(int)(ListItem3.pxNext));
	printf("ListItem2->pxNext                 %#x					\r\n",(int)(ListItem2.pxNext));
	printf("/*******************前后向连接分割线********************/\r\n");
	printf("TestList->xListEnd->pxPrevious    %#x					\r\n",(int)(TestList.xListEnd.pxPrevious));
	printf("ListItem1->pxPrevious             %#x					\r\n",(int)(ListItem1.pxPrevious));
	printf("ListItem3->pxPrevious             %#x					\r\n",(int)(ListItem3.pxPrevious));
	printf("ListItem2->pxPrevious             %#x					\r\n",(int)(ListItem2.pxPrevious));
	printf("/************************结束**************************/\r\n");
    
    uxListRemove(&ListItem2);						//删除ListItem2
	printf("/******************删除列表项ListItem2*****************/\r\n");
	printf("项目                              地址				    \r\n");
	printf("TestList->xListEnd->pxNext        %#x					\r\n",(int)(TestList.xListEnd.pxNext));
	printf("ListItem1->pxNext                 %#x					\r\n",(int)(ListItem1.pxNext));
	printf("ListItem3->pxNext                 %#x					\r\n",(int)(ListItem3.pxNext));
	printf("/*******************前后向连接分割线********************/\r\n");
	printf("TestList->xListEnd->pxPrevious    %#x					\r\n",(int)(TestList.xListEnd.pxPrevious));
	printf("ListItem1->pxPrevious             %#x					\r\n",(int)(ListItem1.pxPrevious));
	printf("ListItem3->pxPrevious             %#x					\r\n",(int)(ListItem3.pxPrevious));
	printf("/************************结束**************************/\r\n");\
    
    TestList.pxIndex=TestList.pxIndex->pxNext;			//pxIndex向后移一项,这样pxIndex就会指向ListItem1。
	vListInsertEnd(&TestList,&ListItem2);				//列表末尾添加列表项ListItem2
	printf("/***************在末尾添加列表项ListItem2***************/\r\n");
	printf("项目                              地址				    \r\n");
	printf("TestList->pxIndex                 %#x					\r\n",(int)TestList.pxIndex);
	printf("TestList->xListEnd->pxNext        %#x					\r\n",(int)(TestList.xListEnd.pxNext));
	printf("ListItem2->pxNext                 %#x					\r\n",(int)(ListItem2.pxNext));
	printf("ListItem1->pxNext                 %#x					\r\n",(int)(ListItem1.pxNext));
	printf("ListItem3->pxNext                 %#x					\r\n",(int)(ListItem3.pxNext));
	printf("/*******************前后向连接分割线********************/\r\n");
	printf("TestList->xListEnd->pxPrevious    %#x					\r\n",(int)(TestList.xListEnd.pxPrevious));
	printf("ListItem2->pxPrevious             %#x					\r\n",(int)(ListItem2.pxPrevious));
	printf("ListItem1->pxPrevious             %#x					\r\n",(int)(ListItem1.pxPrevious));
	printf("ListItem3->pxPrevious             %#x					\r\n",(int)(ListItem3.pxPrevious));
	printf("/************************结束**************************/\r\n\r\n\r\n");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/452265.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Unity 显示MeshRenderer的渲染层级

Unity 显示MeshRenderer的渲染层级 前言源码MeshRendererInspectorSkinnedMeshRendererInspector 参考 前言 Mesh Renderer和Skinned Mesh Renderer组件默认不显示Order&#xff0c;找了个工具显示一下。 源码 下面两个代码放入Editor文件夹中 MeshRendererInspector Me…

ChatGPT Prompt 的原理总结

ChatGPT Prompt 的原理总结 ChatGPT Prompt 是 OpenAI 开发的大型语言模型 ChatGPT 的一种使用方式。通过 Prompt&#xff0c;用户可以引导 ChatGPT 生成特定内容&#xff0c;例如回答问题、写故事、写代码等等。 Prompt 的原理 Prompt 本质上是一段文本&#xff0c;它告诉 C…

人工智能在增强数据安全方面的作用

近年来&#xff0c;人工智能&#xff08;AI&#xff09;的力量已被证明是无与伦比的。它不再是我们想象的主题。人工智能已经成为现实&#xff0c;并且越来越清楚地表明它可以让世界变得更美好。但人工智能能帮助我们增强数据安全吗&#xff1f; 由于技术的日益普及&#xff0…

Java JUC 笔记(2)

Java JUC 笔记&#xff08;2&#xff09; 锁框架 JDK5以后增加了Lock接口用来实现锁功能&#xff0c;其提供了与synchronized类似的同步功能&#xff0c;但是在使用时手动的获取和释放锁 Lock和Condition锁 这里的锁与synchronized锁不太一样&#xff0c;我们可以认为是Loc…

递归与递推

递归 92. 递归实现指数型枚举 - AcWing题库 import java.util.*;public class Main{static int N 16, n;static int[] st new int[N];//st[x] 等于0表示还没考虑到它&#xff0c;等于1表示选它&#xff0c;等于2表示不选它public static void dfs(int u){if(u > n){for…

蓝桥·算法双周赛|第七场分级赛——小白入门赛

&#x1f525;博客介绍&#xff1a; 27dCnc &#x1f3a5;系列专栏&#xff1a; <<数据结构与算法>> << 算法入门>> << C项目>> &#x1f3a5; 当前专栏: << 算法入门>> 专题 : 数据结构帮助小白快速入门算法 &#x1f4…

蓝鲸作业平台升级openssh执行方案分享

本文来自腾讯蓝鲸智云社区用户&#xff1a;AK47 蓝鲸的运维系统在我们单位使用已经快四个年头了&#xff0c;从刚开始的5到现在最新的7.1都有部署、测试、验证和使用。在实际的使用过程中&#xff0c;给我们运维提供了非常大的帮助。其中有一个场景分享给大家。这个场景是关于o…

NVidia NX 中 ROS serial软件包的安装

自己装的ROS是noetic版本&#xff0c;受限于网络&#xff0c;直接用命令安装串口包不行。于是手动安装了一次。 1 下载源码 git clone https://github.com/wjwwood/serial.git 或者直接在浏览器里面输入 https://github.com/wjwwood/serial.git 2 解压 然后在serial&#xf…

LeetCode108题:将有序数组转换为二叉搜索树(python3)

一个容易想到的思路&#xff1a;使用 nums 中最靠近中心的位置作为整棵 BST 的根节点&#xff0c;确保左右子树节点数量平衡。随后递归构造 nums 中下标范围为 [0,mid−1]作为左子树&#xff0c;递归构造 nums 中下标范围为 [mid1,n−1]作为右子树。 # Definition for a binar…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的田间杂草检测系统(深度学习模型+UI界面+Python代码+训练数据集)

摘要&#xff1a;开发用于田间杂草识别的系统对提高农业运营效率和提升作物产出至关重要。本篇文章详尽阐述了如何应用深度学习技术开发一个用于田间杂草识别的系统&#xff0c;并附上了完备的代码实现。该系统基于先进的YOLOv8算法&#xff0c;并对比了YOLOv7、YOLOv6、YOLOv5…

保护数字前沿:有效的威胁暴露管理

人工智能技术正在从根本上改变网络安全领域的方向。仅 2023 年&#xff0c;全球企业预计将在人工智能上花费 1027.8 亿美元&#xff0c;以阻止网络安全威胁。 人工智能 (AI)在增强网络安全措施方面发挥着关键作用&#xff0c;因为它能够快速分析大量数据并识别可能表明潜在威胁…

Weblogic 常规渗透测试环境

测试环境 本环境模拟了一个真实的weblogic环境&#xff0c;其后台存在一个弱口令&#xff0c;并且前台存在任意文件读取漏洞。分别通过这两种漏洞&#xff0c;模拟对weblogic场景的渗透。 Weblogic版本&#xff1a;10.3.6(11g) Java版本&#xff1a;1.6 弱口令 环境启动后…

读取Excel的封装方法

步骤&#xff1a; 1、我们需要将得到的结果存储到list集合中&#xff0c;所以实例化一个ArrayList类 List<CaseInfo> list new ArrayList<CaseInfo>();//实例化一个类 常规下在list里添加内容即可 不再是字符串类&#xff0c;是caseinfo用例 list.add里添加casei…

【位运算】【脑筋急转弯】2749. 得到整数零需要执行的最少操作数

作者推荐 视频算法专题 本文涉及知识点 2749. 得到整数零需要执行的最少操作数 给你两个整数&#xff1a;num1 和 num2 。 在一步操作中&#xff0c;你需要从范围 [0, 60] 中选出一个整数 i &#xff0c;并从 num1 减去 2i num2 。 请你计算&#xff0c;要想使 num1 等于 …

常用的gpt网站

ChatGPT是一款基于人工智能技术的对话型AI助手&#xff0c;能够进行自然语言交互并提供个性化的对话服务。通过先进的深度学习模型&#xff0c;ChatGPT能够理解用户输入的文本&#xff0c;并生成有逻辑、连贯性的回复。它可以回答各种问题、提供建议、分享知识&#xff0c;还能…

Zookeeper搭建

目录 前言 初了解Zookeeper 搭建 准备 配置Zookeeper 前言 今天来介绍Zookeeper的搭建&#xff0c;其实Zookeeper的搭建很简单&#xff0c;但是为什么还要单独整一节呢&#xff0c;这就不得不先了解Zookeeper有什么功能了&#xff01;而且现在很火的框架也离不开Zookeepe…

来来来, SAP BTP下使用CAP来生成PostgreSQL应用(一): Node.js篇

前言 SAP云应用程序编程模型(CAP)是一个语言、库和工具框架&#xff0c;用于构建企业级服务和应用程序。它引导开发人员沿着一条经过验证的最佳实践的“黄金之路”前进&#xff0c;并为反复出现的任务提供大量开箱即用的解决方案。 我们这就来看看SAP BTP的CAP到底提供了哪些…

有来团队后台项目-解析5

一、 husky 安装 pnpm install -D husky生成husky 配置文件 如果文件中有.git文件&#xff0c;那么直接执行 npx husky-init如果没有&#xff0c;那么先执行git init 结果&#xff1a; PS F:\company_project\demo\youlahoutaijiexi\vite-project> git init Initializ…

【DDR】DDR4学习记录

这里以美光DDR4芯片 MT40A512M16HA-075E datasheet 为例&#xff0c;说明DDR4存储器的原理及仿真。   根据开发板手册ug1302&#xff0c;在vcu128&#xff08;xcvu37p&#xff09;开发板上&#xff0c;共具有5块DDR4芯片&#xff0c;在数据信号上4块DDR4具有16位数据线&#…

【HomeAssistant新版文件管理器】

【HomeAssistant新版文件管理器】 1. 前言2. 地址3. 安装4. 使用方法5. 总结欢迎大家阅读2345VOR的博客【Home Assistant 之QQ邮箱推送提醒】🥳🥳🥳2345VOR鹏鹏主页: 已获得CSDN《嵌入式领域优质创作者》称号🎉🎉、阿里云《arduino专家博主》👻👻👻,座右铭:…