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;														//´´½¨ÁбíÏî3int flag = 0;int main(void)
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);// ÉèÖÃÖжÏÓÅÏȼ¶·Ö×é4,×ÓÓÅÏȼ¶Îª0LED_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.mzph.cn/bicheng/4734.shtml

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

相关文章

电商独立站||跨境电商独立站网站搭建|功能系统搭建||API接口接入

搭建多语言跨境电商独立站系统 前台主要功能模块 短信接口 第三方登陆 支付方式 会员中心 代购订单列表 - new 会员签到 -1000(1) new 支付密码 ---1000 国内流程 -----5000 new 订单运单多退少补 -1000 未付款运单取消功能 - 修改运单运输方式 -----1000 年费会员 -----3000 …

D435+opencv识别色块

在当前的机器视觉和机器人技术领域,实时图像处理是一项至关重要的技术。本文介绍了如何利用Python、OpenCV库以及Intel的Realsense摄像头来进行实时的颜色识别。这种技术可以广泛应用于自动化检测、机器人导航以及交互式媒体等领域。 一、 开发环境配置 首先&#x…

大型零售企业,适合什么样的企业邮箱大文件解决方案?

大型零售企业通常指的是在全球或特定地区内具有显著市场影响力和知名度的零售商。这些企业不仅在零售业务收入上达到了惊人的规模,而且在全球范围内拥有广泛的销售网络和实体店铺。它们在快速变化的零售行业中持续创新,通过实体店、电商平台等多种渠道吸…

C#队列(Queue)的基本使用

概述 在编程中&#xff0c;队列&#xff08;Queue&#xff09;是一种常见的数据结构&#xff0c;它遵循FIFO&#xff08;先进先出&#xff09;的原则。在C#中&#xff0c;.NET Framework提供了Queue<T>类&#xff0c;它位于System.Collections.Generic命名空间下&#x…

【深度学习实战(26)】标签处理之语义分割标签转换,数据集划分

一、标签转换 我们在使用labeme标签工具&#xff0c;标注完数据后会获得json文件。在标注结束过后&#xff0c;我们需要通过标签转换操作&#xff0c;生成jpg格式原始图片和png格式mask标签图。 1.1 使用img_b64_to_arr将json标签中二进制图像数据变成numpy格式数据&#xf…

介绍一个小技巧-Luhn算法

这种算法主要用于验证身份识别码的正确性&#xff0c;比如信用卡号、发卡行识别码、国际移动设备识别码&#xff08;IMEI&#xff09;、美国国家提供商标识号码以及电子票的票号验证等。是由IBM科学家Hans Peter Luhn于1954年发明的一种简单校验和算法。在工业自动化领域也有使…

selenium在Pycharm中结合python的基本使用、交互、无界面访问

下载 下载与浏览器匹配的浏览器驱动文件&#xff0c;这里一定注意的是&#xff0c;要选择和浏览器版本号相同的驱动程序&#xff0c;否则后面会有很多问题。 &#xff08;1&#xff09;浏览器&#xff08;以google为例&#xff09;版本号的查询&#xff1a; 我这里的版本号是1…

java实现模板填充word,word转pdf,pdf转图片

Java实现Word转PDF及PDF转图片 在日常开发中&#xff0c;我们经常需要将文件操作&#xff0c;比如&#xff1a; 根据模板填充wordword文档中插入图片Word文档转换为PDF格式将PDF文件转换为图片。 这些转换可以帮助我们在不同的场景下展示或处理文档内容。下面&#xff0c;我将…

回归(Regression)

回归&#xff08;Regression&#xff09;在统计学和机器学习中是一种预测建模技术&#xff0c;它研究的是因变量&#xff08;目标变量&#xff09;和自变量&#xff08;特征&#xff09;之间的关系。回归分析的目的是建立一个数学模型&#xff0c;这个模型能够基于一个或多个自…

Leetcode—1256. 加密数字【中等】Plus(bitset、find_first_not_of、erase)

2024每日刷题&#xff08;120&#xff09; Leetcode—1256. 加密数字 实现代码 class Solution { public:string encode(int num) {string ans;num 1;while(num ! 0) {ans to_string(num & 1);num num >> 1;}if(ans.empty()) {return "";} else {stri…

