FreeRTOS之列表

1.FreeRTOS的列表和列表项十分重要。列表类相当于链表,列表项则相当于链表中的节点。列表项的地址是非连续的,列表项的数量可随时修改。在OS中的任务状态和数量会发生改变,因此使用列表可以很好的满足需求。

列表和列表项的相关定义与操作函数都存放在task.h、task.c中。

(1)列表的定义:

(2)列表项目的定义:

迷你列表项:

2.列表和列表项的关系:

列表类似于双向循环列表,列表项为其中的节点。每个列表项都有前驱指针指向其上一个节点,每个列表项都有后驱指针指向其后一个节点。同时,末尾的列表项和第一个列表项相连接,形成环路。默认情况下,列表的pxIndex指向末尾列表项,而末尾列表项的xItemValue为最大portMAX_DELAY,此部分的操作在初始化列表时完成。

3.列表相关的API函数:

(1)初始化列表函数vListInitialise:

(2)初始化列表项函数vListInitialiseItem:

(3)往列表中插入列表项函数vListInsert:

此方法是按升序的方式将列表项插入到列表中。

在此函数中会遍历到列表项值小于要插入列表项值的最大列表项,即找到列表项值小于要插入的列表项,并且此列表项的值在所有小于要插入列表项值中是最大的,简单来说按升序进行排列,并插入。

(4)列表末尾插入函数vListInsertEnd:

此函数并不是直接将列表项插入到末尾列表项的前面,而是将列表项插入到pxIndex所指向列表的前面

(5)列表项移除函数uxListRemove:

此函数是将需要删除的列表项从列表中移除,并返回列表的剩余列表项数量。

4.代码:本文只展示main.c代码,将本文同前面的FreeRTOS动态创建任务相结合便可以得到完整的代码。

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "FreeRTOS.h"
#include "task.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "time.h"

//¶¨Òåstart_taskµÄÅäÖã¬ÈÎÎñ¾ä±ú£¬ÈÎÎñÓÅÏȼ¶£¬¶ÑÕ»´óС£¬ÈÎÎñÉùÃ÷£º
#define START_TASK_PRIO 1
#define START_TASK_STACK_SIZE 64
TaskHandle_t start_handler;
void start_task(void);

//¶¨ÒåÈÎÎñ1µÄÅäÖã¬ÈÎÎñ¾ä±ú£¬ÈÎÎñÓÅÏȼ¶£¬¶ÑÕ»´óС£¬ÈÎÎñÉùÃ÷£º
#define TASK1_PRIO 2
#define TASK1_STACK_SIZE 64
TaskHandle_t task1_handler;
void task1(void);

//¶¨ÒåÈÎÎñ2µÄÅäÖã¬ÈÎÎñ¾ä±ú£¬ÈÎÎñÓÅÏȼ¶£¬¶ÑÕ»´óС£¬ÈÎÎñÉùÃ÷£º
#define TASK2_PRIO 3
#define TASK2_STACK_SIZE 64
TaskHandle_t task2_handler;
void task2(void);

List_t TestList;																//´´½¨Áбí
ListItem_t ListItem1;														//´´½¨ÁбíÏî1
ListItem_t ListItem2;														//´´½¨ÁбíÏî2
ListItem_t ListItem3;														//´´½¨ÁбíÏî3

int flag = 0;

int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);// ÉèÖÃÖжÏÓÅÏȼ¶·Ö×é4,×ÓÓÅÏȼ¶Îª0
	LED_Init();
	KEY_Init();
	delay_init();
	usart_init(9600);
	
	xTaskCreate((TaskFunction_t) start_task,																//ÈÎÎñº¯Êý
							(const char *)"start_task",																	//ÈÎÎñÃû³Æ
							(uint16_t)START_TASK_STACK_SIZE,											      //ÈÎÎñ¶ÑÕ»´óС
							(void *)NULL,																								//´«µÝ¸øÈÎÎñº¯ÊýµÄ²ÎÊý
							(UBaseType_t)START_TASK_PRIO,																//ÈÎÎñÓÅÏȼ¶
							(TaskHandle_t *)&start_handler);														//ÈÎÎñ¾ä±ú
	
			
	vTaskStartScheduler();																								//¿ªÊ¼ÈÎÎñµ÷¶È
}

