FreeRTOS实时操作系统的列表与列表项操作示例

目录
  • 前言
  • 列表项数据结构
  • 列表项初始化
  • 列表数据结构
  • 将列表项按照升序排列插入到列表
  • 将列表项从列表删除

前言

FreeRTOS列表与列表项其实就是链表和节点,在list.clist.h实现

列表项数据结构

//列表项数据结构
typedef struct xLIST_ITEM
{
	TickType_t xItemValue;  //辅助值,用作节点做顺序排序
	struct xLIST_ITEM * pxNext;//后继指针
	struct xLIST_ITEM * pxPrevious;//前驱指针
	void * pvOwner;      //指向拥有该列表项的内核对象,通常是TCB
	void * pvContainer;  //指向该列表项所在的列表
}ListItem_t;

列表项初始化

void vListInitialiseItem(ListItem_t * const pxItem)
{
//初始化该列表项所在列表指针指向NULL,表示还没插入任何列表
		pxItem->pvContainer = NULL;
}

列表数据结构

typedef struct xLIST
{
	UBaseType_t uxNumberOfItems; //指示这条列表上有多少个列表项
	ListItem_t * pxIndex; //列表项索引指针
	MiniListItem_t xListEnd; //列表最后一个列表项
}List_t;

其中MiniListItem_t数据结构如下

typedef struct xMINI_LIST_ITEM
{
	TickType_t xItemValue;//辅助值,用作节点做顺序排序
	struct xLIST_ITEM * pxNext;//后继指针
	struct xLIST_ITEM * pxPrevious;//前驱指针
}MiniListItem_t;

可以看到是列表项数据结构去掉了pvOwnerpvContainer成员

列表初始化

void vListInitialise(List_t * const pxList)
{
	//列表索引指向最后一个节点
	pxList->pxIndex = (ListItem_t *) &(pxList->xListEnd);
	//将列表最后一个节点辅助值设置为最大,确保该节点是最后节点
	pxList->xListEnd.xItemValue = portMAX_DELAY;
	//将最后一个节点的前驱和后继指针指向自己,表示列表此时为空
	pxList->xListEnd.pxNext     = (ListItem_t*) &(pxList->xListEnd);
	pxList->xListEnd.pxPrevious = (ListItem_t*) &(pxList->xListEnd);
	//表示此时列表中有0个列表项
	pxList->uxNumberOfItems = (UBaseType_t)0U;
}

如下图

将列表项插入列表尾部

void vListInsertEnd(List_t * const pxList,ListItem_t * const pxNewListItem)
{
    //取列表项索引指针,此时该指针指向最后一个节点
	ListItem_t * const pxIndex = pxList->pxIndex;
	//新插入的列表项前驱指针指向最后一个节点
	pxNewListItem->pxNext = pxIndex;
	//新插入的列表项的后继指针也指向最后一个节点
	pxNewListItem->pxPrevious = pxIndex->pxPrevious;
	//列表的最后一个节点的后继指针指向新插入的列表项
	pxNewListItem->pxPrevious->pxNext = pxNewListItem;
	//列表的最后一个节点的前驱指针也指向新插入的列表项
	pxIndex->pxPrevious = pxNewListItem;
	//新插入的列表项是输入该列表的
	pxNewListItem->pvContainer = (void*) pxList;
	 //该列表中列表项数目+1
	(pxList->uxNumberOfItems)++;
}

如下

将列表项按照升序排列插入到列表

假如向现有的2个列表项序辅助值分别是 1 和 3的列表插入辅助值是2个列表项

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
	{
			for(pxIterator = (ListItem_t*) &(pxList->xListEnd);
		      pxIterator->pxNext->xItemValue <=xValueOfInsertion ;
		      pxIterator = pxIterator->pxNext)
			{
			}
	}
	//对于下图此时pxIterator指向List_item1
	//此时pxIterator->pxNext是List_item3地址
	pxNewListItem->pxNext = pxIterator->pxNext;//1
	//pxNewListItem->pxNext->pxPrevious是item3的前驱指针指向新列表项item2
	pxNewListItem->pxNext->pxPrevious = pxNewListItem;
	//新列表项item2的前驱指针指向pxIterator即item1
	pxNewListItem->pxPrevious = pxIterator;
	//pxIterator即item1的后继指向新列表项item2
	pxIterator->pxNext = pxNewListItem;
	pxNewListItem->pvContainer = (void*) pxList;
	(pxList->uxNumberOfItems)++;
}

