【学习FreeRTOS】第8章——FreeRTOS列表和列表项

1.列表和列表项的简介

列表是 FreeRTOS 中的一个数据结构,概念上和链表有点类似,列表被用来跟踪 FreeRTOS中的任务。列表项就是存放在列表中的项目。

在这里插入图片描述

  • 列表相当于链表,列表项相当于节点,FreeRTOS 中的列表是一个双向环形链表
  • 列表的特点:列表项间的地址非连续的,是人为的连接到一起的。列表项的数目是由后期添加的个数决定的,随时可以改变
  • 数组的特点:数组成员地址是连续的,数组在最初确定了成员数量后期无法改变
  • 在OS中任务的数量是不确定的,并且任务状态是会发生改变的,所以非常适用列表(链表)这种数据结构

1.1.列表的数据结构

typedef struct xLIST
{listFIRST_LIST_INTEGRITY_CHECK_VALUE	/* 校验值 */volatile UBaseType_t 					uxNumberOfItems;			/* 列表中的列表项数量 */ListItem_t * c							onfigLIST_VOLATILE pxIndex	/* 用于遍历列表项的指针 */MiniListItem_t 							xListEnd					/* 末尾列表项 */listSECOND_LIST_INTEGRITY_CHECK_VALUE	/* 校验值 */
} List_t;
  • 在该结构体中, 包含了两个宏,这两个宏是确定的已知常量, FreeRTOS通过检查这两个常量的值,来判断列表的数据在程序运行过程中,是否遭到破坏 ,该功能一般用于调试, 默认是不开启的
  • 成员uxNumberOfItems:用于记录列表中列表项的个数(不包含 xListEnd)
  • 成员 pxIndex:用于指向列表中的某个列表项,一般用于遍历列表中的所有列表项
  • 成员xListEnd:是一个迷你列表项,排在最末尾

1.2.列表项的数据结构

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								/* 列表项的拥有者 */struct xLIST * 								configLIST_VOLATILE pxContainer; 	/* 列表项所在列表 */listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE	/* 用于检测列表项的数据完整性 */
};
typedef struct xLIST_ITEM ListItem_t; 	
  • xItemValue为列表项的值,这个值多用于按升序对列表中的列表项进行排序
  • pxNext 和 pxPrevious分别用于指向列表中列表项的下一个列表项和上一个列表项
  • pxOwner 用于指向包含列表项的对象(通常是任务控制块)
  • pxContainer 用于指向列表项所在列表。

1.3.迷你列表项的数据结构

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;
  • xItemValue为列表项的值,这个值多用于按升序对列表中的列表项进行排序 (一般为0xFFFFFFFF)
  • pxNext 和 pxPrevious 分别用于指向列表中列表项的下一个列表项和上一个列表项
  • 迷你列表项只用于标记列表的末尾和挂载其他插入列表中的列表项,因此不需要成员变量 pxOwner 和 pxContainer,以节省内存开销

1.4.列表、列表项、迷你列表项的关系

在这里插入图片描述
在这里插入图片描述

2.列表相关API函数介绍

2.1.初始化列表vListInitialise()

void vListInitialise( List_t * const pxList) 
{ /* 初始化时,列表中只有xListEnd,因此pxIndex指向xListEnd */ pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /* xListEnd的值初始化为最大值,用于列表项升序排序时,排在最后 */pxList->xListEnd.xItemValue = portMAX_DELAY; /* 初始化时,列表中只有xListEnd,因此上一个和下一个列表项都为xListEnd本身 */ pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd ); /*初始化时,列表中的列表项数量为0(不包含xListEnd) */ pxList->uxNumberOfItems = ( UBaseType_t ) 0U; /* 初始化用于检测列表数据完整性的校验值 */ listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ); listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ); 
}
  • 形参:待初始化列表
    在这里插入图片描述

2.2.初始化列表项vListInitialiseItem()

void vListInitialiseItem(ListItem_t * const pxItem)
{/* 初始化时,列表项所在列表设为空 */pxItem->pxContainer = NULL;/* 初始化用于检测列表项数据完整性的校验值 */listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
}
  • 形参:待初始化列表项

2.3.列表末尾插入列表项vListInsertEnd()

void vListInsertEnd(List_t * const pxList,ListItem_t * const pxNewListItem)
{/* 获取列表pxIndex 指向的列表项 */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->pxContainer = pxList;/* 更新列表中列表项的数量 */( pxList->uxNumberOfItems )++;
}
  • 形参:列表、待插入列表项
  • 此函数用于将待插入列表的列表项插入到列表 pxIndex 指针指向的列表项前面,是一种无序的插入方法
    在这里插入图片描述

