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 );//列表的末尾项因为排在最后,所以要给最大值0xFFFFFFFFpxList->xListEnd.xItemValue = portMAX_DELAY;//列表中只有 xListEnd ,因此上一个与下一个都指向自身pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );//列表中没有列表项(mini列表项不算),因此赋值为0pxList->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);		//插入列表项ListItem1printf("/******************添加列表项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);	//插入列表项ListItem2printf("/******************添加列表项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);	//插入列表项ListItem3printf("/******************添加列表项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);						//删除ListItem2printf("/******************删除列表项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);				//列表末尾添加列表项ListItem2printf("/***************在末尾添加列表项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");

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Elasticsearch基础操作

一、Restful接口 Elasticsearch通过RESTful接口提供与其进行交互的方式。在ES中&#xff0c;提供了功能丰富的RESTful API的操作&#xff0c;包括CRUD、创建索引、删除索引等操作。你可以用你最喜爱的 web 客户端访问 Elasticsearch 。事实上&#xff0c;你甚至可以使用 curl …

k8s简单架构图

背景 k8s目前应用的很广泛&#xff0c;它其实也是采用分布式系统中最常见的一个master管理节点多个worker节点的方式构成的&#xff0c;本文就简单看下k8s的架构 k8s架构图 1.管理节点master&#xff0c;master节点主要有三个模块构成 1.1 APIServer模块&#xff1a;这个模块…

记录 Dubbo+Zookeeper 学习Demo

DubboZookeeper ZookeeperZookeeper 下载可能出现的问题 辅助程序下载dubbo-admin项目打包工程打包常见问题 SpringBoot集成Dubbo项目依赖定义服务接口服务端实现服务端配置依赖代码实现 消费端实现服务端配置依赖代码实现 启动 结合Dubbo官网学习如何完成SpringBootDubboZooke…

React 教程

学习主要来源 React 教程 | 菜鸟教程 React 是一个用于构建用户界面的 JAVASCRIPT 库。 React 主要用于构建 UI&#xff0c;很多人认为 React 是 MVC 中的 V&#xff08;视图&#xff09;。 React 起源于 Facebook 的内部项目&#xff0c;用来架设 Instagram 的网站&#xff0…

学习笔记-华为IPD转型2020:2,IPD的核心思想

2&#xff0c;IPD的核心思想 以客户为导向&#xff1a;应该开发什么产品&#xff1f; 应该开发哪些产品&#xff1f;华为的“基本法”规定&#xff0c;其目的是为客户服务&#xff08;Huawei&#xff0c;1998&#xff09;。然而&#xff0c;在IPD实施后&#xff0c;对这种以客…

视频监控/云存储EasyCVR视频融合平台设备增删改操作不生效是什么原因?

国标GB28181协议EasyCVR安防平台可以提供实时远程视频监控、视频录像、录像回放与存储、告警、语音对讲、云台控制、平台级联、磁盘阵列存储、视频集中存储、云存储等丰富的视频能力&#xff0c;平台支持7*24小时实时高清视频监控&#xff0c;能同时播放多路监控视频流&#xf…

[linux] socket 非阻塞模式使用注意事项

在使用 socket 的一些 api 的时候&#xff0c;默认情况下都是阻塞模式。比如使用 tcp socket 时&#xff0c;客户端调用 connect() 创建连接&#xff0c;connect() 返回的时候要么是创建连接成功了&#xff0c;要么是出现了错误&#xff0c;反正 connect() 返回的时候结果是确定…

微信小程序开发系列(二十九)·界面交互API·loading 提示框、showModal模态对话框、showToast消息提示框

目录 1. loading 提示框 1. 1 wx.showLoading()显示loading提示框 1.2 wx.hideLoading()关闭 loading 提示框 2. showModal 模态对话框 3. showToast 消息提示框 小程序提供了一些用于界面交互的 API&#xff0c;例如&#xff1a;loading 提示框、消息提示框、模态对…

python学习1:csv模块、time模块、random、jieba、worldcloud、pycharm的虚拟环境认识、black格式化文件

标准库与第三方库 模块&#xff08;modules&#xff09;&#xff1a;是包含python函数和变量的文件&#xff0c;名称符合Python标识符要求&#xff0c;并使用.py后缀 包&#xff08;package&#xff09;&#xff1a;是包含其他模块、包的文件夹。名称符合Python标识符要求&am…

安装配置HBase