如图,注意2、3步的指针箭头,野火的pdf画的有误

将列表项从列表删除

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;
	if(pxList->pxIndex == pxItemToRemove)
	{
			pxList->pxIndex = pxItemToRemove->pxPrevious;
	}
	//该列表项所有者置空
	pxItemToRemove->pvContainer = NULL;
	(pxList->uxNumberOfItems)--;
	return pxList->uxNumberOfItems;
}

下面是测试代码即仿真结果

List_t List_Test;
ListItem_t List_Item1;
ListItem_t List_Item2;
ListItem_t List_Item3;
int main(void)
{
	//初始化列表
    vListInitialise(&List_Test);
    //初始化列表项
    vListInitialiseItem(&List_Item1);
	List_Item1.xItemValue = 1;
    vListInitialiseItem(&List_Item2);
	List_Item2.xItemValue = 2;
    vListInitialiseItem(&List_Item3);
	List_Item3.xItemValue = 3;
    vListInsert(&List_Test,&List_Item1);
	vListInsert(&List_Test,&List_Item3);
	vListInsert(&List_Test,&List_Item2);
	while(1);
}

以上就是FreeRTOS实时操作系统的列表与列表项操作示例的详细内容,更多关于FreeRTOS列表与列表项操作的资料请关注我们其它相关文章!

(0)

