FreeRTOS任务调度器

目录

1、什么是任务调度器

 2、FreeRTOS中的任务调度器

2.1 抢占式调度

2.2 时间片调度

2.3 协作式调度

3、任务调度案例分析

3.1 实验需求

3.2 CubeMX配置

3.3 代码实现

3.3.1 uart.c 重定向printf

3.3.2 打开freertos.c并添加代码

3.3.4 代码现象


1、什么是任务调度器

任务调度器是实时操作系统(RTOS)的一个关键组件,它负责决定在多个可运行任务中哪一个将获得CPU时间得以执行。它基于任务的优先级和状态来做出这些决定。

在一个RTOS中,可能会有多个任务同时运行,但是在任意时刻,CPU只能执行一个任务。任务调度器的主要目标是按照系统的需求合理分配CPU时间

调度器就是使用相关的调度算法来决定当前需要执行的哪个任务

基本功能

任务的选择任务调度器会根据预设的算法从所有可运行的任务中选择一个要执行的任务
任务的优先级任务通常会被分配一个优先级,优先级越高的任务在抢占式调度中会优先执行
任务状态管理任务可能处于就绪状态(可立即运行)、阻塞状态(等待某些条件满足)或者挂起状态(暂停执行)。
上下文切换任务调度器负责在不同任务之间进行上下文切换。这意味着将当前任务的状态保存起来,然后加载另一个任务的状态,以便它可以继续执行。
定时器管理任务调度器通常会关注系统中的定时器,以便能够在特定事件发生时唤醒相应的任务
中断处理任务调度器需要与系统的中断处理程序协同工作,以确保在中断上下文中也能够正常进行任务调度

 2、FreeRTOS中的任务调度器

FreeRTOS 是一个实时操作系统,它所奉行的调度规则:

1. 抢占式调度器:抢占式调度器是一种优先级基础的调度器,高优先级抢占低优先级任务,系统永远执行最高优先级的任务。

2. 时间片调度器:时间片轮转调度器是一种抢占式调度器,它将CPU时间划分成小的时间片段,每个任务在一个时间片段内运行

3. 协程式调度器:协作式调度器依赖于任务自行释放CPU,没有明确的任务优先级任务必须自愿放弃CPU控制权,以便其他任务能够运行。(但官方已明确表示不更新,主要是用在小容量的芯片上,用得也不多)

FreeRTOS中开启任务调度的函数是vTaskStartScheduler() ,但在CubeMX中被封装为osKernelStart() 。

2.1 抢占式调度

优点适用于实时要求严格的系统,可以确保高优先级任务及时响应。
缺点上下文切换的开销较大,可能会影响系统的性能。

        1. 任务优先级:每个任务都会被分配一个优先级。优先级较高的任务被认为更紧急,将会在可运行时抢占具有较低优先级的任务

        2. 抢占:当一个高优先级的任务准备好运行时,RTOS会暂停当前正在执行的低优先级任务,并将CPU的控制权转交给高优先级任务

        3. 上下文切换:在抢占发生时,RTOS会保存当前任务的上下文(包括寄存器状态等),然后加载高优先级任务的上下文,使其可以继续执行。这个过程称为上下文切换。

        4. 实时性:抢占式调度器可以保证高优先级任务能够及时响应紧急事件。这对于实时系统和需要快速响应的应用程序非常重要。

        5. 任务挂起:在抢占式调度中,可以随时挂起(暂停)一个任务,以便给更高优先级的任务让路。挂起(暂停)函数为vTaskSuspend(),恢复函数为vTaskResume()

        6. 任务阻塞:一个任务可以由于等待某些条件的发生而被阻塞。当这些条件满足时,RTOS会将其重新置为就绪状态

        7. 中断处理:抢占式调度需要能够在中断上下文中正确地处理任务的切换。

        8. 实时性保证:抢占式调度对于需要在严格的实时约束下工作的系统非常重要,因为它可以确保高优先级任务在预期的时间内得到处理。

总结:

  1. 高优先级任务,优先执行;
  2. 高优先级任务不停止,低优先级任务无法执行;
  3. 被抢占的任务将会进入就绪态。

2.2 时间片调度