/*´´½¨¿ªÊ¼ÈÎÎñ£º*/
void start_task(void)
{
//	taskENTER_CRITICAL();	
	/*´´½¨ÈÎÎñ*/
	if(flag == 0)
	{
		xTaskCreate((TaskFunction_t) task1,																		//ÈÎÎñº¯Êý
								(const char *)"task1",																		//ÈÎÎñÃû³Æ
								(uint16_t)TASK1_STACK_SIZE,											      		//ÈÎÎñ¶ÑÕ»´óС
								(void *)NULL,																							//´«µÝ¸øÈÎÎñº¯ÊýµÄ²ÎÊý
								(UBaseType_t)TASK1_PRIO,																	//ÈÎÎñÓÅÏȼ¶
								(TaskHandle_t *)&task1_handler);													//ÈÎÎñ¾ä±ú
		xTaskCreate((TaskFunction_t) task2,																		//ÈÎÎñº¯Êý
								(const char *)"task2",																		//ÈÎÎñÃû³Æ
								(uint16_t)TASK2_STACK_SIZE,											      		//ÈÎÎñ¶ÑÕ»´óС
								(void *)NULL,																							//´«µÝ¸øÈÎÎñº¯ÊýµÄ²ÎÊý
								(UBaseType_t)TASK2_PRIO,																	//ÈÎÎñÓÅÏȼ¶
								(TaskHandle_t *)&task2_handler);													//ÈÎÎñ¾ä±ú
	 flag = 1;
	}
	 vTaskDelay(500);										
	 vTaskDelete(NULL);											//ɾ³ýµ±Ç°ÈÎÎñ
//	 taskEXIT_CRITICAL();
}

void task1(void)
{
	while(1)
	{
		/*LEDÉÁ˸*/
		GPIO_ResetBits(GPIOA,GPIO_Pin_8);
		GPIO_ResetBits(GPIOD,GPIO_Pin_2);
		vTaskDelay(500);
		GPIO_SetBits(GPIOA,GPIO_Pin_8);
		GPIO_SetBits(GPIOD,GPIO_Pin_2);
		vTaskDelay(500);
	}
}