相关推荐

  • 使用FreeRTOS遇到死等异常的解决

    目录 问题场景: 追溯代码: 分析代码 问题场景: 在使用apollo3时,调试时发现在ADC中断中一发送信号量就卡住. 追溯代码: 追溯代码发现其实是在ADC中断中调用xQueueGenericSendFromISR就卡住,卡住位置如下 这个宏定义如下 继续往里看,发现卡在下面位置 此断言如下 所以打印看到的条件是0>=128,所以就while(1);卡在这里了 分析代码 这是获得ipsr寄存器的值,保存在ulCurrentInterrupt变量,那ipsr寄存器代表的是什么呢,这里有写htt

  • FreeRTOS实时操作系统Cortex-M内核使用注意事项

    前言 在阅读本文之前,有两个定义在FreeRTOSConfig.h中的宏,你必须先明白它们是什么意思,<FreeRTOS内核配置说明>一文中,讲解了这两个宏: configKERNEL_INTERRUPT_PRIORITY configMAX_SYSCALL_INTERRUPT_PRIORITY FreeRTOS与Cortex-M内核可谓是绝配,以至于让移植和使用FreeRTOS都变得更简单起来.根据FreeRTOS官方反馈,在Cortex-M内核上使用FreeRTOS大多数的问题点是由不正确

  • FreeRTOS实时操作系统的任务应用函数详解

    目录 1.获取任务系统状态 1.1函数描述 1.2参数描述 1.3返回值 1.4用法举例 2.获取当前任务句柄 2.1函数描述 2.2返回值 3.获取空闲任务句柄 3.1函数描述 3.2返回值 4.获取任务堆栈最大使用深度 4.1函数描述 4.2参数描述 4.3返回值 4.4用法举例 5.获取任务状态 5.1函数描述 5.2参数描述 5.3返回值 6.获取任务描述内容 6.1函数描述 6.2参数描述 6.3返回值 7.获取系统节拍次数 7.1函数描述 7.2返回值 8.获取调度器状态 8.1函数

  • FreeRTOS任务控制API函数的功能分析

    目录 1.相对延时 1.1函数描述 1.2参数描述 1.3用法举例 2.绝对延时 2.1函数描述 2.2参数描述 2.3用法举例 3.获取任务优先级 3.1函数描述 3.2参数描述 3.3返回值 3.4用法举例 4.设置任务优先级 4.1函数描述 4.2参数描述 4.3用法举例 5.任务挂起 5.1函数描述 5.2参数描述 5.3用法举例 6.恢复挂起的任务 6.1函数描述 6.2参数描述 7.恢复挂起的任务(在中断服务函数中使用) 7.1函数描述 7.2参数描述 7.3返回值 7.4用法举例

  • FreeRTOS实时操作系统的内核控制示例解析

    目录 前言 1.强制上下文切换宏 2.进入临界区宏 3.退出临界区宏 4.禁止可屏蔽中断宏 5.使能可屏蔽中断宏 6.启动调度器 6.1函数描述 7.停止调度器 7.1函数描述 8.挂起调度器 8.1函数描述 9.恢复被挂起的调度器 9.1函数描述 9.2返回值 9.3用法举例 10.调整系统节拍 10.1函数描述 10.2参数描述 10.3用法举例 前言 内核控制的一些功能需要移植层提供,为了方便移植,这些API函数用宏来实现,比如上下文切换.进入和退出临界区.禁止和使能可屏蔽中断.内核控制函

  • FreeRTOS实时操作系统的任务创建与任务切换

    目录 任务控制块数据结构 任务创建函数 定义就绪表 就绪表初始化 启动调度器 任务切换 任务控制块数据结构 任务控制块数据结构在task.c声明 typedef struct tskTaskControlBlock { volatile StackType_t * pxTopOfStack; //栈顶指针 ListItem_t xStateListItem; //任务节点 StackType_t * pxStack; //任务栈起始地址 char pcTaskName[configMAX_TAS

  • FreeRTOS软件定时器apollo中断状态判断

    问题场景 开发中发现FreeRTOS软件定时器不走了,具体表现在软件定时器中断进不去. 分析问题 观察发现只有在某个任务执行期间,FreeRTOS的软件定时器才会不走,其他任务执行时正常,排查后是此任务的优先级比定时器任务高,且占用时间比较长,导致任务切不出去. 解决问题 在FreeRTOSConfig.h中修改定时器任务优先级为最高解决问题 apollo中断状态判断 在看apollo3 代码时发现下面这个函数 void WsfSetOsSpecificEvent(void) { if(xRad

  • FreeRTOS实时操作系统内核配置说明

    目录 1.configUSE_PREEMPTION 2.configUSE_PORT_OPTIMISED_TASK_SELECTION 3.configUSE_TICKLESS_IDLE 4.configUSE_IDLE_HOOK 5.configUSE_MALLOC_FAILED_HOOK 6.configUSE_TICK_HOOK 7.configCPU_CLOCK_HZ 8.configTICK_RATE_HZ 9.configMAX_PRIORITIES 10.configMINIMAL

  • FreeRTOS实时操作系统空闲任务的阻塞延时实现

    目录 什么是阻塞延时.为什么需要空闲任务 空闲任务的实现 阻塞延时的实现 xTicksToDelay 递减 SysTick初始化 仿真 什么是阻塞延时.为什么需要空闲任务 RTOS中的延时叫阻塞延时,即任务需要延时时,任务会放弃cpu使用权,cpu转而去做其他的事,当任务延时时间到后,任务重新请求获得cpu使用权.但当所有的任务都处于阻塞后,为了不让cpu空闲没事干就需要一个空闲任务让cpu干活. 空闲任务的实现 空闲任务实现和创建普通任务没区别,空闲任务在调用vTaskStartSchedul

  • FreeRTOS实时操作系统的列表与列表项操作示例

    目录 前言 列表项数据结构 列表项初始化 列表数据结构 将列表项按照升序排列插入到列表 将列表项从列表删除 前言 FreeRTOS列表与列表项其实就是链表和节点,在list.c和list.h实现 列表项数据结构 //列表项数据结构 typedef struct xLIST_ITEM { TickType_t xItemValue; //辅助值,用作节点做顺序排序 struct xLIST_ITEM * pxNext;//后继指针 struct xLIST_ITEM * pxPrevious;//

  • FreeRTOS实时操作系统的任务创建和删除

    目录 前言 1.任务创建 1.1函数描述 1.2参数描述 1.3返回值 1.4用法举例 2.任务删除 2.1任务描述 2.2参数描述 前言 在FreeRTOS移植到Cortex-M3硬件平台的文章中,我们已经见过任务创建API,但那篇文章的重点在于如何移植FreeRTOS,本文将重点放在任务的创建和删除API函数上面. 任务创建和删除API函数位于文件task.c中,需要包含task.h头文件. 1.任务创建 1.1函数描述 BaseType_t xTaskCreate( TaskFunctio

  • FreeRTOS实时操作系统的多优先级实现

    目录 如何实现任务多优先级 软件通用方法和硬件指令方法 如何实现任务多优先级 FreeRTOS中,数字优先级越小,逻辑优先级也越小,空闲任务优先级为0.List_t pxReadyTasksLists[configMAX_PRIORITIES]是数组,数组下标代表任务优先级,任务创建是根据设置的任务优先级插入到对应下标的列表根节点上,如下. 要支持多优先级,就是再任务切换时让pxCurrentTCB指向最高优先级的TCB即可,之前时手动再任务1.任务2来回切换,现在问题就是怎么找到优先级最高的就

  • FreeRTOS实时操作系统的内存管理分析

    目录 1.heap_1.c 功能简介: 2.heap_2.c 功能简介: 3.heap_3.c 功能简介: 4.heap_4.c 功能简介: 5.heap_5.c(V8.1.0新增) 前言 本文介绍内存管理的基础知识,详细源码分析见< FreeRTOS内存管理示例分析> FreeRTOS提供了几个内存堆管理方案,有复杂的也有简单的.其中最简单的管理策略也能满足很多应用的要求,比如对安全要求高的应用,这些应用根本不允许动态内存分配的. FreeRTOS也允许你自己实现内存堆管理,甚至允许你同时使

  • FreeRTOS实时操作系统的任务通知方法

    目录 前言 1.发送通知-方法1 1.1函数描述 1.2参数描述 1.3返回值 2.发送通知-方法2 2.1函数描述 2.2参数描述 2.3用法举例 3.获取通知 3.1函数描述 3.2参数描述 3.3返回值 4.等待通知 4.1函数描述 4.2参数描述 4.3返回值 4.4用法举例 5.任务通知并查询 5.1函数描述 5.2参数描述 5.3返回值 前言 注:本文介绍任务通知的基础知识,详细源码分析见FreeRTOS进阶<FreeRTOS高级篇8---FreeRTOS任务通知分析> 每个RTO

  • FreeRTOS实时操作系统的任务概要讲解

    目录 1. 任务和协程(Co-routines) 1.1任务的特性 1.2任务概要 2. 任务状态 3.任务优先级 4.实现一个任务 5.空闲任务和空闲任务钩子(idle task和Idle Task hook) 5.1空闲任务 5.2空闲任务钩子 1. 任务和协程(Co-routines) 应用程序可以使用任务也可以使用协程,或者两者混合使用,但是任务和协程使用不同的API函数,因此在任务和协程之间不能使用同一个队列或信号量传递数据. 通常情况下,协程仅用在资源非常少的微处理器中,特别是RAM

  • Python实现的列表排序、反转操作示例

    本文实例讲述了Python实现的列表排序.反转操作.分享给大家供大家参考,具体如下: 排序: 使用sorted方法和列表的sort方法: sorted方法适用范围更广,sort方法只有列表有. li = [{'a':'23'}, {'a':'12'}] def sort_fun(mp): s = mp['a'] return int(s) print(sorted(li, key = sort_fun, reverse = True)) #这会返回一个排好序的列表,原列表不变. print(li

随机推荐