coreldraw2024精简版绿色版安装包免费下载

CorelDRAW 2024是一款矢量图形设计软件&#xff0c;于2024年3月5日正式在全球范围内发布。这款软件在多个方面进行了更新和改进&#xff0c;为用户提供了更多高效、灵活和便捷的设计工具。 首先&#xff0c;CorelDRAW 2024新增了绘画笔刷功能&#xff0c;这些笔刷不仅模拟了传…

Ubuntu20.04 [Ros Noetic]版本——在catkin_make编译时出现报错的解决方案

今天在新的笔记本电脑上进行catkin_make的编译过程中遇到了报错&#xff0c;这个报错在之前也遇到过&#xff0c;但是&#xff0c;我却忘了怎么解决。很是头痛&#xff01; 经过多篇博客的查询&#xff0c;特此解决了这个编译报错的问题&#xff0c;于此特地记录&#xff01;&…

深入探索Android Service:多线程环境最佳实践与系统级操作

引言 Service作为Android平台的基石之一&#xff0c;其在多线程环境下的高级应用以及跨应用通信的能力&#xff0c;为开发者提供了构建高性能、高稳定性应用的可能。本文将深入探讨Service在多线程环境下的最佳实践&#xff0c;以及Service 与系统级操作、Service与系统资源管…

day17面向对象三大特征—封装

回顾 1.对象:一个拥有属性和方法的实例:实体 2类名 ;大骆驼峰 class 类名: 类代码 class People: 类属性 (类属性:所有的对象共有的属性) name = 一类人 def __init__(self, name, age, sex): self : 对象本身 self.name 拿到属性值 self…

SpringCloud和SpringBoot技术选型

Spring Cloud和Spring Boot在技术选型上各自具有独特的特点和优势&#xff0c;它们在不同的场景和需求下发挥着不同的作用。 Spring Boot是一个快速开发框架&#xff0c;它简化了传统MVC的XML配置&#xff0c;使得配置变得更加方便、简洁。通过采用“约定优于配置”的理念&…

【已解决】c++如何在MFC框架中按下某键触发触发事件

本博文源于昨天处理的一个事件&#xff0c;接收到回车键进行检测&#xff0c;同样的这个也可以接收其他键&#xff0c;比如A 键B键之类的。这里可以在mfc框架中使用这个函数 BOOL ****::PreTranslateMessage(MSG* pMsg);该函数会在程序运行时不停地被调用只需要你用if去拦截它…

[论文笔记]SEARCHING FOR ACTIVATION FUNCTIONS

引言 今天带来另一篇激活函数论文SEARCHING FOR ACTIVATION FUNCTIONS的笔记。 作者利用自动搜索技术来发现新的激活函数。通过结合详尽的搜索和基于强化学习的搜索&#xff0c;通过实验发现最佳的激活函数 f ( x ) x ⋅ sigmoid ( β x ) f(x) x \cdot \text{sigmoid}(βx…

Unity DOTS中的baking(五)prefabs

Unity DOTS中的baking&#xff08;五&#xff09;prefabs 在DOTS的baking过程中&#xff0c;prefabs会被烘焙成entity prefabs。entity prefabs也是一个entity&#xff0c;可以在运行时实例化&#xff0c;就像是prefab一样。我们可以使用EntityPrefabReference这个struct&#…

瓦片编辑器成功移植到小熊猫C++ 2.25.1版本,解决_findnext移植问题

移植之后出现绿色屏幕闪退 查了版本回滚直到不闪退&#xff0c;发现是在读取自定义文件上出问题 然后在找读取自定义文件函数&#xff0c;发现是读取图片部分出问题 然后就卡住了 调试半天&#xff0c;不是数据溢出&#xff0c;于是就看 函数_findnext,网上搜 ———_findn…

Java项目启动检测 Redis 是否启动,未启动则启动(macOS 版本)

文章目录 一、概述二、代码 一、概述 启动项目时&#xff0c;检测macos 上 Redis 是否启动&#xff0c;未启动&#xff0c;则启动。 二、代码 /*** 用途: 项目启动时检查 redis&#xff0c;未启动则启动&#xff08;开发环境&#xff09;** author: ADAM* create: 2024/04/2…