FreeRTOS之列表

news2024/10/7 14:31:09

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.coloradmin.cn/o/1632276.html

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

相关文章

基于51单片机的8路抢答器—计分功能

基于51单片机的8路抢答器 (仿真+程序) 功能介绍 具体功能: 1.主持人按下复位后数码管依次显示选手的编号和分数; 2.显示结束后主持人才可以按开始按键; 3.数码管倒计时10秒,选手开始抢答&a…

Jenkins邮件发送失败问题解决

如下提示为 Extended E-mail Notification开启Debug模式下显示的错误信息, (Debug模式设置方法:Dashboard-> manage Jenkins->configure System)DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM XOAUTH2 DEB…

Qt窗口

QMainWindow Qt 窗⼝ 是通过 QMainWindow类 来实现的。 QMainWindow 是⼀个为⽤⼾提供主窗⼝程序的类,继承⾃ QWidget 类,并且提供了⼀个预定义的 布局。QMainWindow 包含 ⼀个菜单栏(menu bar)、多个⼯具栏(tool bars)、多个浮动…

HarmonyOS NEXT应用开发之适配挖孔屏案例

介绍 本示例介绍使用屏幕属性getDefaultDisplaySync、getCutoutInfo接口实现适配挖孔屏。该场景多用于沉浸式场景下。 效果图预览 使用说明 加载完成后顶部状态栏时间和电量显示位置规避了不可用区域。 实现思路 通过setWindowLayoutFullScreen、setWindowSystemBarEnable…

自制贪吃蛇小游戏

此片文章涉及到到控制台设置的相关操作,虚拟键码,宽字符输出等,有些地方大家可能会看不懂,可以阅读以下文章来进一步了解: 控制台程序设置-CSDN博客 效果展示: QQ2024428-181932 源码已放在文章结尾 目录 …

Python | Leetcode Python题解之第55题跳跃游戏

题目&#xff1a; 题解&#xff1a; class Solution:def canJump(self, nums: List[int]) -> bool:n, rightmost len(nums), 0for i in range(n):if i < rightmost:rightmost max(rightmost, i nums[i])if rightmost > n - 1:return Truereturn False

AHB传输---等待传输

等待传输 slave在需要更多时间支持或采样数据时使用HREADYOUT信号插入等待状态。在等待传输期间&#xff0c;master对传输类型和地址的更改受到限制。 1. 在等待状态下传输类型的变化 当slave请求等待状态时&#xff0c;master不得更改传输类型&#xff0c;除非是以下状态&a…

Spring AOP是什么?可以拿它做什么?

Spring AOP&#xff08;Aspect-Oriented Programming&#xff0c;面向切面编程&#xff09;是Spring框架提供的一种重要特性&#xff0c;它通过在应用程序的横切关注点&#xff08;Cross-cutting Concerns&#xff09;中&#xff0c;将重复性的代码和逻辑分离出来&#xff0c;以…

青年夜校 | 李良济中医课堂,赋能“夜生活”,传承中医药文化

下班后的苏州年轻人都在干什么&#xff1f; 约饭看电影&#xff1f; 宅家打游戏&#xff1f; 最近&#xff0c;一种全新的“夜生活”模式开启啦&#xff01; 那就是—— 去家门口的夜校&#xff0c;学习中医和中药&#xff01; 1 家门口的夜校 解锁正确的中医养生法 4月…

Matlab实现CNN-LSTM模型,对一维时序信号进行分类

1、利用Matlab2021b训练CNN-LSTM模型&#xff0c;对采集的一维时序信号进行分类二分类或多分类 2、CNN-LSTM时序信号多分类执行结果截图 训练进度&#xff1a; 网络分析&#xff1a; 指标变化趋势&#xff1a; 代码下载方式&#xff08;代码含数据集与模型构建&#xff0c;附…

LabVIEW自动剪板机控制系统

LabVIEW自动剪板机控制系统 随着工业自动化的快速发展&#xff0c;钣金加工行业面临着生产效率和加工精度的双重挑战。传统的手动或脚踏式剪板机已无法满足现代生产的高效率和高精度要求&#xff0c;因此&#xff0c;自动剪板机控制系统的研究与开发成为了行业发展的必然趋势。…

消失了一个月,失踪人口回归!

大家好&#xff0c;我是前端队长。前端程序员&#xff0c;2023年开始玩副业。玩过AI绘画&#xff0c;公众号爆文项目&#xff0c;目前在做AI代写&#xff0c;累计变现五位数。 最近比较忙&#xff0c;而且没有意识到持续分享的重要性。 周六的时候&#xff0c;参加了武汉老徐合…

prompt提示词:AI英语词典,让AI教你学英语,通过AI实现一个网易有道英语词典

目录 英语词典提问技巧效果图&#xff1a;提示词&#xff1a; 英语词典提问技巧 随着AI工具的出现&#xff0c;学英语也可以变得很简单&#xff0c;大家可以直接通过AI 来帮助自己&#xff0c;提高记忆单词的效率&#xff0c;都可以不需要网易有道词典了&#xff0c;今天我教大…

Docker容器:数据管理与镜像的创建(主要基于Dockerfile)

目录 一、Docker 数据管理 1、数据卷&#xff08;Data Volumes&#xff09; 2、数据卷容器&#xff08;DataVolumes Containers&#xff09; 二、容器互联&#xff08;使用centos镜像&#xff09; 三、Docker 镜像的创建 1、基于现有镜像创建 2、基于本地模板创建 3、基…

不同状态空间模型的实验对比(二)

对五个下游任务进行了实验比较&#xff0c;包括单/多标签分类、视觉对象跟踪、像素级分割、图像到文本生成和人/车辆再识别。 论文&#xff1a;https://arxiv.org/abs/2404.09516 作者单位&#xff1a;安徽大学、哈尔滨工业大学、北京大学更多相关工作将在以下GitHub上不断更新…

JavaScript 的基本术语大全

文章目录 1、概述2、基本术语2.1、有效负载 (Payload)2.2、ReadableStream2.3、模块系统2.4、DOM (Document Object Model)2.5、事件 (Events)2.6、活动委托 (Event Delegation)2.7、内容安全策略 (CSP)2.8、渐进增强和优雅降级2.9、JSON (JavaScript Object Notation)2.10、AJ…

支付宝沙盒(java使用支付宝)springboot

目录 前言 注册账号&#xff08;直接搜索支付宝沙盒&#xff09; ​编辑 具体代码编写 Application配置(按自己需求添加) config&#xff08;这里需要亲自添加appid&#xff0c;privateKey&#xff0c;publicKey&#xff09; controller类 Service类 ServiceImpl类 运…

OpenNJet产品体验丨从零部署一个炫酷的Web服务器

本文记录了使用OpenNJet从零部署一个Web服务器的心得体会。 OpenNJet官方网站&#xff1a;https://njet.org.cn/ 一、基本信息 产品名称 OpenNJet 体验版本 2.1.0 体验设备 VMware16Ubuntu18.04 体验时间 2024.4.23 体验耗时 1.5 h 二、产品信息 产品简介&#x…

【13-支持向量机(SVM):Scikit-learn中的分类与回归】

文章目录 前言理解SVM核心概念SVM的优势SVM的劣势Scikit-learn中的SVM实现安装与导入数据准备SVM分类SVM回归调优与最佳实践总结前言 支持向量机(SVM)是一种强大的机器学习算法,用于解决分类、回归和异常检测问题。它的核心思想是找到一个最优超平面,使得不同类别之间的边界…