【STM32之FreeRTOS(三)】任务的调度与状态

news2024/11/15 12:33:31

【STM32之FreeRTOS(三)】任务的调度与状态

文章目录

  • 【STM32之FreeRTOS(三)】任务的调度与状态
    • 一、什么是任务调度?
    • 二、FreeRTOS的任务调度规则
      • 1.抢占式调度运行过程
      • 2.时间片调度运行过程
    • 三、任务的状态
    • 四、任务综合小实验
      • 1.实验需求
      • 2.CubeMX配置
        • 2.1 配置KEY1,KEY2引脚
        • 2.2 打开串口配置
        • 2.3 创建任务
        • 2.4 串口打印测试
        • 2.5 编写任务函数业务逻辑代码
      • 3.效果演示

一、什么是任务调度?

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

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

二、FreeRTOS的任务调度规则

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

  • 1.高优先级抢占低优先级任务,系统永远执行最高优先级的任务(即抢占式调度)

  • 抢占式调度——比如,陪女朋友 > 玩游戏

  • 2. 同等优先级的任务轮转调度(即时间片调度)

  • 时间片调度——比如,三个好朋友找你打球,陪第一个打1s,再陪等二个打1s,接着陪第三个打1s,依次类推循环

还有一种调度规则是协程式调度,但官方已明确表示不更新,主要是用在小容量的芯片上,用得也不多。


1.抢占式调度运行过程

当优先级更高的任务开始运行后,会去打断运行中的低优先级的任务;

当某个任务进入阻塞态后,会根据优先级去执行其他任务;

在这里插入图片描述

Task 1:玩游戏

Task 2:老妈喊你吃饭

Task 3:女朋友喊你看电视

阻塞:比如女朋友肚子疼上厕所

总结:

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

2.时间片调度运行过程

在这里插入图片描述

Task 1:陪A打1s篮球

Task 2:陪B打1s兵乓球

Task 3:陪C打1s桌球

阻塞:A/B/C肚子痛上厕所(阻塞的时间0.5s就不管了,直接去和下一个人打球)

总结:

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

三、任务的状态

FreeRTOS中任务共存在4种状态:

  • Running 运行态

当任务处于实际运行状态称之为运行态,即CPU的使用权被这个任务占用(同一时间仅一个任务 处于运行态)。

比如,汽车已经在公路上跑起来了

  • Ready 就绪态

处于就绪态的任务是指那些能够运行(没有被阻塞和挂起),但是当前没有运行的任务,因为同优先级或更高优先级的任务正在运行。

比如,汽车加满了油,引擎发动了,就等着一脚油门出发;分时复用,同一个时间只能跑一辆车

  • Blocked 阻塞态

如果一个任务因延时,或等待信号量、消息队列、事件标志组等而处于的状态被称之为阻塞态。

比如,汽车跑着跑着遇到了红灯(调用delay延时);此时进入阻塞,就可以根据优先级安排另一辆汽车出发

  • Suspended 挂起态

类似暂停,通过调用函数vTaskSuspend() 对指定任务进行挂起,挂起后这个任务将不被执行, 只有调用函数 xTaskResume() 才可以将这个任务从挂起态恢复。

比如,车故障了,我们调用vTaskSuspend() 把该辆汽车拿去修理厂维修,暂时就不跑了;等人家调用xTaskResume()告诉我们说修好了才能上路

在这里插入图片描述

总结:

  1. 就绪态可转变成运行态
  2. 其他状态的任务想运行,必须先转变成就绪态

四、任务综合小实验

1.实验需求

创建 4 个任务:taskLED1,taskLED2,taskKEY1,taskKEY2

开发板采用STM32F103C8T6

任务要求如下:

  • taskLED1:间隔 500ms 闪烁 LED1;
  • taskLED2:间隔 1000ms 闪烁 LED2;
  • taskKEY1:如果 taskLED1 存在,则按下 KEY1 后删除 taskLED1 ,否则创建 taskLED1 ;
  • taskKEY2:如果 taskLED2 正常运行,则按下 KEY2 后挂起 taskLED2 ,否则恢复 taskLED2;