HBase集群需要整个集群所有节点安装的HBase版本保持一致&#xff0c;并且拥有相同的配置&#xff0c;具体配置步骤如下&#xff1a; 1. 解压缩HBase的压缩包 2. 配置HBase的环境变量 3. 修改HBase的配置文件&#xff0c;HBase的配置文件存放在HBase安装目录下的conf中 4. 首…

蓝桥杯每日一题 走迷宫bfs 超超详细解释!!!

昨天学习了bfs的基本概念&#xff0c;今天来做一道经典习题练练手吧&#xff01; bfs常用的两类题型 1.从A出发是否存在到达B的路径(dfs也可) 2.从A出发到B的最短路径&#xff08;数小:<20才能用dfs&#xff09; 遗留的那个问题的答案- 题目&#xff1a;走迷宫 答案&…

Java爬虫-获取数据的方式之一

目录 一、jsoup的使用 1.概述 2.主要功能 3.快速入门 4.数据准备 二、Selenium 1.概述 2.使用 三、Selenium配合jsoup获取数据 四、爬虫准则 五、Seleniumjsoupmybatis实现数据保存 1.筛选需要的数据 2.创建一个表&#xff0c;准备存储数据 手写&#xff1f;不存在…

基于STM32的电动车防盗器设计

1.项目需求 点击遥控器 A 按键&#xff0c;系统进入警戒模式&#xff0c;一旦检测到震动&#xff08;小偷偷车&#xff09;&#xff0c;则喇叭发出声响报警&#xff0c; 吓退小偷。 点击遥控器 B 按键&#xff0c;系统退出警戒模式&#xff0c;再怎么摇晃系统都不会报警&#…

Qt/C++音视频开发69-保存监控pcm音频数据到mp4文件/监控录像/录像存储和回放/264/265/aac/pcm等

一、前言 用ffmpeg做音视频保存到mp4文件&#xff0c;都会遇到一个问题&#xff0c;尤其是在视频监控行业&#xff0c;就是监控摄像头设置的音频是PCM/G711A/G711U&#xff0c;解码后对应的格式是pcm_s16be/pcm_alaw/pcm_mulaw&#xff0c;将这个原始的音频流保存到mp4文件是会…

Java代码审计工程师直播第六期

本期直播课程将深入探讨Java代码审计的关键概念和技术。涵盖课题包括安全漏洞分析、代码审查方法、常见漏洞案例分析等。学员将通过实例掌握代码审计实战技能&#xff0c;提升对Java应用程序安全的认知和技能水平。 课程大小&#xff1a;6.1G 课程下载&#xff1a;https://do…

从根到叶:深入了解Map和Set

窗间映出一片高远的天空&#xff0c; 向晚的天际宁静而又清明。 我孤独的心灵在幸福地哭泣&#xff0c; 它在为天空如此美好而高兴。 恬静的晚霞一片火红&#xff0c; 晚霞灼烧着我的热情。 此刻的世界没有别人&#xff0c; 只有上帝&#xff0c;我和天空。 ——&#x…

SpringBlade error/list SQL 注入漏洞复现

0x01 产品简介 SpringBlade 是一个由商业级项目升级优化而来的 SpringCloud 分布式微服务架构、SpringBoot 单体式微服务架构并存的综合型项目。 0x02 漏洞概述 SpringBlade 框架后台 /api/blade-log/error/list路径存在SQL注入漏洞,攻击者除了可以利用 SQL 注入漏洞获取数…

让生活更加精致的APP?

晚上好&#xff0c;今天博主来介绍几款帮助你条理生活的APP&#xff0c;让你的生活更加精致&#xff0c;充满仪式感。 一&#xff0e;格志日记 一款以“格子”的方式记录日记的APP&#xff0c;非常简单明了&#xff0c;用户可以依据自己的喜好&#xff0c;来自由定义或者删除格…

SpringBoot实战项目——博客笔记项目

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、项目介绍二、项目的整体框架 2.1 数据库模块 2.2 前端模块 2.3 后端模块三、项目图片展示四、项目的实现 4.1 准备工作 4.…

【R语言实战】——金融时序分布拟合

&#x1f349;CSDN小墨&晓末:https://blog.csdn.net/jd1813346972 个人介绍: 研一&#xff5c;统计学&#xff5c;干货分享          擅长Python、Matlab、R等主流编程软件          累计十余项国家级比赛奖项&#xff0c;参与研究经费10w、40w级横向 文…