void task2(void)
{
		
		/*³õʼ»¯ÁбíºÍÁбíÏî*/
		vListInitialise(&TestList);
		vListInitialiseItem(&ListItem1);
		vListInitialiseItem(&ListItem2);
		vListInitialiseItem(&ListItem3);
	
		ListItem1.xItemValue = 40;
		ListItem2.xItemValue = 60;
		ListItem3.xItemValue = 50;
	
		printf("********´òÓ¡ÁбíºÍÁбíÏîµØÖ·********\r\n");
		printf("TestList							0x%p 		\r\n",&TestList);
		printf("TestList->pxIndex						0x%p 		\r\n",(TestList.pxIndex));
		printf("TestList->xListEnd						0x%p 		\r\n",&(TestList.xListEnd));
		printf("ListItem1							0x%p 		\r\n",&ListItem1);
		printf("ListItem2							0x%p 		\r\n",&ListItem2);
		printf("ListItem3							0x%p 		\r\n",&ListItem3);
		printf("****************½áÊø****************\r\n");
		printf("\r\n");
	
//		/*²åÈëÁбíÏî1£º*/
		vListInsert(&TestList,&ListItem1);
//		printf("TestList->xListEnd->pxNext					0x%p 		\r\n",(int)(TestList.xListEnd.pxNext));
//		printf("ListItem1->pxNext						0x%p 		\r\n",(int)ListItem1.pxNext);
//		printf("TestList->xListEnd->pxPrevious					0x%p 		\r\n",(int)(TestList.xListEnd.pxPrevious));
//		printf("ListItem1->pxPrevious						0x%p 		\r\n",(int)ListItem1.pxPrevious);
		
//		printf("\r\n");
//		/*²åÈëÁбíÏî2£º*/
		vListInsert(&TestList,&ListItem2);
//		printf("TestList->xListEnd->pxNext					0x%p 		\r\n",(int)(TestList.xListEnd.pxNext));
//		printf("ListItem1->pxNext						0x%p 		\r\n",(int)ListItem1.pxNext);
//		printf("ListItem2->pxNext						0x%p 		\r\n",(int)ListItem2.pxNext);
//		printf("TestList->xListEnd->pxPrevious					0x%p 		\r\n",(int)(TestList.xListEnd.pxPrevious));
//		printf("ListItem1->pxPrevious						0x%p 		\r\n",(int)ListItem1.pxPrevious);
//		printf("ListItem2->pxPrevious						0x%p 		\r\n",(int)ListItem2.pxPrevious);
		
		printf("\r\n");
		/*²åÈëÁбíÏî3£º*/
		vListInsert(&TestList,&ListItem3);
//		printf("TestList->xListEnd->pxNext					0x%p 		\r\n",(int)(TestList.xListEnd.pxNext));
//		printf("ListItem1->pxNext						0x%p 		\r\n",(int)ListItem1.pxNext);
//		printf("ListItem2->pxNext						0x%p 		\r\n",(int)ListItem2.pxNext);
//		printf("ListItem3->pxNext						0x%p 		\r\n",(int)ListItem3.pxNext);
//		printf("TestList->xListEnd->pxPrevious					0x%p 		\r\n",(int)(TestList.xListEnd.pxPrevious));
//		printf("ListItem1->pxPrevious						0x%p 		\r\n",(int)ListItem1.pxPrevious);
//		printf("ListItem2->pxPrevious						0x%p 		\r\n",(int)ListItem2.pxPrevious);
//		printf("ListItem3->pxPrevious						0x%p 		\r\n",(int)ListItem3.pxPrevious);
		
		printf("\r\n");
		/*ɾ³ýÁбíÏî3£º*/
		uxListRemove(&ListItem3);
		printf("TestList->xListEnd->pxNext					0x%p 		\r\n",(TestList.xListEnd.pxNext));
		printf("ListItem1->pxNext						0x%p 		\r\n",ListItem1.pxNext);
		printf("ListItem2->pxNext						0x%p 		\r\n",ListItem2.pxNext);
		//printf("ListItem3->pxNext						0x%p 		\r\n",(int)ListItem3.pxNext);
		printf("TestList->xListEnd->pxPrevious					0x%p 		\r\n",(TestList.xListEnd.pxPrevious));
		printf("ListItem1->pxPrevious						0x%p 		\r\n",ListItem1.pxPrevious);
		printf("ListItem2->pxPrevious						0x%p 		\r\n",ListItem2.pxPrevious);
		//printf("ListItem3->pxPrevious						0x%p 		\r\n",(int)ListItem3.pxPrevious);
		
				printf("\r\n");
		/*β²åÈëÁбíÏî3£º*/
		vListInsertEnd(&TestList,&ListItem3);
		printf("TestList->xListEnd->pxNext					0x%p 		\r\n",(TestList.xListEnd.pxNext));
		printf("ListItem1->pxNext						0x%p 		\r\n",ListItem1.pxNext);
		printf("ListItem2->pxNext						0x%p 		\r\n",ListItem2.pxNext);
		printf("ListItem3->pxNext						0x%p 		\r\n",ListItem3.pxNext);
		printf("TestList->xListEnd->pxPrevious					0x%p 		\r\n",(TestList.xListEnd.pxPrevious));
		printf("ListItem1->pxPrevious						0x%p 		\r\n",ListItem1.pxPrevious);
		printf("ListItem2->pxPrevious						0x%p 		\r\n",ListItem2.pxPrevious);
		printf("ListItem3->pxPrevious						0x%p 		\r\n",ListItem3.pxPrevious);
		
}

5.运行结果:

6.总结:

本文介绍了FreeRTOS中的列表和列表项的定义,以及列表与列表项的相关操作函数。在理解的时,可以将列表当作双向循环列表,将列表项当作其中的节点。