2.CubeMX配置

复制一份之前的工程模板(muban_freertos),打开它的CubeMX,再进行下面的操作

2.1 配置KEY1,KEY2引脚

根据自己的开发板原理图来,我这里是PA0和PA1

在这里插入图片描述

在这里插入图片描述

2.2 打开串口配置

在这里插入图片描述

2.3 创建任务

taskLED1,taskLED2可根据上一章的内容直接创建,这里不过多重复

创建taskKEY1

在这里插入图片描述

创建taskKEY2

在这里插入图片描述

2.4 串口打印测试

生成工程代码后,打开工程编写串口代码

/* USER CODE BEGIN 0 */
#include "stdio.h"
int fputc(int ch,FILE *f)
{	
	unsigned char temp[1] = {ch};
	HAL_UART_Transmit(&huart1,temp,1,0xffff);
	return ch;
}
/* USER CODE END 0 */

在这里插入图片描述

打开库设置,并勾选✔

在这里插入图片描述

在这里插入图片描述

可以在main.c里测试一下,串口打印是否成功

使用打印函数printf()

在这里插入图片描述

引入头文件

#include “stdio.h”

在这里插入图片描述

串口接线

STM32F103C8T6串口调试模块
PA9RX
PA10TX
3.3V/5V3.3V/5V
GNDGND

编译后烧录,测试成功

在这里插入图片描述

2.5 编写任务函数业务逻辑代码

在freertos.c下去编写代码

FreeRTOS帮我们创建好了4个任务

在这里插入图片描述

实现TaskLED1和TaskLED2

在这里插入图片描述

/* USER CODE END Header_StartTaskLED1 */
void StartTaskLED1(void const * argument)
{
  /* USER CODE BEGIN StartTaskLED1 */
  /* Infinite loop */
  for(;;)
  {
		HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);
    osDelay(500); //ms
  }
  /* USER CODE END StartTaskLED1 */
}

/* USER CODE END Header_StartTaskLED2 */
void StartTaskLED2(void const * argument)
{
  /* USER CODE BEGIN StartTaskLED2 */
  /* Infinite loop */
  for(;;)
  {
		HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);
    osDelay(1000);
  }
  /* USER CODE END StartTaskLED2 */
}

实现TaskKEY1

在这里插入图片描述

/* USER CODE END Header_StartTaskKEY1 */
void StartTaskKEY1(void const * argument)
{
  /* USER CODE BEGIN StartTaskKEY1 */
  /* Infinite loop */
  for(;;)
  {
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET){
			//软件实现简单防抖
			osDelay(20);   //20ms
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET){
				printf("KEY1被按下!\r\n");
				if(taskLED1Handle == NULL){
					printf("任务1!不存在\r\n");
					printf("开始创建任务1!\r\n");
					osThreadDef(taskLED1, StartTaskLED1, osPriorityNormal, 0, 128);
					taskLED1Handle = osThreadCreate(osThread(taskLED1), NULL);		
					if(taskLED1Handle!= NULL){
						printf("任务1创建完成!\r\n");
					}
				}
				else{
					printf("开始删除任务1!\r\n");
					osThreadTerminate(taskLED1Handle);
					//手动将句柄置为NULL
					taskLED1Handle = NULL;
					printf("任务1删除成功!\r\n");
				}
			}
			while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET);
		}
    osDelay(10);

  }
  /* USER CODE END StartTaskKEY1 */

实现TaskKEY2

在这里插入图片描述

/* USER CODE END Header_StartTaskKEY2 */
void StartTaskKEY2(void const * argument)
{
  /* USER CODE BEGIN StartTaskKEY2 */
	static int flag = 0;
  /* Infinite loop */
  for(;;)
  {
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET){
			//软件实现简单防抖
			osDelay(20);   //20ms
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET){
				printf("KEY2被按下!\n");
				if(flag == 0){
					//任务2挂起
					osThreadSuspend(taskLED2Handle);
					printf("任务2已挂起(暂停)!\n");
					flag = 1;
				}
				else{
					osThreadResume(taskLED2Handle);
					printf("任务2恢复!\n");
					flag = 0;
				}
			}
			while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET);
		}
    osDelay(10);
  }
  /* USER CODE END StartTaskKEY2 */
}