优点适用于多个任务优先级相近的场景,可以避免某个任务长时间占用CPU。
缺点会引入一定的上下文切换开销。

        1. 时间片段:CPU的执行时间被划分成固定长度的时间片段。每个时间片段可以是几毫秒或者更短的时间,具体取决于系统的配置。

        2. 任务优先级:每个任务都被分配一个优先级。在一个时间片段内,具有相同优先级的任务会依次轮流执行。

        3. 抢占:当一个时间片段结束时,RTOS会暂停当前执行的任务,并将CPU的控制权转交给具有相同优先级的下一个任务。

        4. 上下文切换:在每个时间片段结束时,RTOS会进行上下文切换,将当前任务的状态保存起来,并加载下一个任务的状态,以便其可以继续执行。

        5. 公平分配CPU时间:时间片调度确保了每个任务在一定时间段内都有机会执行,从而实现了相对公平的CPU时间分配。

        6. 避免任务长时间占用CPU:时间片调度可以防止某个任务长时间占用CPU,从而保证了其他任务也有机会执行。

        7. 适用于优先级相近的任务:时间片调度特别适用于具有相近优先级的任务集,因为它可以确保它们在相对公平的条件下执行。

        8. 降低实时性:相比于抢占式调度,时间片调度可能会引入一定的上下文切换开销,从而降低了系统的实时性。

总结:

  1. 同等优先级任务,轮流执行,时间片流转;
  2. 一个时间片大小,取决为滴答定时器中断周期;
  3. 注意没有用完的时间片不会再使用,下次任务Task3得到执行,还是按照一个时间片的时钟节拍运行。

2.3 协作式调度

        1. 任务自主控制:在协作式调度中,任务负责自己的执行时间任务在需要让出CPU时,会主动调用RTOS提供的让出控制权的函数

        2. 没有明确的任务优先级:协作式调度中通常没有明确的任务优先级概念。所有的任务被视为平等,没有任务可以强制其他任务停止执行。

        3. 低上下文切换开销:相比抢占式调度,协作式调度通常具有更低的上下文切换开销,因为任务只有在愿意让出CPU时才会发生切换

        4. 任务合作:任务之间需要合作以确保系统的正常运行。如果一个任务长时间占用CPU,其他任务可能会受到影响。

        5. 适用于资源受限的系统:协作式调度适用于资源有限的嵌入式系统,因为它减少了抢占式调度中的上下文切换开销。

        6. 可能导致响应性降低:如果一个任务不合作,即使有更高优先级的任务需要执行,也可能导致响应性降低,因为任务不会主动让出CPU。

        7. 任务挂起和任务阻塞:虽然没有抢占,但任务仍然可以被挂起(暂停)或者阻塞,等待某些条件的发生。

3、任务调度案例分析

3.1 实验需求

创建 4 个任务:taskLED1,taskLED2,taskKEY1,taskKEY2,任务要求如下:

taskLED1:间隔 500ms 闪烁 LED1;

taskLED2:间隔 1000ms 闪烁 LED2;

taskKEY1:如果 taskLED1 存在,则按下 KEY1 后删除 taskLED1 ,否则创建 taskLED1 ;

taskKEY2:如果 taskLED2 正常运行,则按下 KEY2 后挂起 taskLED2 ,否则恢复 taskLED2。

3.2 CubeMX配置

查看原理图配置按键跟LED灯引脚

这里已经将FreeRTOS移植到STM32F103C8T6,具体操作流程看前面的文章。

串口配置

创建任务

点击add即可添加任务并修改参数配置,注意:其中任务的优先级从上往下越来越高,设置成Normal即可,同时Entry Fuction为函数指针,固定格式是Start+函数名字(函数名字首个字母需要大写)

3.3 代码实现

3.3.1 uart.c 重定向printf
#include "stdio.h"
int fputc(int ch,FILE *f)
{
	unsigned char temp[1] = {ch};
	HAL_UART_Transmit(&huart1,temp,1,0xffff);
	return ch;
}

需要打开魔术棒勾上红框内选项实现串口打印

3.3.2 打开freertos.c并添加代码
void StartTaskLED1(void const * argument)
{
  for(;;)
  {
		HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_8);
    osDelay(500);
  }
}
 
void StartTask02(void const * argument)
{
  for(;;)
  {
		HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_9);
    osDelay(1000);
  }
}
 
