FreeRTOS内核——数据结构链表

2023-05-16

1.数据结构

1.1 list与list item

也就是c语言中的链表与链表结点

单项链表很少用,多用双向链表

1.1.1 list (List_t)

list就是一串链表,具体来说就是这一串链表的头结点。因此,一个list对象就代表着一串链表,通过它可以找到这一串链表中的每一个结点

结构体定义如下:

typedef struct xLIST
{	
	UBaseType_t uxNumberOfItems;		/*链表结点计数器*/
	ListItem_t * pxIndex;				/*链表结点索引地址*/
	MiniListItem_t xListEnd;			/*链表最后一个结点*/

} List_t

1.1.2 list item (ListItem_t)

所谓item就是链表中每一个结点的结构体

struct xLIST_ITEM
{
	TickType_t xItemValue;						/* 辅助值,用于结点进行顺序排列  */
	struct xLIST_ITEM *  pxNext;				/* 指向链表下一个节点 */
	struct xLIST_ITEM *  pxPrevious;			/* 指向链表上一个结点 */
	void * pvOwner;								/* 指向拥有该节点的内核对象,通常是TCB */
	void * pvContainer							/* 指向该节点所在的链表 */
}

1.2 链表的相关操作

1.2.1 链表节点初始化 vListInitialiseItem()

void vListInitialiseItem( ListItem_t * const pxItem )
{
	pxItem->pvContainer = NULL;
}

1.2.2 链表根节点初始化 vListInitialise()

void vListInitialise( List_t * const pxList )
{
	/* 将链表索引指向最后一个节点 */
	pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );

	/* 将链表最后一个节点的辅助排序值设置为最大,确保该节点就是链表的最后节点 */
	pxList->xListEnd.xItemValue = portMAX_DELAY;

	/* 将链表的最后一个结点的pxNext和pxPrevious指针均指向节点自身,表示链表为空 */
	pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );	
	pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );
	
	/* 初始化链表结点计数器的值为0,表示链表为空 */
	pxList->uxNumberOfItems = ( UBaseType_t ) 0U;

}

1.2.3 节点尾插法插入链表 vListInsertEnd()

void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{
	ListItem_t * const pxIndex = pxList->pxIndex;

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

   /* Remember which list the item is in. */
   pxNewListItem->pvContainer = ( void * ) pxList;

   ( pxList->uxNumberOfItems )++;
}

1.2.4 节点升序插入链表 vListInsert()

void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
{
	ListItem_t *pxIterator;			/* 迭代指针 */
	/* 获取节点的辅助排序值 */
	const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
	/* 寻找节点要插入的位置 */
	if( xValueOfInsertion == portMAX_DELAY )
	{
		pxIterator = pxList->xListEnd.pxPrevious;
	}
	else
	{
	/* 不断迭代,找到节点要插入的位置 ,因为链表的最后一个节点的pxNext永远指向第一个节点 */
		for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) 
		{
			/* There is nothing to do here, just iterating to the wanted
			insertion position. */
		}
	}
	/* 将节点插入 */
	pxNewListItem->pxNext = pxIterator->pxNext;
	pxNewListItem->pxNext->pxPrevious = pxNewListItem;
	pxNewListItem->pxPrevious = pxIterator;
	pxIterator->pxNext = pxNewListItem;

	/* Remember which list the item is in.  This allows fast removal of the
	item later. */
	pxNewListItem->pvContainer = ( void * ) pxList;

	( pxList->uxNumberOfItems )++;
}

1.2.5 将节点从链表中删除 uxListRemove()

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;

	/* 调整链表的索引指针 Make sure the index is left pointing to a valid item. */
	if( pxList->pxIndex == pxItemToRemove )
	{
		pxList->pxIndex = pxItemToRemove->pxPrevious;
	}
	/* 初始化该节点所在的链表为空,表示节点还没有插入任何链表*/
	pxItemToRemove->pvContainer = NULL;
	
	/* 更新链表节点计数器 */
	( pxList->uxNumberOfItems )--;
	
	/* 返回立案表中剩余节点的个数 */
	return pxList->uxNumberOfItems;
}

1.2.6 节点带参宏函数