到此完成业务代码编写,可以进行编译烧录了

3.效果演示

编译烧录重启后,蓝灯0.5s翻转一次,黄灯1s翻转一次

当按下KEY1,蓝灯任务被删除,蓝灯状态停滞,同时串口有删除任务信息

在这里插入图片描述

当再次按下KEY1,蓝灯任务再次被创建,任务执行,蓝灯0.5s翻转一次,同时串口有创建任务信息

在这里插入图片描述

当按下KEY2,黄灯任务被挂起(暂停),黄灯状态停滞,同时串口有挂起(暂停)任务信息

在这里插入图片描述

当按下KEY2,黄灯任务恢复,黄灯1s翻转一次,同时串口有恢复任务信息

在这里插入图片描述

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

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

相关文章

学生护眼台灯哪个品牌好?一文教会你如何挑选学生护眼台灯

台灯作为我们日常生活中重要的桌面照明工具,对于办公族的工作和学生的学习都扮演着关键角色。长期使用质量不佳的台灯可能会对我们的视力健康造成不利影响,尤其是对于眼睛尚在发育阶段的学生来说,这种影响更为显著。因此,在选择台…

表字段如何设计,如何打标签,如何进行维度分组,关于优先级排序如何处理(大数据开发)

今天分享一篇,热腾腾的实战,关于在数据开发中,表字段如何设计,如何打标签,如何进行维度分组,关于优先级排序如何处理??? 1,表字段如何设计 首先&#xff0c…

RPG Maker MZ中被你忽略的干货操作——事件页优先级

文章目录 事件页优先级问题结论问题1答案 事件页优先级问题 结论 事件页2的优先级是大于事件页1的 问题1 事件页1没有条件、自动执行生成图片,效果如下 事件页2,没有条件,自动执行,效果如下 答案 只会执行事件页2&#…

数据库索引推荐大PK,DBdoctor和资深DBA的终极较量

前言 在上一篇文章《端午特别篇:你真的了解数据库索引吗?》中,纪宽针对一个业务SQL推荐索引优化问题提出了疑问。他发现DBdoctor推荐的索引组合(status, purchase_date,device_name, device_id)似乎与他作为DBA凭借多…

vue element-ui 下拉框 以及 input 限制输入,小数点后保留两位 界面设计案例 和 例子:支持mp4和m3u8视频播放

vue input 限制输入,小数点后保留两位 以及 图片垂直居中显示 和 分享 git 小技巧-CSDN博客文章浏览阅读430次,点赞5次,收藏4次。error:Your local changes to the following files would be overwritten by merge:_error: your local change…

传神社区|数据集合集第3期|中文NLP数据集合集

自从ChatGPT等大型语言模型(Large Language Model, LLM)出现以来,其类通用人工智能(AGI)能力引发了自然语言处理(NLP)领域的新一轮研究和应用浪潮。尤其是ChatGLM、LLaMA等普通开发者都能运行的…

计算机SCI期刊,中科院3区,IF=3.4,难度不大,无预警风险

一、期刊名称 Automated Software Engineering 二、期刊简介概况 期刊类型:SCI 学科领域:计算机科学 影响因子:3.4 中科院分区:3区 三、期刊征稿范围 自动化软件工程是一份档案,同行评审的期刊,发表研…

网络故障排除:保持网络稳定与业务连续

目录 什么是网络故障? 网络故障排除的基本步骤 1. 问题识别 2. 确定故障范围 3. 检查物理连接 4. 检查设备配置 5. 测试与诊断 6. 实施解决方案 7. 验证与监控 了解更多 在现代企业中,网络的稳定性和性能直接影响业务的连续性和效率。作为一名…

