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.rhkb.cn/news/274669.html

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

相关文章

强化学习工具箱(Matlab)

1、Get Started 1.1、MDP环境下训练强化学习智能体 MDP环境如下图 每个圆圈代表一个状态每个状态都有上或下的选择智能体从状态 1 开始智能体接收的奖励值为图中状态转移的值训练目标是最大化累计奖励 &#xff08;1&#xff09;创建 MDP 环境 创建一个具有 8 个状态和 2 …

基于深度学习的番茄叶片病害检测系统(含UI界面、yolov8、Python代码、数据集)

项目介绍 项目中所用到的算法模型和数据集等信息如下&#xff1a; 算法模型&#xff1a;     yolov8 yolov8主要包含以下几种创新&#xff1a;         1. 可以任意更换主干结构&#xff0c;支持几百种网络主干。 数据集&#xff1a;     网上下载的数据集&#x…

03_渲染进程调用node

我们先创建一个文件夹及文件&#xff0c;并且在 html 引入 JS 文件。 在 render.js 里面输入以下内容&#xff1a; let fs require(fs) // let是在当前代码块有效console.log(fs) // 将fs对象的内容打印到控制台供调试和查看 fs 模块&#xff1a;对文件系统进行操作&#xf…

对GIS与游戏引擎(UE4 或 U3D)结合的看法

GIS与游戏引擎结合&#xff0c;这在6年前就已经很多公司在进行探索了&#xff0c;经过这几年的发展&#xff0c;结合当前的政策&#xff0c;从以下几方面说一下我的看法&#xff1a; 1.GIS客户都是特殊单位及领域。2018年后&#xff0c;国内已经对国产化有明确要求了&#xff0…

测试一下 Anthropic 宣称超过 GPT-4 的 Claude 3 Opus

测试一下 Anthropic 宣称超过 GPT-4 的 Claude 3 Opus 0. 引言1. 测试 Claude 3 Opus3. 试用 api key 限制 0. 引言 今天测试一下 Anthropic 发布的 Claude 3 Opus。 3月4日&#xff0c;Anthropic 宣布推出 Claude 3 型号系列&#xff0c;该系列在广泛的认知任务中树立了新的…

Java客户端调用elasticsearch进行深度分页查询 (search_after)

Java客户端调用elasticsearch进行深度分页查询 &#xff08;search_after&#xff09; 一. 代码二. 测试结果 前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 具体的Search_after解…

keepalived原理以及lvs、nginx跟keeplived的运用

keepalived基础 keepalived的原理是根据vrrp协议&#xff08;主备模式&#xff09;去设定的 vrrp技术相关原理 状态机&#xff1b; 优先级0~255 心跳线1秒 vrrp工作模式 双主双备模式 VRRP负载分担过程 vrrp安全认证&#xff1a;使用共享密匙 keepalived工具介绍 keepal…

CSS 【详解】响应式布局(明天内容)

响应式布局&#xff1a; 同一页面在不同的屏幕上有不同的布局&#xff0c;即一套代码自适应不同的屏幕。 常用 单位&#xff1a; 像素&#xff08;px&#xff09;&#xff1a;像素是最常用的长度单位&#xff0c;它表示屏幕上的一个物理像素点。例如&#xff0c;width: 200px; …

如何导入非同一级的py文件里的函数

我正在main_cnn.py里写代码&#xff0c;要到入models文件夹下的resnet50里的CustomResNet50函数。应该怎么导入。 如果 models 文件夹与我们main_cnn.py的主文件不在同一级目录下&#xff0c;而是在上一级目录&#xff0c;你可以这样导入&#xff1a; from ..models.resnet50…

【NR 定位】3GPP NR Positioning 5G定位标准解读(十二)-Multi-RTT定位

前言 3GPP NR Positioning 5G定位标准&#xff1a;3GPP TS 38.305 V18 3GPP 标准网址&#xff1a;Directory Listing /ftp/ 【NR 定位】3GPP NR Positioning 5G定位标准解读&#xff08;一&#xff09;-CSDN博客 【NR 定位】3GPP NR Positioning 5G定位标准解读&#xff08;…

