【FreeRTOS】——列表与列表项列表相关API函数(初始化、插入、移除)

news2025/1/4 17:13:09

目录

前言:

一、列表与列表项

二、列表相关API函数

①初始化列表vListInitialise()

②初始化列表项vListInitialise()

③列表插入列表项(升序)函数vListInsert()

④列表插入列表项(无序)函数vListInsertEnd()

⑤移除列表项uxListRemove()函数

总结:


前言:

博客笔记根据B站视频教程编辑,仅供学习交流使用!

一、列表与列表项

列表:FreeRTOS 中的一个数据结构,概念上和链表类似,列表被用来跟踪 FreeRTOS中的任务

列表项:存放在列表中的项目。

列表相当于链表,列表项相当于节点,FreeRTOS 中的列表是一个双向环形链表

      

列表特点:列表项间的地址非连续的,是人为的连接到一起的列表项:数目是由后期添加的个数决定的,随时可变可随时删除和插入新的列表项。

数组的特点:数组成员地址是连续的,数组在最初确定了成员数量后期无法改变。

OS中任务的数量是不确定的,并且任务状态是会发生改变的,所以非常适用列表(链表)这种数据结构!

①FreeRTOS的源码中的list.h和list.c中存了有关列表的内容,list.h中列表的相关结构体:

typedef struct xLIST
{
    	listFIRST_LIST_INTEGRITY_CHECK_VALUE			/* 校验值 */
    	volatile UBaseType_t uxNumberOfItems;			/* 列表中的列表项数量 */
   	ListItem_t * configLIST_VOLATILE pxIndex			/* 用于遍历列表项的指针 */
    	MiniListItem_t xListEnd					/* 末尾列表项 */
    	listSECOND_LIST_INTEGRITY_CHECK_VALUE		/* 校验值 */
} List_t;


//首位两个校验值是两个宏,已知常量,通过它们判断列表数据运行过程是否遭到破坏,一般用于调试,默认不开启
//uxNumberOfItems,用于记录列表中列表项的个数(不包含 xListEnd)
//pxIndex用于指向列表中的某个列表项,一般用于遍历列表中所有列表项
//xListEnd是一个迷你列表项,排在最末尾

② list.h中列表项的相关结构体:

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指向列表项所在列表(就绪、阻塞、挂起)

迷你列表项

也是列表项,但仅用于标记列表的末尾挂载其他插入列表中的列表项

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; 		/* 下一个列表项 */
};

//xItemValue,pxNext,pxPrevious与普通列表项相同
//由于其功能特点,不需要pxOwner和pxContainer,节省了内存开销

 列表与列表项关系(列表初始状态和即将插入的两个列表项):


二、列表相关API函数

①初始化列表vListInitialise()

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

//注意:->和.都可用于访问结构体的成员,但.操作结构体变量本身(跟在变量本身后面),
//而->操作的是结构体变量的指针(地址)

②初始化列表项vListInitialise()

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 );
    //数据完整性校验值
} 

③列表插入列表项(升序)函数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 )
 	{ 
		pxIterator = pxList->xListEnd.pxPrevious; 				/* 插入的位置为列表 xListEnd 前面 */ 
	} 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 )++;							/* 更新列表中列表项的数量 */ 
}

如下示例:一次插入列表项值为40,60,50的列表项:

④列表插入列表项(无序)函数vListInsertEnd()

用于将待插入列表的列表项插入到列表 pxIndex 指针指向的列表项前面,是一种无序的插入方法

void vListInsertEnd (  List_t * const pxList ,   ListItem_t * const pxNewListItem  )
{
	 //省略部分非关键代码 … …
	/* 获取列表 pxIndex 指向的列表项 */
    ListItem_t * const pxIndex = pxList->pxIndex;	
    /* 更新待插入列表项的指针成员变量 */	
    pxNewListItem->pxNext = pxIndex;
    pxNewListItem->pxPrevious = pxIndex->pxPrevious;
    /* 更新列表中原本列表项的指针成员变量 */
    pxIndex->pxPrevious->pxNext = pxNewListItem;	
    pxIndex->pxPrevious = pxNewListItem;
    /* 更新待插入列表项的所在列表成员变量 */
    pxNewListItem->pxContainer = pxList;
    /* 更新列表中列表项的数量 */
    ( pxList->uxNumberOfItems )++;
} 

假设初始列表pxIndex指向末尾列表,此时插入列表项值为30的列表项:

 

假设初始列表pxIndex指向值为40的列表项,此时插入列表项为30的列表项:

⑤移除列表项uxListRemove()函数

UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) 
{
	List_t * const pxList = pxItemToRemove->pxContainer; 
    //从列表中移除列表项(即更换被移除项前后两项的指针指向):
	pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
	pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; 	
    //如果pxIndex正指向待移除的列表项,需要将pxIndex指向待移除项的上一个列表项
	if( pxList->pxIndex == pxItemToRemove ) 
	{
	 	pxList->pxIndex = pxItemToRemove->pxPrevious;
	} else 
	{ 
		mtCOVERAGE_TEST_MARKER(); 
	} 
    //将待移除项所在的列表指针清空
	pxItemToRemove->pxContainer = NULL; 
    //更新列表中列表项的数量
	( pxList->uxNumberOfItems )--; 
    //返回移除后列表中列表项的数量
	return pxList->uxNumberOfItems; 
}

如下示例移除列表项2:

总结:

FreeRTOS是一个开源的实时操作系统,适用于低成本、低功耗的嵌入式系统。它具有高度可移植性和可扩展性,并支持多种处理器架构和编程语言! 广泛用于汽车电子中的实时控制系统,如发动机管理、制动系统、转向系统等。控制和监视工业自动化过程中的各个部分,如机器人和生产线。开发路由器、交换机、调制解调器和其他网络设备等通信设备。医疗设备需要快速响应并保持高度可靠性,因此FreeRTOS也在这个领域得到了广泛应用,如心脏起博器、血压计、呼吸机等。

往期精彩:

电机应用控制——直流无刷电机

OpenCV机器视觉系列专栏

C语言进阶

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

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

相关文章

开源赋能 普惠未来——回顾全球数字经济大会及开放原子全球开源峰会(Intel专题)

一、峰会背景 2023年6月11日至13日&#xff0c;中国北京迎来了一场全球数字经济大会和开放原子全球开源峰会的盛会。这次大会在北京北人亦创国际会展中心隆重举行&#xff0c;为来自世界各地的数字经济和开源社区的代表们提供了一个共同交流、合作的平台。 本次大会以"开…

GAMES101笔记 Lecture02 线性代数基础