列表在FreeRTOS中十分重要,比如FreeRTOSD有三个和任务相关的列表:就绪列表、阻塞列表、挂起列表。当将任务从阻塞状态变成就绪状态时,需要先将列表项对应的任务从阻塞列表中删除,然后再插入到就绪列表中。

下图为任务的状态图:

其中,运行、就绪、阻塞态和挂起态的定义是:

(1)运行态:当前正在运行的任务便处于运行态。

(2)就绪态:处于就绪态的任务是那些已经准备就绪(这些任务没有被阻塞或者挂起),可以运行的任务, 但是处于就绪态的任务还没有运行,因为有一个同优先级或者更高优先级的任务正在运行!

(3)阻塞态:如果一个任务当前正在等待某个外部事件的便处于阻塞态,比如如果某个任务调用了函数 vTaskDelay()的话就会进入阻塞态,直到延时周期完成。任务在等待队列、信号量、事 件组、通知或互斥信号量的时候也会进入阻塞态。任务进入阻塞态会有一个超时时间,当超过 这个超时时间任务就会退出阻塞态,即使所等待的事件还没有来临!

(4)挂起态:挂起态和阻塞态都无法被任务调度器调用进入运行态,但是,挂起的任务没有超时时间。挂起任务函数为vTaskSuspend(),推出挂起函数为xTaskResume()。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网工交换基础——生成树协议(01)

一、生成树的技术概述 1、技术背景 二层交换机网络的冗余性导致出现二层环路: 人为因素导致的二层环路问题: 二层环路带来的网络问题: 生成树协议的概念: STP(Spanning Tree Protocol)是生成树协议的英文缩写。该协议可应用于在网…

vue3 -- 项目使用自定义字体font-family

在Vue 3项目中使用自定义字体(font-family)的方法与在普通的HTML/CSS项目中类似。可以按照以下步骤进行操作: 引入字体文件: 首先,确保你的字体文件(通常是.woff、.woff2、.ttf等格式)位于项目中的某个目录下,比如src/assets/font/。 在全局样式中定义字体: 在你的全局…

智慧健康旅居养老产业,做智慧旅居养老服务的公司

随着社会的进步和科技的飞速发展,传统的养老模式已经无法满足 现代老年人的多元化 需求。智慧健康旅居养老产业应运而生,成为了一种新型的养老模式,旨在为老年人提供更加舒适、便捷、安全的养老生活。随着社会的进步和人口老龄化趋势的加剧&a…

pytest数据驱动DDT

常见的DDT技术 数据结构: 列表、字典、json串 文件: txt、csv、xcel 数据库: 数据库链接 数据库提取 参数化: pytest.mark.parametrize() pytest.fixture() D…

【课程发布】软考高项目十大管理ITTO宫殿记忆法新版第四版正式发布

软考高项十大管理ITTO宫殿记忆法视频课程: 平台:荔枝微课 连接:十方教育 各位软考高级信息系统项目管理师考生好,新版第四版十大管理ITTO宫殿记忆法视频课程终于发布了,之前苦等的考生终于迎来了救星,再也…

OAuth2、JWT

文章目录 OAuth2JWT OAuth2 官网: https://oauth.net/2/ 在 RFC 6749 中说明 1、资源所有者 resource owner, 如 github 用户 2、客户端/第三方应用 client, 如 支持github 登录的 csdn 3、资源服务器 resource server, 如 4、授…

【C/C++笔试练习】OSI分层模型、源端口和目的端口、网段地址、SNMP、状态码、tcp报文、域名解析、HTTP协议、计算机网络、美国节日、分解因数

文章目录 C/C笔试练习选择部分(1)OSI分层模型(2)源端口和目的端口(3)网段地址(4)SNMP(5)状态码(6)tcp报文(7)域…

GRASSHOPPER电池Expression

Grasshopper中如果要实现简单的条件if语句的效果,可以使用电池Expression。 举例:获取两个数的差值,永远用大数减去小数

Geoserver中点击切片图层报错问题

最近想试试wmts,其中有一步需要用到切片图层 但是点击页面老是报错, 于是乎想断点,可惜代码太复杂 弃了,所以想重新部署一下新版本,结果还是报错,想着可能tomcat有缓存吧,在换个tomcat还是报错…