算法day26

第一题 429. N 叉树的层序遍历 本题的要求我们可以通过队列来辅助完成层序遍历; 如下图的n叉树: 步骤一: 我们定义一个队列,先进行根节点入队列操作; 步骤二: 我们进行当前队列每一个元素的出队列操作&…

复旦大学首本大模型中文书太厉害啦!【大模型书籍推荐】

前言 在信息爆炸的时代,自然语言处理(NLP)技术如同璀璨的星辰,照亮了我们与机器沟通的道路。而今,复旦大学自然语言处理实验室的教授团队,如同航海家般,为我们带来了一本指引大语言模型领域前行…

[Java基础揉碎]网络相关概念

目录 网络通信 网络 ip地址 ​编辑 域名 ​编辑 网络协议 TCP和UDP 网络编程比较重要的的InetAddress类 Socket ​编辑 tcp字节流编程 案例一 案例二​编辑 案例三 网络上传文件 ​编辑​编辑 ​编辑 netstat tcp网络通信客户端也是通过端口和服务端进行通讯的…

python怎么保留小数

保留两位小数,并做四舍五入处理 方法一:使用字符串格式化 a 12.345 print("%.2f" % a)# 12.35 方法二:使用round内置函数 a 12.345 a1 round(a, 2) print(a1)# 12.35 方法三:使用decimal模块 from decimal import D…

每日一题39:甲板上的战舰

一、每日一题 题意 这题的标题应该是《棋盘上的战舰》,来源于 海战棋,把横着或竖着的连续 X 看成一艘战舰,统计棋盘上有多少艘战舰。 思路 战舰的个数,等于战舰「头部」的个数。如下图,我们只需要统计蓝色 X 的个数&…

LLM应用实战:当图谱问答(KBQA)集成大模型(三)

1. 背景 最近比较忙(也有点茫),本qiang~想切入多模态大模型领域,所以一直在潜心研读中... 本次的更新内容主要是响应图谱问答集成LLM项目中反馈问题的优化总结,对KBQA集成LLM不熟悉的客官可以翻翻之前的文章《LLM应用实战:当KBQ…

Android 14 系统启动流程 之 启动init进程、启动Zygote进程

Android 14 系统启动流程 之 启动init进程、启动Zygote进程 废话不多说,先上图,不清楚的可以在评论区留言。

计算机体系结构学习(一)

计算机体系结构的发展 20 世纪五六十年代, 由于工艺技术的限制, 计算机都做得很简单, 计算机体系结构主要研究怎么做加减乘除, Computer Architecture 基本上等于 Computer Arithmetic。 20 世纪七八十年代的时候, 以精简指令集 (Reduced Instruction Set Computer, 简称 RISC…

AI大模型战场:通用大模型与垂直大模型的角逐

随着人工智能技术的迅猛发展,AI大模型已成为推动科技进步的重要力量。然而,在AI大模型的战场上,通用大模型与垂直大模型之间的分化日益明显。两者各有其独特的优势和潜力,在不同的应用场景中发挥着重要作用。那么,在这…

SSM 离散数学线上考试系统-计算机毕业设计源码83059

摘 要 随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,高校当然也不例外。离散数学线上考试系统是以实际运用为开发背景,运用软件工程原理和开发方法,采…

centos下创建raid6磁盘阵列

在CentOS系统中创建RAID 6阵列,可以使用mdadm工具。 以下是创建RAID 6阵列的基本步骤和示例代码: 安装mdadm工具(如果尚未安装): sudo yum install mdadm 假设你有至少四个以上的磁盘设备(例如 /dev/sdi…

信创4.0|暴雨出席空间智能软件技术交流会

6月19日,由自然资源部地理信息系统技术创新中心、中国测绘学会软件与信息技术服务工委会、内蒙古自治区测绘学会共同主办的“空间智能软件技术交流会暨自然资源数字化治理交流会”在呼和浩特举办,500余位嘉宾汇聚一堂,就空间智能赋能数字经济…