void StartTaskKey1(void const * argument)
{
  for(;;)
  {
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET)
		{
			osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET)
			{
				printf("KEY1被按下!!!\r\n");
				if(task_LED1Handle == NULL)	//在上面任务创建会返回一个句柄,判断句柄是否为NULL																				
				{
					printf("任务1不存在,准备创建任务1\r\n");	//为NULL说明任务1不存在												
					osThreadDef(task_LED1, StartTask_LED1, osPriorityNormal, 0, 128); //调用上面任务创建函数
					task_LED1Handle = osThreadCreate(osThread(task_LED1), NULL);
					if(task_LED1Handle != NULL)	//此时任务1创建成功,句柄不为NULL																			
						printf("任务1创建完成!\r\n");
				}
				else
				{
					printf("删除任务1!\r\n");
					osThreadTerminate(task_LED1Handle);	//调用删除任务函数,参数为任务返回的句柄															
					task_LED1Handle = NULL;	//手动将句柄置为NULL,否则后面调用到此句柄会有意外					 																
				}
			}
			while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET);	//若按键一直处于按下状态则处于死循环,即松手检测									
		}
    osDelay(10);
  }
 
void StartTaskKey2(void const * argument)
{
	static int flag = 0;	
  for(;;)
  {
		if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET)
		{
			osDelay(20); // 延时消抖
            if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET)
            {
    			printf("Key2 被按下\r\n");
		    	if(flag == 0)
		    	{
			    	osThreadSuspend(TaskLED2Handle);//调用任务挂起函数
			    	printf("任务2被挂起暂停\r\n");
			    	flag = 1;
			    }
			    else
			    {
			    	osThreadResume(TaskLED2Handle);//调用任务恢复函数
			    	printf("任务2重新恢复\r\n");
			    	flag = 0;
		    	}
           }
            while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET);
		}
        osDelay(10);
  }
}

上述代码中:

osThreadTerminate()为删除函数,osThreadSuspend()为挂起函数,osThreadResume()为恢复函数。(这些函数与前面所学的不一样,因为他们都是CubeMX的内置函数)

下图为创建任务后各个任务的句柄和CubeMX创建任务函数。

3.3.4 代码现象

按下KEY1任务1删除(LED1保持不变),再次按下任务1创建(LED1闪烁);按下KEY2任务2挂起(LED2保持不变),再次按下任务2恢复(LED2闪烁)。

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

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

相关文章

家装新宠!装修APP开发解决方案,为业主提供全新装修模式

随着人们对家庭装修的需求度越来越高,装修APP开发也随之出现。如今装修APP开发可实现互联网与传统家装行业的信息结合,由传统的家装行业广告模式向移动端的互联网模式进行转移,实现传统家装行业与互联网的相辅相成,以此来推动家装…

Maven 插件使用

1.spring-boot-maven-plugin 我们直接使用 maven package (maven自带的package打包功能),打包Jar包的时候,不会将该项目所依赖的Jar包一起打进去,在使用java -jar命令启动项目时会报错,项目无法正常启动。…

每日一题8:Pandas-改变数据类型

一、每日一题 编写一个解决方案来纠正以下错误: grade 列被存储为浮点数,将它转换为整数。 返回结果格式如下示例所示。 解答: import pandas as pddef changeDatatype(students: pd.DataFrame) -> pd.DataFrame:students[grade] studen…

Java入门基础学习笔记7——Intellij IDEA开发工具概述、安装