2.4.列表插入列表项vListInsert()

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 ) { /* 插入的位置为列表xListEnd前面 */ 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->pxContainer = pxList; /* 更新列表中列表项的数量 */ ( pxList->uxNumberOfItems )++; 
}
  • 形参:列表、待插入列表项
  • 此函数用于将待插入列表的列表项按照列表项值升序进行排序,有序地插入到列表中
    在这里插入图片描述

2.5.列表移除列表项uxListRemove()

UBaseType_t uxListRemove(ListItem_t * const pxItemToRemove)
{List_t * const pxList = pxItemToRemove->pxContainer;/* 从列表中移除列表项 */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->pxContainer = NULL;/* 更新列表中列表项的数量 */( pxList->uxNumberOfItems )--;/* 返回列表项移除后列表中列表项的数量 */return pxList->uxNumberOfItems;
}
  • 形参:待移除列表项
  • 返回值:待移除列表项移除后,所在列表剩余列表项的数量
  • 此函数用于将列表项从列表项所在列表中移除
    在这里插入图片描述

3.列表项的插入和删除实验

  • 实验目的:学会对FreeRTOS 列表和列表项的操作函数使用,并观察运行结果和理论分析是否一致
  • 实验设计:将设计三个任务:start_task、task1、task2
    start_task:用来创建其他的2个任务
    task1:实现LED0每500ms闪烁一次,用来提示系统正在运行
    task2:调用列表和列表项相关API函数,并且通过串口输出相应的信息,进行观察

在这里插入图片描述

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

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

相关文章

@Repeatable的作用以及具体如何使用

文章目录 1. 前言2. 先说结论3. 案例演示 1. 前言 最近无意看到某些注解上有Repeatable&#xff0c;出于比较好奇&#xff0c;因此稍微研究并写下此文章。 2. 先说结论 Repeatable的作用&#xff1a;使被他注释的注解可以在同一个地方重复使用。 具体使用如下&#xff1a; T…

.netcore grpc客户端工厂及依赖注入使用

一、客户端工厂概述 gRPC 与 HttpClientFactory 的集成提供了一种创建 gRPC 客户端的集中方式。可以通过依赖包Grpc.Net.ClientFactory中的AddGrpcClient进行gRPC客户端依赖注入AddGrpcClient函数提供了许多配置项用于处理一些其他事项&#xff1b;例如AOP、重试策略等 二、案…

【100天精通python】Day41:python网络爬虫开发_爬虫基础入门

目录 专栏导读 1网络爬虫概述 1.1 工作原理 1.2 应用场景 1.3 爬虫策略 1.4 爬虫的挑战 2 网络爬虫开发 2.1 通用的网络爬虫基本流程 2.2 网络爬虫的常用技术 2.3 网络爬虫常用的第三方库 3 简单爬虫示例 专栏导读 专栏订阅地址&#xff1a;https://blog.csdn.net/…

Databend 开源周报第 106 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 数据脱敏 Data…

APSIM模型参数优化 批量模拟丨气象数据准备、物候发育和光合生产、物质分配与产量模拟、土壤水分平衡算法、土壤碳氮平衡模块、农田管理模块等

随着数字农业和智慧农业的发展&#xff0c;基于过程的农业生产系统模型在模拟作物对气候变化的响应与适应、农田管理优化、作物品种和株型筛选、农田固碳和温室气体排放等领域扮演着越来越重要的作用。APSIM (Agricultural Production Systems sIMulator)模型是世界知名的作物生…

nginx php-fpm安装配置

nginx php-fpm安装配置 nginx本身不能处理PHP&#xff0c;它只是个web服务器&#xff0c;当接收到请求后&#xff0c;如果是php请求&#xff0c;则发给php解释器处理&#xff0c;并把结果返回给客户端。 nginx一般是把请求发fastcgi管理进程处理&#xff0c;fascgi管理进程选…

6.RocketMQ之索引文件ConsumeQueue