目录 A Swift and Brutal Introduction to Linear AlgebraGarphics Dependencies(图形学的依赖)Basic mathematics(基础的数学)Basic physics(基础的物理)Misc(杂项)And a bit of asethetics(以及一点美学) Vectors(向量)Vector Normalization(向量归一化)Vector Addition(向量…

记录好项目D7

记录好项目 你好呀&#xff0c;这里是我专门记录一下从某些地方收集起来的项目&#xff0c;对项目修改&#xff0c;进行添砖加瓦&#xff0c;变成自己的闪亮项目。修修补补也可以成为毕设哦 本次的项目是个酒店预订管理系统 技术栈&#xff1a;springbootjavamysqlmybatis …

从0到1学会在Linux中部署SpringBoot+Vue前后端分离项目

1.打包Vue前端项目 使用npm run build命令打包前端项目 前端项目会 打包到dist文件夹中 2.打包SpringBoot后端项目 点击生命周期的package命令&#xff0c;对后端项目进行打包 target目录下的renren-fast.jar就是刚刚打包的后端项目 后端打包项目有一个小技巧&#xff0c;就…

基于VUE3+Layui从头搭建通用后台管理系统(前端篇)一:项目规划及初始化

一、项目内容 使用vue3+Layui实现通用管理系统前端,使用vue3+layui搭建系统UI界面,使用nodejs搭建模拟web服务器,使用echarts实现系统可视化模块,可以此项目为基础进行扩展开发,快速搭建管理系统,具体内容如下:   1. 常见功能实现: 实现用户登录(用户名密码登录、手…

【c语言】 -- 详解数组篇

&#x1f4d5;博主介绍&#xff1a;目前大一正在学习c语言&#xff0c;数据结构&#xff0c;计算机网络。 c语言学习&#xff0c;是为了更好的学习其他的编程语言&#xff0c;C语言是母体语言&#xff0c;是人机交互接近底层的桥梁。 本章来学习数据的存储。 让我们开启c语言学…

XSS测试-业务安全测试实操(11)

XSS测试 测试原理和方法 跨站脚本漏洞是Web应用程序在将数据输出到网页的时候存在问题,导致恶意攻击者可以往Web页面里插入恶意JavaScript、HTML代码,并将构造的恶意数据显示在页面的漏洞中。攻击者一般利用此漏洞窃取或操纵客户会话和 Cookie,用于模仿合法用户,从而使攻击…

CVE-2010-2883-PDF漏洞提权复现过程

第二步&#xff0c;打开Kali Linux渗透机使用命令msfconsole进入Metasploit渗透测试平台&#xff0c;使用模块adobe_cooltype_sing生成木马文件。 输入search adobe_cooltype_sing命令搜索Adobe渗透模块 与漏洞相关的模块有两个&#xff0c;编号为0的模块是使用本地的服务器挂…

项目实战:防刷

你好&#xff0c;我是田哥 最近在搞充电桩项目&#xff0c;用户使用短信验证码形式进行注册和登录&#xff0c;那么问题来了&#xff1f; 分布式微服务项目实战&#xff1a;充电桩项目 实战分布式事务【SeataSpring Cloud】 项目实战&#xff1a;自定义异常和统一参数验证&…

lazarus开发:快速读写excel文件的神奇控件——FPSpreadsheet

目录 1 简介 2 用wps制作一个简单的工资表 3 编译一下自带的演示程序 1 简介 FPSpreadsheet是一个功能强大的控件库&#xff0c;用于读取和写入电子表格文件。使用该控件库开发的软件&#xff0c;能够在不安装电子表格应用程序的情况下&#xff0c;快速读出、写入电子表格文…

详解Hystrix

目录 1.微服务中的容错 1.1.服务雪崩 1.2.解决办法 2.hystrix 2.1.概述 2.2.项目结构及依赖 2.3.代码示例 2.3.1.注册中心 2.3.2.服务调用者 2.3.3.服务提供者 2.4.服务降级 2.4.1.单点响应 2.4.2.默认响应 2.4.3.前置响应 2.5.服务熔断 2.5.1.概述 2.5.2.使用…

【C语言复习】第一篇、关于我的C语言的复习路线

目录 第一部分、前言 第二部分、学习视频 第三部分、我的建议 第一部分、前言 首先想谈一下为啥都读研究生的我还在学习C语言&#x1f602;&#xff0c;说起来我认为挺搞笑的&#xff0c;一句话解释就是&#xff1a;本科上课的时候&#xff0c;耳朵打苍蝇去&#xff0c;哈哈。…

面向快速反应的工程团队--QRF团队模型

很多团队都纠结于产品业务需求和各种不断插入的中断请求而无法自拔&#xff0c;这篇文章介绍了QRF团队模型&#xff0c;将产品业务开发和紧急响应团队区分开&#xff0c;为重要而紧急的事情提供单独的处理通道&#xff0c;从而帮助团队能够聚焦在重要的事情上。原文&#xff1a…

Nucleo-F411RE (STM32F411)LL库体验 7 - 低功耗(睡眠、待机)

Nucleo-F411RE &#xff08;STM32F411&#xff09;LL库体验 7 - 低功耗&#xff08;睡眠&#xff09; 1、简述 F411有三种模式 Sleep mode、stop mode 、standby mode。 其中SleepMode 、Stop Mode 可选择WFI 以及WFE&#xff0c;两者的区别在于&#xff0c;前者任何中断都能…

编译原理笔记(哈工大编译原理)

文章目录 前言概论语言与文法基本概念字母表串字母表与串的联系 文法语言推导和规约句型与句子语言与字母表 文法的分类 前言 说实话&#xff0c;我不是很想上这门课&#xff0c;确实没什么大用&#xff0c;虽然我觉得这门课学一学也挺好&#xff0c;但是我觉得弄8个大实验就真…

socket地址的通配符地址、环回地址

今天在写ServerSocket的时候&#xff0c;遇到了socket地址的通配符地址、环回地址。 package com.thb;import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket;public class ServerSocketMain {public static void main(String[] args) {try…

UI Tool Kit 使用

Unity 2021 已经把UIBuilder 内置了&#xff0c;项目组也打算 后续工具采用 toolkit来写&#xff0c;这边也是找了一下教程熟悉了一下。 UI 工具包 - Unity 手册 首先 先创建一个EditorWindow 会生成相应的C#&#xff0c;UXML,USS代码 默认会把显示的MenuItem代码生成&#xf…

记录--设计一个可选择不连续的时间范围的日期选择器

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 npm包&#xff1a;sta-datepicker效果图 需求 普通的时间选择器要么只能单选&#xff0c;要么只能选范围&#xff0c;不可以随意选择若干个时间&#xff0c;同时大多数现成的时间选择器选择结束会收起…

EasyExcel实战与笔记

概述 Excel导入导出是业务开发中非常常见的需求。本文记录一下如何快速入门使用EasyExcel&#xff0c;深度实战&#xff0c;以及遇到的问题。 入门 使用EasyExcel导入如下依赖即可&#xff1a; <dependency><groupId>com.alibaba</groupId><artifactI…