之前的开发工具存在一些问题: 文本编辑工具:记事本、NotePad、EditPlus、Sublime...编写代码的时候没有错误提醒、没有智能代码提示、需要自己进行编译、执行、功能不够强大。 集成开发环境(IDE:Integrated Development Environm…

推荐4个可用的github国内镜像

Github是全球最大的代码托管云平台,超过1亿用户在平台上分享代码及数据,深受生物信息学软件开发者的喜爱,并且现在发表文章,若涉及到代码,编辑还要求我们把代码及数据存放在github上,以便检查数据的真实性和…

matlab使用教程(68)—修改双y轴图的属性

使用 yyaxis 函数可创建一个左右两侧都有 y 轴的 Axes 对象。与 y 轴有关的坐标区属性有两个值。但是,MATLAB 仅允许访问活动侧的值。例如,如果左侧处于活动状态,则 Axes 对象的 YDir 属性包含左侧 y 轴的方向。同样,如果右侧处于…

DIY可视化软件环境准备

DIY官网可视化工具做好的可视化拖拽开发工具无须编程、零代码基础、所见即所得设计工具支持轻松在线可视化导出微信小程序、支付宝小程序、头条小程序、H5、WebApp、UNIAPP等源码 支持组件库,高颜值,卡片,列表,轮播图,导航栏,按钮,标签,表单,单选,复选,下拉选择,多层选择,级联选…

XTuner笔记

为什么要微调: 1. 模型不具备一些私人定制的知识 2。模型回答问题的套路你不满意。 对应衍生出来两种概念 增量预训练微调: 使用场景:让基座模型学习到一些新知识,如某个垂类领域的常识训练数据:文章、书籍、代码等…

Microsoft 365 for Mac v16.84 office365全套办公软件

Microsoft 365 for Mac是一款功能丰富的办公软件套件,为Mac用户提供了丰富的功能和工具,提高了工作效率和协作能力。Microsoft 365 for Mac是一款专为Mac用户设计的订阅式办公软件套件,旨在提高生产力和效率。 Microsoft 365 for Mac v16.84正…

图解HTTP(2、简单的 HTTP 协议)

HTTP 协议用于客户端和服务器端之间的通信 请求访问文本或图像等资源的一端称为客户端,而提供资源响应的一端称为服务器端。 通过请求和响应的交换达成通信 请求必定由客户端发出,而服务器端回复响应报文 请求报文是由请求方法、请求 URI、协议版本、…

ArcGIS10.2能用了10.2.2不行了(解决)

前两天我们的推文介绍了 ArcGIS10.2系列许可到期解决方案-CSDN博客文章浏览阅读2次。本文手机码字,不排版了。 昨晚(2021\12\17)12点后,收到很多学员反馈 ArcGIS10.2系列软件突然崩溃。更有的,今天全单位崩溃。​提示许…

tokenize

源码 def tokenize():eot enc._special_tokens[<|endoftext|>] # end of text tokendata_filename os.path.join(DATA_CACHE_DIR, "tiny_shakespeare.txt")text open(data_filename, r).read()# lets treat every persons statement in the dialog as a se…

mysql中sql语句 exists 判断子句的用法

如果子查询成立才执行父查询 exists判断子查询的使用例子&#xff1a; 张三不存在所以前面的父查询不执行 后面的子句结果存在&#xff0c;所以前面的父查询被执行 where条件所连接的嵌套子查询都是&#xff0c;条件子查询 ———————————————————————…

无人播剧项目怎么做,快手无人播剧全攻略,版权难题一招破解!

相信大家比较关注的问题就是快手无人直播无人播剧到底是不是真的&#xff1f;是不是骗人的&#xff1f;靠不靠谱&#xff1f;是不是真的能赚钱&#xff1f;会不会涉及到版权问题&#xff1f;等等。接下来我就给大家一一做解答&#xff01; 首先关于快手无人播剧是不是骗人的&a…

Python-VBA函数之旅-sorted函数

目录 一、sorted函数的常见应用场景 二、sorted函数使用注意事项 三、如何用好sorted函数&#xff1f; 1、sorted函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a; https://blog.csdn.net/ygb_1024?spm1…

【WEEK11】 【DAY4】Employee Management System Part 5【English Version】

2024.5.9 Thursday Continued from 【WEEK11】 【DAY3】Employee Management System Part 4【English Version】 Contents 10.6. Add Employee10.6.1. Modify list.html10.6.2. Modify EmployeeController.java10.6.3. Create add.html10.6.4. Restart and Run 10.6. Add Emplo…

【Vue3进阶】- Pinia

什么是Pinia Pinia 是 Vue 的专属状态管理库&#xff0c;它允许你跨组件或页面共享状态。它提供了类似于 Vuex 的功能&#xff0c;但比 Vuex 更加简单和直观。 需要在多个组件之间共享状态或数据时使用 Pinia 的 store&#xff0c;这样可以避免 props 和 eventBus 等传统方法…

刷代码随想录有感(62):修建二叉搜索树

题干&#xff1a; 代码&#xff1a; class Solution { public:TreeNode* traversal(TreeNode* root, int low, int high){if(root NULL)return NULL;if(root->val < low)return traversal(root->right, low, high);if(root->val > high)return traversal(ro…

MATLAB 基于格网的点云最低点采样 (69)

MATLAB 基于格网的点云最低点采样 (69) 一、算法原理二、算法实现1.代码2.效果三、数据链接一、算法原理 最低点格网采样是一种基于点云数据的简化技术。它通过将点云数据划分为网格,并在每个网格单元中保留最低的点来实现简化。以下是该方法的步骤: 1 定义格网尺度: 选…

服务智能化公共生活场景人员检测计数,基于YOLOv9系列【yolov9/yolov9-c/yolov9-e】参数模型开发构建公共生活场景下人员检测计数识别系统

在当今社会&#xff0c;随着科技的飞速发展&#xff0c;各种智能化系统已广泛应用于各个领域&#xff0c;特别是在人员密集、流动性大的场合&#xff0c;如商场、火车站、景区等&#xff0c;智能人员检测计数系统发挥着至关重要的作用。特别是在特殊时期&#xff0c;如节假日、…