FreeRTOS之列表

news/2025/2/11 2:20:45/

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.ppmy.cn/news/1443153.html

相关文章

CMUS狮身人面像(四)-构建语言模型

构建语言模型 语言模型是配置的重要组成部分,它告诉解码器可以识别哪些单词序列。 模型有多种类型:关键词列表、语法和统计语言模型以及语音语言模型。它们具有不同的功能和性能特性。您可以根据需要选择任何解码模式,甚至可以在运行时在模…

从Grafana支持的认证方式分析比较IAM产品现状与未来展望

调研报告 标题:从Grafana支持的认证方式分析比较IAM产品现状与未来展望 概述 本报告首先概述了评价IAM(Identity and Access Management)产品的主要因素,并基于Grafana支持的认证方式,引出对IAM产品的深入探讨。通过…

Flink DataStream API 批处理能力演进之路

摘要:本文由阿里云 Flink 团队郭伟杰老师撰写,旨在向 Flink Batch 社区用户介绍 Flink DataStream API 批处理能力的演进之路。内容主要分为以下三个部分: 1. 批处理语义和性能优化 2. Batch API 功能增强 3. 总结 最近在和一个朋友闲聊时&am…

秋招后端开发面试题 - Java语言基础(下)

目录 Java基础下前言面试题toString() 、String.valueof()、(String)?hashCode() 方法?hashCode 和 equals 方法判断两个对象是否相等?为什么重写 equals 时必须重写 hashCode 方法?String、StringBuffer、StringBuilder?String …

【保姆级讲解下gateway基本配置】

🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出…

Eclipse C++ 无法debug 问题

环境: ubuntu20.04 Eclipse CDT(x86_64) 工程,使用的是默认的CMake Project 现象: 1. 使用Eclipse, 加了断点后,debug 无法停在断点;step over 执行后是从main 直接执行到exit &#xff…

应急学院物联网应急安全产教融合基地解决方案

第一章 背景 1.1物联网应急安全产教融合发展概况 物联网应急安全产教融合发展是当前社会发展的重要趋势。随着物联网技术的广泛应用,应急安全领域对人才的需求日益迫切。因此,产教融合成为培养高素质、专业化人才的关键途径。在这一背景下,…

2024最新华为OD机试试题库全 -【孙悟空吃蟠桃】- C卷

1. 🌈题目详情 1.1 ⚠️题目 孙悟空爱吃蟠桃,有一天趁着蟠桃园守卫不在来偷吃。已知蟠桃园有 N 棵桃树,每颗树上都有桃子,守卫将在 H 小时后回来。 孙悟空可以决定他吃蟠桃的速度K(个/小时),每个小时选一颗桃树,并从树上吃掉 K 个,如果树上的桃子少于 K 个,则全部…