mysql5.6---windows和linux安装教程和忘记密码怎么办

一、windows安装 1.完成解压 解压完成之后将其放到你喜欢的地址当中去&#xff0c;这里我默认放在了D盘&#xff0c;这是我的根目录 2.配置环境变量 我的电脑->属性->高级->环境变量->系统变量 选择PATH,在其后面添加: (注意自己的安装地址) D:\mysql-5.6.49…

基于EasyCVR视频技术的流媒体视频融合与汇聚管理系统建设方案

流媒体视频融合与汇聚管理系统可以实现对各类模块化服务进行统一管理和配置等操作&#xff0c;可实现对应用服务的整合、管理及共享&#xff0c;以标准接口的方式&#xff0c;业务平台及其他第三方业务平台可以方便地调用各类数据&#xff0c;具有开放性和可扩展性。在流媒体视…

Android Studio轮播图使用失败怎么办【已解决】

Android Studio轮播图使用失败怎么办 1.在gethub上面搜索轮播图 2.选择要使用的轮播图 3.查看该轮播图的配置方法 4.复制该依赖放入build.gradle中 5.重新构建 6.使用banner 发现没有报错了 7.参考网址 https://github.com/youth5201314/banner

Java代码审计安全篇-SSRF(服务端请求伪造)漏洞

前言&#xff1a; 堕落了三个月&#xff0c;现在因为被找实习而困扰&#xff0c;着实自己能力不足&#xff0c;从今天开始 每天沉淀一点点 &#xff0c;准备秋招 加油 注意&#xff1a; 本文章参考qax的网络安全java代码审计&#xff0c;记录自己的学习过程&#xff0c;还希望各…

Observer 模式

文章目录 &#x1f4a1;问题引入&#x1f4a1;概念&#x1f4a1;例子&#x1f4a1;总结 &#x1f4a1;问题引入 假设有一个在线商店系统&#xff0c;用户可以订阅商品的库存通知。当某个商品的库存数量发生变化时&#xff0c;系统会自动发送通知给所有订阅了该商品的用户。设计…

鸿蒙原生应用元服务开发-WebGL网页图形库开发无着色器绘制2D图形

无着色器绘制2D图形 使用WebGL开发时&#xff0c;为保证界面图形显示效果&#xff0c;请使用真机运行。 此场景为未使用WebGL绘制的2D图形&#xff08;CPU绘制非GPU绘制&#xff09;。开发示例如下&#xff1a; 1.创建页面布局。index.hml示例如下&#xff1a; <div class…

【C#】【SAP2000】读取SAP2000中frame单元列表到Grasshopper中

private void RunScript(bool build, ref object p1, ref object p2, ref object Profile, ref object stressRatio, ref object temperatureLoad, ref object displacement, ref object frameList){if (build true){// 声明变量int ret;int Numit 0;int[] ObjType new int[…

Linux——线程(3)

在上一篇博客中&#xff0c;我介绍了关于Linux系统中pthread库线程的接口使用以 及对于pthread库的理解。但是我们单单会使用多线程的接口还不够&#xff0c;因为 在使用多线程解决问题的时候&#xff0c;由于进程中的数据对于其中的线程来说大 多是共享的&#xff0c;这也势必…

css3实现3D立方体旋转特效源码

源码介绍 CSS3自动旋转正方体3D特效是一款基于css3 keyframes属性制作的图片相册自动旋转立方体特效 效果展示 下载地址 css3实现3D立方体旋转特效代码

发那科数控机床FanucCNC(NCGuide)仿真模拟器配置和数据采集测试

开发日记3.12 此篇用于记录发那科数控机床(Fanuc CNC)采集程序开发中&#xff0c;用虚拟机做测试时&#xff0c;虚拟机的配置和使用以支持采集软件开发和测试。 配置虚拟机使用仿真软件 下载VMware15 「链接&#xff1a;https://pan.xunlei.com/s/VNsl9Gmb14ANBiiNlsT7vA2LA…