1.2.6.1 初始化节点拥有者
#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner )		( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )
1.2.6.2 获取节点拥有者
#define listGET_LIST_ITEM_OWNER( pxListItem )	( ( pxListItem )->pvOwner )
1.2.6.3 初始化节点排序辅助值
#define listSET_LIST_ITEM_VALUE( pxListItem, xValue )	( ( pxListItem )->xItemValue = ( xValue ) )
1.2.6.4 获取节点排序辅助值
#define listGET_LIST_ITEM_VALUE( pxListItem )	( ( pxListItem )->xItemValue )
1.2.6.5 获取链表根节点的节点计数器的值
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList )	( ( ( pxList )->xListEnd ).pxNext->xItemValue )
1.2.6.6 获取链表的入口节点
#define listGET_HEAD_ENTRY( pxList )	( ( ( pxList )->xListEnd ).pxNext )
1.2.6.7 获取节点的下一个节点
#define listGET_NEXT( pxListItem )	( ( pxListItem )->pxNext )
1.2.6.8 获取链表的最后一个节点
#define listGET_END_MARKER( pxList )	( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )
1.2.6.9 判断链表是否为空
#define listLIST_IS_EMPTY( pxList )	( ( BaseType_t ) ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) )
1.2.6.10 获取链表节点数
#define listCURRENT_LIST_LENGTH( pxList )	( ( pxList )->uxNumberOfItems )
1.2.6.11 获取链表第一个节点的OWNER即TCB
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )										\
{																							\
List_t * const pxConstList = ( pxList );													\
	/* Increment the index to the next item and return the item, ensuring */				\
	/* we don't return the marker used at the end of the list.  */							\
	( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;							\
	if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) )	\
	{																						\
		( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;						\
	}																						\
	( pxTCB ) = ( pxConstList )->pxIndex->pvOwner;											\
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS内核——数据结构链表 的相关文章

  • FreeRTOS内核配置说明---FreeRTOS Kernel V10.2.1

    FreeRTOS内核是高度可定制的 使用配置文件FreeRTOSConfig h进行定制 每个FreeRTOS应用都必须包含这个头文件 用户根据实际应用来裁剪定制FreeRTOS内核 这个配置文件是针对用户程序的 而非内核 因此配置文件一般
  • FreeRTOS config开始的宏

    FreeRTOSConfig h系统配置文件中可以自定义 FreeRTOS h中定义默认值 configAPPLICATION ALLOCATED HEAP 默认情况下FreeRTOS的堆内存是由编译器来分配的 将宏configAPPLIC
  • STM32F103移植FreeRTOS必须搞明白的系列知识---3(堆栈)

    STM32F103移植FreeRTOS必须搞明白的系列知识 1 Cortex CM3中断优先级 STM32F103移植FreeRTOS必须搞明白的系列知识 2 FreeRTOS任务优先级 STM32F103移植FreeRTOS必须搞明白的系
  • STM32CubeMX+FreeRTOS学习笔记(一)

    嵌入式实时操作系统FreeRTOS 基本概述 在嵌入式领域当中 实时操作系统的应用越来越广泛了 目前嵌入式操作系统种类很多 例如 Clinux C OS II C OS III FreeRTOS RT Thread等等 这篇文章所记录的就是
  • 单链表的插入操作(全)

    1 在指定位序插入数据第一步 主要执行操作 查找 先查找所要插入位置的前一个元素 具体方法 根据链表的特点 每一个节点都需要一个数据域和指针域 所以只需从头节点遍历到所要插入数据的的前一个节点即可 后面的showList函数也用的这种方法第
  • FreeRTOS软件定时器创建、复位、开始和停止(备忘)

    目录 一 简介 1 1 开发环境 1 2 摘要 二 STM32CubeIDE配置 三 创建定时器 3 1 头文件声明 3 2 工程文件定义 3 3 创建定时器 3 4 开启 复位 和关闭定时器 四 定时器回调函数 一 简介 1 1 开发环境
  • 解决错误“ #error “include FreeRTOS.h“ must appear in source files before “include event_groups.““例子分享

    今天来给大家分享一下 关于之前自己在学习FreeRTOS过程中遇到的一个错误提示 话不多说 我们直接来看 错误分析 首先 我们看一下错误的提示 error 35 error directive include FreeRTOS h must
  • STM32移植FreeRTOS的Tips

    转自 http bbs armfly com read php tid 7140 1 在FreeRTOS的demo文件夹中拷贝对应的FreeRTOSConfig h文件后 需要加入一行 define configUSE MUTEXES 1
  • 【FreeRTOS】队列的使用

    作者主页 凉开水白菜 作者简介 共同学习 互相监督 热于分享 多加讨论 一起进步 专栏资料 https pan baidu com s 1nc1rfyLiMyw6ZhxiZ1Cumg pwd free 点赞 收藏 再看 养成习惯 订阅的粉丝
  • FreeRTOS记录(九、一个裸机工程转FreeRTOS的实例)

    记录一下一个实际项目由裸机程序改成FreeRTOS 以前产品的平台还是C8051单片机上面的程序 硬件平台改成了STM32L051 同时使用STM32CubeMX生成的工程 使用FreeRTOS系统 EEPROM数据存储读取函数修改更新 2
  • FreeRTOS:中断配置

    目录 一 Cortex M 中断 1 1中断简介 1 2中断管理简介 1 3优先级分组定义 1 4优先级设置 1 5用于中断屏蔽的特殊寄存器 1 5 1PRIMASK 和 FAULTMASK 寄存器 1 5 2BASEPRI 寄存器 二 F
  • FreeRTOS临界段和开关中断

    http blog sina com cn s blog 98ee3a930102wg5u html 本章教程为大家讲解两个重要的概念 FreeRTOS的临界段和开关中断 本章教程配套的例子含Cortex M3内核的STM32F103和Co
  • FreeRTOS基础五:软件定时器

    软件定时器简介 软件定时器的作用 在指定的时间到来时执行指定的函数 或者以某个频率周期性地执行某个函数 被执行的函数叫做软件定时器回调函数 软件定时器由FreeRTOS内核实现 不需要硬件支持 软件定时器只有在软件定时器回调函数被调用时才需
  • FreeRTOS之软件定时器

    FreeRTOS之软件定时器 声明 本人按照正点原子的FreeRTOS例程进行学习的 欢迎各位大佬指责和批评 谢谢 include sys h include delay h include usart h include led h in
  • FreeRTOS笔记(十)中断

    中断 当CPU在执行某一事件A时 发生另外一个更重要紧急的事件B请求CPU去处理 产生了中断 于是CPU暂时中断当前正在执行的事件A任务而对对事件B进行处理 CPU处理完事件B后再返回之前中断的位置继续执行原来的事件A 这一过程统称为中断
  • FreeRTOS笔记(二)

    FreeRTOS笔记 二 静态任务 文章目录 FreeRTOS笔记 二 静态任务 一 任务定义 二 任务创建 2 1 定义任务栈 2 2 定义任务函数 2 3 定义任务控制块 2 4 实现任务创建函数 三 实现就绪列表 3 1 定义就绪列表
  • FreeRTOS实时操作系统(三)任务挂起与恢复

    系列文章 FreeRTOS实时操作系统 一 RTOS的基本概念 FreeRTOS实时操作系统 二 任务创建与任务删除 HAL库 FreeRTOS实时操作系统 三 任务挂起与恢复 FreeRTOS实时操作系统 四 中断任务管理 FreeRTO
  • FreeRTOS之系统配置

    1 FreeRTOS的系统配置文件为FreeRTOSConfig h 在此配置文件中可以完成FreeRTOS的裁剪和配置 在官方的demo中 每个工程都有一个该文件 2 先说一下 INCLUDE 开始的宏 使用 INCLUDE 开头的宏用来
  • 防止GCC LTO删除函数

    我使用 GCC ARM Embedded 和 FreeRTOS FreeRTOS具有的功能vTaskSwitchContext 仅在某些情况下使用 内联汇编代码 问题是 当我使用LTO时 GCC不考虑内联汇编代码并认为该函数没有被使用 因此
  • 有关 CMake 错误的问题:没有为目标提供源

    我正在尝试使用 cmake 和 eclipse 将 FreeRtos 添加到我的项目中 但出现错误 我运行的是 debian 10 我的 cmake 版本是 3 13 4 cmake 的文件可以在以下位置找到这个 git 仓库 https

随机推荐

  • Go实现分布式锁

    Go分布式锁 目录 Go分布式锁进程内加锁trylock基于 redis 的 setnx基于 zk基于 etcdredlock如何选择 在单机程序并发或并行修改全局变量时 xff0c 需要对修改行为加锁以创造临界区 为什么需要加锁呢 xff
  • Golang实习蓝湖二面

    蓝湖二面 自我介绍 问题 casbin的策略 ACL RBAB ABAC 他们的区别和应用 JWT的实现 JWT和传统的token有什么区别 三次握手和四次挥手 time wait 为什么需要等待2MSL 什么是完全二叉树 完全二叉树有什么
  • export、import、commit、save、load的区别

    目录 1 docker export 和 docker import2 docker commit3 docker save 和 docker load 1 docker export 和 docker import docker expo
  • docker搭建redis集群模式

    目录 docker 安装redis1 创建redis conf开启redis验证 开启密码 允许redis外地连接后台启动开启redis持久化 2 启动redis容器3 进入容器 redis集群3主3从1 新建6个redis容器2 构建主从
  • SONiC+P4实践——P4Runtime下发ACL表项

    转载请表明出处 注 xff1a SONiC系统为vs版本 Part1 xff1a 实现外部宿主机与SONiC的网络连通 步骤 1 xff1a 打开一个ubuntu系统安装kvm及其依赖 xff08 1 xff09 查看CPU是否支持虚拟化
  • BDD100K自动驾驶数据集格式转YOLO格式

    说明 xff1a 为了用BDD100K数据集训练YOLOV5模型 xff0c 首先需要将BDD100K数据集格式转成YOLOV5支持的输入格式 转换代码如下 xff1a 一 BDD100K转YOLO格式 usr bin env python
  • 全局代理-WINDOWS怎么设置全局代理?

    https blog 51cto com u 15275599 2923545 WINDOWS设置全局代理可以通过以下4个步骤操作来实现 xff1a 1 点击开始菜单 xff0c 然后点击setting xff08 设置 xff09 xff
  • Easyexcle导入导出

    一 导入 1 依赖 lt excel gt lt dependency gt lt groupId gt com alibaba lt groupId gt lt artifactId gt easyexcel lt artifactId
  • Springboot+(linux)redis哨兵模式实现

    下面是主从redis服务 6379主6380从16381从2 下面是多个哨兵 26379哨兵126380哨兵226381哨兵3 windows下redis压缩包 xff08 本文使用的是5 0 13 xff09 Redis xff08 点我
  • 记一次springboot2.1.6配置(mysql)多数据源

    pom xml lt xml version 61 34 1 0 34 encoding 61 34 UTF 8 34 gt lt project xmlns 61 34 http maven apache org POM 4 0 0 34
  • 小车跟随行驶系统(基于MSP-EXP430F5529LP系统板)

    选用材料 xff1a 主控板MSP EXP430F5529LP 陀螺仪 直流减速电机 xff08 可以选用光电编码器 xff0c 霍尔电机不好调节PID xff09 TB6612电机驱动 超声波测距模块 灰度传感器 无线透传 蓝牙模块 xf
  • 使用sheetjs读取excle表格

    span class token comment cdn引入js span span class token operator lt span script lang span class token operator 61 span sp
  • js的六种继承方式

    1 原型链继承 核心 xff1a 将父类的实例作为子类的原型 span class token keyword function span span class token function Parent1 span span class
  • 代理服务器的学习

    一 代理服务器和VPN 1 工作原理 xff08 1 xff09 代理的工作原理是 xff1a 由代理服务器自己去访问你的目标网站 xff0c 并加载它的内容 xff0c 然后再把这些加载过的内容传递到你的窗口上 这样就相当于你在浏览目标网
  • MyBatisPlus(基于starter和Bean方式)

    文章目录 基于boot starter方式基于Bean方式 基于boot starter方式 1 microboot项目 修改配置文件 xff0c 引入所需要的相关依赖库 dependences gradle ext span class
  • web前端开发常用浏览器介绍及运行配置

    1 web前端开发常用浏览器介绍 浏览器是用来检索展示以及传递web信息的应用程序 xff0c 市面上比较常见的浏览器有IE浏览器 火狐浏览器 谷歌浏览器 Safari浏览器和欧朋浏览器等 xff0c 其中IE 火狐和谷歌是目前互联网上的三
  • 数据集格式--图像--目标检测

    一 项目数据集介绍 xff1a 1 COCO数据集 xff1a coco2017 有80个类别 包含交通信号灯和交通标志 红绿灯信号灯没有颜色属性标签 COCO数据集JSON文件格式 xff0c 主要有以下五个键字段 xff1a span
  • elasticsearch排错指南(各种错误~)

    博主在学习es的时候 xff0c 遇到了很多错误 xff0c 这里列举安装时的错误 一 can not run elasticsearch as root 如上图 xff0c 代表不能使用root用户运行es xff0c 这是es的开发团队
  • Ubuntu下的SD卡分区操作(制作Linux启动文件)

    最近在使用SD卡制作Linux启动文件时 xff0c 要进行SD卡的分区操作 总结了主要的流程 xff0c 操作步骤如下 xff1a 1 插入SD卡并挂载到Ubuntu下 xff0c 输入以下命令查看SD卡挂载信息 sudo fdisk l
  • FreeRTOS内核——数据结构链表

    1 数据结构 1 1 list与list item 也就是c语言中的链表与链表结点 单项链表很少用 xff0c 多用双向链表 1 1 1 list List t list就是一串链表 xff0c 具体来说就是这一串链表的头结点 因此 xff