本文着重分析为consumequeue/topic/queueId目录下的索引文件。 1.ConsumeQueueStore public class ConsumeQueueStore {protected final ConcurrentMap<String>, ConcurrentMap<Integer>, ConsumeQueueInterface>> consumeQueueTable;public boolean load(…

Sentinel 规则持久化

文章目录 Sentinel 规则持久化一、修改order-service服务1.引入依赖2.配置nacos地址 第二步修改非常麻烦&#xff0c;可以略过&#xff0c;直接使用已经打好包的来使用二、修改sentinel-dashboard源码1. 解压2. 修改nacos依赖3. 添加nacos支持4. 修改nacos地址5. 配置nacos数据…

micropython SSD1306/SSD1315驱动

目录 简介 代码 功能 显示ASCII字符 ​编辑 画任意直线 画横线 画竖线 画矩形 画椭圆 画立方体 画点阵图 翻转 反相 滚动 横向滚动 纵向滚动 奇葩滚动 简介 我重新写了一个驱动&#xff0c;增加了一些功能&#xff0c;由于我的硬件是128*64oled单色I2C&#xff0c;我只…

Hlang--用Python写个编程语言-判断与循环

文章目录 前言语法描述判断循环词法解析语法解析定义节点生成节点判断节点循环节点解释器处理判断节点循环处理前言 okey,很好,在上一篇文章当中,我们实现了这个基本的逻辑运算,所以的话,在这里,我们将可以实现到我们的这个判断和循环了。由于这里的话,我们的操作其实和…

UML图绘制 -- 类图

1.类图的画法 类 整体是个矩形&#xff0c;第一层类名&#xff0c;第二层属性&#xff0c;第三层方法。 &#xff1a;public- : private# : protected空格: 默认的default 对应的类写法。 public class Student {public String name;public Integer age;protected I…

浏览器渲染原理 - 输入url 回车后发生了什么

目录 渲染时间点渲染流水线1&#xff0c;解析&#xff08;parse&#xff09;HTML1.1&#xff0c;DOM树1.2&#xff0c;CSSOM树1.3&#xff0c;解析时遇到 css 是怎么做的1.4&#xff0c;解析时遇到 js 是怎么做的 2&#xff0c;样式计算 Recalculate style3&#xff0c;布局 la…

集群、负载均衡集群、高可用集群简介,LVS工作结构、工作模式、调度算法和haproxy/nginx模式拓扑介绍

一.集群的定义 1.定义 2.分类 &#xff08;1&#xff09;负载均衡集群&#xff08;LBC/LB&#xff09; &#xff08;2&#xff09;高可用集群&#xff08;HAC&#xff09; 二.使用集群的意义 1.高性价比和性能比 2.高可用性 3.可伸缩性强 4.持久和透明性高 三.常见的…

图像去雨-雨线清除-图像处理-(计算机作业附代码)

背景 多年来&#xff0c;图像去雨已经被广泛研究&#xff0c;使用传统方法和基于学习的方法。然而&#xff0c;传统方法如高斯混合模型和字典学习方法耗时&#xff0c;并且无法很好地处理受到严重雨滴影响的图像块。 算法 通过考虑雨滴条状特性和角度分布&#xff0c;这个问…

Mybatis查询数据库返回任意形式的返回结构

Mybatis查询数据库返回任意形式的返回结构 mapper的接口mapper.xml mapper的接口 假如有多个记录&#xff0c;可以将map放到 arraylist里 mapper.xml 主要是通过resultMap定义好映射格式

尼科彻斯定理-C语言/Java

描述 验证尼科彻斯定理&#xff0c;即&#xff1a;任何一个整数m的立方都可以写成m个连续奇数之和。 例如&#xff1a; 1^31 2^335 3^37911 4^313151719 输入一个正整数m&#xff08;m≤100&#xff09;&#xff0c;将m的立方写成m个连续奇数之和的形式输出。&…

vscode远程连接Linux失败,提示过程试图写入的管道不存在(三种解决办法)

vscode报错如下&#xff1a; 一、第一种情况 原因是本地的known_hosts文件记录服务器信息与现服务器的信息冲突了&#xff0c;导致连接失败。 解决方案就是把本地的known_hosts的原服务器信息全部删掉&#xff0c;然后重新连接。 二、第二种情况 在编写配置文件config时&…

RequestRespons

文章目录 Request&Respons1 Request和Response的概述2 Request对象2.1 Request继承体系2.2 Request获取请求数据2.2.1 获取请求行数据2.2.2 获取请求头数据2.2.3 获取请求体数据2.2.4 获取请求参数的通用方式 2.3 IDEA快速创建Servlet2.4 请求参数中文乱码问题2.4.1 POST请…

stable diffusion基础

整合包下载&#xff1a;秋叶大佬 【AI绘画8月最新】Stable Diffusion整合包v4.2发布&#xff01; 参照&#xff1a;基础04】目前全网最贴心的Lora基础知识教程&#xff01; VAE 作用&#xff1a;滤镜微调 VAE下载地址&#xff1a;C站&#xff08;https://civitai.com/models…

Oracle将与Kubernetes合作推出DevOps解决方案!

导读Oracle想成为云计算领域的巨头&#xff0c;但它不是推出自己品牌的云DevOps软件&#xff0c;而是将与CoreOS在Kubernetes端展开合作。七年前&#xff0c;Oracle想要成为Linux领域的一家重量级公司。于是&#xff0c;Oracle主席拉里埃利森&#xff08;Larry Ellison&#xf…