《QT实用小工具·四十二》圆形发光图像

1、概述 源码放在文章末尾 该项目实现了图像的发光效果,特别适合做头像,项目demo演示如下所示: 项目部分代码如下所示: import QtQuick 2.7 import QtGraphicalEffects 1.12Item {id: rootwidth: 80height: 80property int ra…

【JVM】java内存区域

目录 一、运行时数据区域 1、方法区 2、堆 3、虚拟机栈 4、本地方法栈 5、程序计数器 6、运行时常量池 二、HotSpot虚拟机的对象 1、对象的创建 指针碰撞: 空闲列表: 2、对象的内存布局 对象头 实例数据 对齐填充 3、对象的访问定位 句…

一种基于 RFID 技术的养老院人员定位解决方案

在今日的中国社会结构老龄化日趋增长,带来了一系列的社会问题。社会老龄化、高龄化、空巢化和病残化的迅速发展,将使得越来越多的老人住进养老院。养老院主要为老人提供集体居住,并具有相对完整的配套服务设施。养老院管理的最终目的就是为老…

【Qt 学习笔记】Qt常用控件 | 输入类控件 | Combo Box的使用及说明

博客主页:Duck Bro 博客主页系列专栏:Qt 专栏关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ Qt常用控件 | 输入类控件 | Combo Box的使用及说明 文章编号&#xff…

张大哥笔记:普通人如何搞钱?

追求短期利润和长期价值相结合的创业方式,是我一直倡导的。短期内寻求盈利的项目进行快速变现,比如各种小风口项目,而长期项目则需保持数年乃至10年不变,比如自媒体内容输出,做有长期价值的事情! 短期项目通…

详解MySQL C API 相关接口(大白话就是:MySQL的c语言怎么写)

文章目录 1、C API 官方文档2、初始化 MYSQL3、连接 MySQL设置连接字符集(使得客户端编码方式匹配) 4、下发 mysql 指令5、获取 mysql 查询结果(保存起来)获取行与列遍历存储结果 6、释放 MYSQL\_RES 对象7、关闭 MySQL 连接8、总结 1、C API 官方文档 …

Linux安装Docker的多版本PHP和多版本MySQL共存

1: 先安装docker 安装完后执行,权限设置 sudo usermod -aG docker $USER或者sudo usermod -aG docker kentrl#添加当前用户到Docker用户组中 sudo newgrp docker#更新用户组数据,必须执行否则无效 sudo systemctl restart docker 先看目录结构: 2:按照目录结构挂载磁盘,…

(一)Amira入门实例

1.打开Amira安装目录下的数据Foam.am图片,打开之后选择“um”选项。 2. 添加一个2D和3D显示组件,即Ortho Slice和Volume Rendering,分别为2D显示和3D显示(模块左侧绿点控制是否显示): 颜色反转之后&#xf…

C# GetField 方法应用实例

目录 关于 C# Type 类 GetField 方法应用 应用举例 心理CT设计题 类设计 DPCT类实现代码 小结 关于 C# Type 类 Type表示类型声明:类类型、接口类型、数组类型、值类型、枚举类型、类型参数、泛型类型定义,以及开放或封闭构造的泛型类型。调用 t…

第十五届蓝桥杯省赛第二场C/C++B组G题【最强小队】题解

20pts 枚举所有可能的左端点、右端点,时间复杂度 O ( n 2 ) O(n^2) O(n2)。 对于每个区间进行遍历检测,时间复杂度 O ( n 3 ) O(n^3) O(n3)。 100pts 由于数据范围为 1 0 5 10^5 105,所以肯定只能进行一次枚举。 我们尝试枚举右端点&…

winform实现的调用bartender打印工具-标签模版管理

生产型企业基本都有条码追溯管理的需求&#xff0c;不同的产品有不同的标签样式规格以及内容&#xff0c;打印的条码往往需要追溯以及防重校验&#xff0c;因此市面有很多打印软件&#xff0c;今天分享基于winform开发的调用bartender标签的工具。 先上效果图 /// <summary…
最新文章