[FREERTOS] 任务的创建、删除、调度与状态

news2024/11/6 7:19:48

1.什么是任务?

我的理解是:任务像是进程/线程,创建一个任务就会开辟一个空间,每一个任务都是独立的执行相应的动作互不干扰,就比如玩游戏,陪女朋友,任务通常都会有一个while(1)死循环

2.与任务创建和删除相关的的几个方式

·xTaskCreate()---------------------------动态方式创建任务

·xTaskCreateStatic()-------------------静态方式创建任务

·vTaskDeletc()---------------------------删除任务

动态方式和静态方式的区别

动态方式创建任务的堆栈是由系统分配,静态方式创建任务的堆栈是由用户自己传递,通常情况下都是使用动态方式创建

cubeMX创建任务会自动封装函数用的是osThreadCread,F12进去之后可以看到依然是调用xTaskCreate();

 

xTaskCreate()的原型

 在cubeMX中可以创建队列

 

 这个对应的就是xTaskCreate()原型这个结构体

任务的优先级和之前所学的优先级不一样,之前学的比如滴答定时器优先级,外部中断,串口中断这些优先级都是数值越小优先级越高,任务优先级是数值越大优先级越高

pxVreatedTask:用于返回已创建任务的句柄可以被引用

如果返回pdPASS说明任务创建成功

如果返回errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY说明任务创建失败

cubuMx封装的函数 比如一个关于led1的任务:

taskLed2Handle = osThreadCreate(osThread(taskLed2), NULL);

也会返回一个句柄,如果taskLed2Handle == NULL就说明任务不存在 

如果taskLed2Handle != NULL则说明任务已经创建成功,任务存在

删除函数的原型

void vTaskDelete(TaskHandle_t xTasjToDelete);

只需要将待删除的任务的句柄传入函数即可以删除这个任务

当传入的参数为NULL时,就是删除当前运行的任务

 3.任务的调度

FreeRtos开启任务调度的函数是:vTaskStarScheduler(); 但是在cubeMX中被封装为osKernelStart();

 

FreeRtos是一个实时操作系统,任务调度的规则是:

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

抢占式调度用更直白的话来说就是:先执行优先级高的,然后执行优先级略低的,如果正在执行优先级低的,这个时候出现了优先级高的任务,就中断优先级低的任务去执行优先级高的任务,如果优先级最高的任务堵塞(比如使用了延时函数)就执行优先级略低的那个任务,等待优先级最高的任务堵塞结束后重新执行优先级最高的任务

2.同等优先级任务轮转制度(时间片制度)

时间片制度用更直白的话来说就是:1ms执行任务一,1ms执行任务二.........每隔1ms执行下一个任务,如果一个任务只执行了0.5ms就被打断了,下一个任务执行完是不会返回上一个任务执行剩下的0.5ms任务

4.任务的状态

任务一共有四种状态

1.Running运行态:

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

2.Ready就绪态:

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

3.Blocked阻塞态

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

4.Suspend挂起态

类似于暂停,通过调用函数vTaskSuspend();对指定任务进行挂起,挂起后这个任务将不会被执行,除非使用函数vTaskResume()才可以将这个任务从挂起态恢复

 从图标分析可以知道:

        阻塞态没拌饭直接到运行态,只能先到就绪态再到运行态

        阻塞态、就绪态、运行态可以调用函数直接到挂起态,挂起态调用函数只能到就绪态

 做一个任务的小实验:

创建四个任务,taskLed1,taskLed2,taskKey1,taskKey2要求如下:

taskLed1:Led1按500ms的间隔闪烁

taskLed2:Led2按700ms的间隔闪烁

taskKey1:按下Key1如果taskLed1存在则删除taskLed1这个任务,如果任务不存在就创建taskLed1这个任务

taskKey2:按下Key2后挂起taskLed2,再次按下恢复taskLed2

freertos.c

#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include "usart.h"

/*cubeMX配置生成---------------------------------↓*/
/* USER CODE END Includes */

osThreadId taskLed1Handle;
osThreadId taskLed2Handle;
osThreadId taskKey1Handle;
osThreadId taskKey2Handle;

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

void StartTaskLed1(void const * argument);
void StartTaskLed2(void const * argument);
void StartTaskKey1(void const * argument);
void StartTaskKey2(void const * argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/* GetIdleTaskMemory prototype (linked to static allocation support) */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );

/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];

void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
{
  *ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;
  *ppxIdleTaskStackBuffer = &xIdleStack[0];
  *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
  /* place for user code */
}
/*cubeMX配置生成---------------------------------↑*/



/*需要手写代码------------------------------------↓*/
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 */
}

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

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);
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET)//消抖
			{
				printf("Key1\r\n");
				if(taskLed1Handle == NULL)//Led任务进程不存在,所以创建任务进程
				{
					 printf("chuanjianrenwu1\r\n");
					 osThreadDef(taskLed1, StartTaskLed1, osPriorityNormal, 0, 128);
					 taskLed1Handle = osThreadCreate(osThread(taskLed1), NULL);
					 if(taskLed1Handle != NULL)
					 printf("success\r\n");
				}else if(taskLed1Handle != NULL)//Led任务存在,删除任务
				{
					printf("delect\r\n");
					osThreadTerminate(taskLed1Handle);
					taskLed1Handle = NULL;
					printf("over\r\n");
				}
			}	
			while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET);//避免连续按下,等到抬起后才开始下一次扫描 
		}
    osDelay(10);
  }
  /* USER CODE END StartTaskKey1 */
}

void StartTaskKey2(void const * argument)
{
  /* USER CODE BEGIN StartTaskKey2 */
  /* Infinite loop */
	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);//挂起任务2
					printf("suspend success\r\n");
					flag = 1;
				}else if(flag != 0)
				{
					osThreadResume(taskLed2Handle);//恢复任务2
					flag = 0;
					printf("resume success\r\n");
				}
			}	
			while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET);//避免连续按下,等到抬起后才开始下一次扫描 
		}
    osDelay(10);
  }
  /* USER CODE END StartTaskKey2 */
}
/*需要手写代码-----------------------------------↑*/



/*cubeMX配置生成---------------------------------↓*/
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* definition and creation of taskLed1 */
  osThreadDef(taskLed1, StartTaskLed1, osPriorityNormal, 0, 128);
  taskLed1Handle = osThreadCreate(osThread(taskLed1), NULL);

  /* definition and creation of taskLed2 */
  osThreadDef(taskLed2, StartTaskLed2, osPriorityNormal, 0, 128);
  taskLed2Handle = osThreadCreate(osThread(taskLed2), NULL);

  /* definition and creation of taskKey1 */
  osThreadDef(taskKey1, StartTaskKey1, osPriorityNormal, 0, 128);
  taskKey1Handle = osThreadCreate(osThread(taskKey1), NULL);//创建任务会返回一个句柄,如果是NULL就说明任务没有创建成功

  /* definition and creation of taskKey2 */
  osThreadDef(taskKey2, StartTaskKey2, osPriorityNormal, 0, 128);
  taskKey2Handle = osThreadCreate(osThread(taskKey2), NULL);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

}
/*cubeMX配置生成---------------------------------↑*/

 

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

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

相关文章

使用cloudflare代理flask启用https服务

原文来自&#xff1a;使用cloudflare代理flask启用https服务 | 夜空中最亮的星 欢迎大家留言讨论 问题1&#xff1a;使用cloudflare的dns回源服务器的时候&#xff0c;出现了http和https不断反复重定向 问题2: flask只能启用http服务&#xff0c;需要启用https 步骤 服务器&…

浅谈[Linux搭建GitLab私有仓库,并内网穿透实现公网访问]

转载自远控源码文章&#xff1a;Linux搭建GitLab私有仓库&#xff0c;并内网穿透实现公网访问 前言 GitLab 是一个用于仓库管理系统的开源项目&#xff0c;使用Git作为代码管理工具&#xff0c;并在此基础上搭建起来的Web服务。 Gitlab是被广泛使用的基于git的开源代码管理平…

报错解决:Python ‘NoneType‘ object is not subscriptable , 获取到的数据为None,需要保留数据

人生苦短&#xff0c;我用python 爬取某DB电影数据的时候&#xff0c; 在获取内容的时候出现 NoneType object is not subscriptablePython 资料报错交流:点击此处跳转文末名片获取 获取数据的部分代码是&#xff1a; writer_avatars (writers_list[wi][avatars][small]) …

Linux0.11 信号(十二)

系列文章目录 Linux 0.11启动过程分析&#xff08;一&#xff09; Linux 0.11 fork 函数&#xff08;二&#xff09; Linux0.11 缺页处理&#xff08;三&#xff09; Linux0.11 根文件系统挂载&#xff08;四&#xff09; Linux0.11 文件打开open函数&#xff08;五&#xff09…

前端webpack项目性能优化——体积压缩和compression-webpack-plugin的使用

前端webpack项目性能优化——体积压缩和compression-webpack-plugin的使用需求优化结果需求 脚手架搭建的项目&#xff0c;会默认开启sourceMap&#xff0c;此时打包下来的包会很大&#xff0c;如图&#xff1a;map文件比所有js文件都大&#xff0c;会导致包整体体积过大&…

NIFI大数据进阶_Json内容转换为Hive支持的文本格式_操作方法说明_01_EvaluteJsonPath处理器---大数据之Nifi工作笔记0031

然后我们再来看一下如何把json内容,转换成hive支持的文本格式,其实还是一个格式转换对吧 首先看一下用到的处理器,可以看到这里我们用到了evaluateJsonPath处理器,这个处理器用来提取json中的熟悉,然后ReplaceText处理器用来替换掉FlowFile中的属性的内容 首先看一下这个Evalua…

【Python-Conda】Conda操作解读 pip 和 conda 的区别

【Python-Conda】Conda操作解读 & conda与pip的区别 文章目录【Python-Conda】Conda操作解读 & conda与pip的区别1. 介绍2. conda 操作2.1 创建环境2.2 查看conda已创建的环境2.3 删除环境2.3.1 删除虚拟环境中的包2.4 激活&#xff08;失活&#xff09;环境2.4.1 激活…

OpenAI Embedding:快速实现聊天机器人(三)

theme: orange 本文正在参加「金石计划」 接上文OpenAI Embedding&#xff1a;快速实现聊天机器人(二)有讲到聊天机器人的架构和流程&#xff0c;这篇开始通过代码讲讲具体实现。 前言 这篇文章为了降低实现的难度&#xff0c;下图中提供存储和向量相似度搜索的Redis(Redis Sea…

智媒ai在线伪原创-python文本自动伪原创

文章伪原创工具的优势 文章伪原创工具是一类自然语言处理工具&#xff0c;通过对原始文本进行语言转换、替换、重组等方式&#xff0c;生成与原始文本相似但不完全相同的新文本。这种工具的优势主要包括以下几点&#xff1a; 提高工作效率&#xff1a;使用文章伪原创工具可以快…

第三章 传输层

传输层基本服务 传输层核心任务是为应用进程之间提供端到端的逻辑通信服务传输层主要实现功能&#xff1a;传输层寻址、对应用层报文进行分段和重组、对报文进行差错检测、实现进程间的端到端的可靠数据传输控制、面向应用层实现复用与分解、实现端到端的流量控制、拥塞控制 …

C++中的引用

上一次&#xff0c;我们只是浅浅的提了一下引用‘&’&#xff0c;那么今天&#xff0c;我们就正式减少一下引用&#xff0c;以及引用是什么&#xff0c;还有就是引用和指针的区别&#xff0c;引用的特点 首先&#xff0c;我们回顾一下什么是引用&#xff0c;引用就是取别名…

MapReduce原理

MapReduce 编程规范 MapReduce 的开发一共有八个步骤, 其中 Map 阶段分为 2 个步骤&#xff0c;Shuffle 阶段 4 个步骤&#xff0c;Reduce 阶段分为 2 个步骤Map 阶段 2 个步骤 设置 InputFormat 类, 将数据切分为 Key-Value(K1和V1) 对, 输入到第二步自定义 Map 逻辑, 将第一…

十五周算法训练营——链表专题

今天是十五周算法训练营的第三周&#xff0c;主要讲链表专题&#xff0c;包含&#xff1a;反转链表、移除链表、交换链表、链表相交、删除链表中的倒数第N个节点、环形链表II。&#xff08;欢迎加入十五周算法训练营&#xff0c;与小伙伴一起卷算法——文章末尾进群&#xff09…

【我的创作纪念日】恒川的创作一周年

机缘 大家好&#xff0c;我是热爱跑步的恒川&#xff0c;今天是个特殊的日子&#xff08;我的创作纪念日&#xff09;&#xff0c;在去年的今天&#xff0c;我发了第一篇博文。去年的时候&#xff0c;刚接触到CSDN&#xff0c;只想把他当作一个学习的工具&#xff0c;后来&…

Node.js -- Express路由

1.路由的概念 在Express中&#xff0c;路由指的是客户端的请求与服务器处理函数之间的关系。 Express中的路由分为三部分&#xff0c;分别是请求的类型&#xff0c;请求的URL地址和处理函数。格式如下&#xff1a; app.METHOD(PATH,HANDLER)例子如下&#xff1a; // 匹配 GE…

【计算几何3】博物馆问题和相关证明

&#xff08; gallery problem or museum problem &#xff09; Art gallery problem - Wikipedia 一、说明 画廊问题是一个基本的计算几何问题&#xff0c;最现实的反映是&#xff0c;到底对一个场景监视会用到几个摄像头。更深刻的层次是&#xff0c;如何对场景生成地图&am…

C生万物 | 十分钟带你学会位段相关知识

结构体相关知识可以先看看这篇文章 —— 链接 一、什么是位段 位段的声明和结构是类似的&#xff0c;有两个不同&#xff1a; 位段的成员必须是 int、unsigned int 或signed int位段的成员名后边有一个冒号和一个数字 在下面&#xff0c;我分别写了一个结构体和一个位段&…

嵌入式51单片机01-开发版介绍与LED流水灯系列

文章目录1. STC89C52单片机介绍2. 单片机预备知识3. LED灯操作系列1. 点亮LED&#xff08;1&#xff09;LED原理图连接方式&#xff08;2&#xff09; proteus接线图&#xff08;3&#xff09;keil代码2. LED灯闪烁&#xff08;1&#xff09;实验电路图&#xff08;2&#xff0…

每日一题104——转置矩阵

给你一个二维整数数组 matrix&#xff0c; 返回 matrix 的 转置矩阵 。 矩阵的 转置 是指将矩阵的主对角线翻转&#xff0c;交换矩阵的行索引与列索引。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[[1,4,7],[2,5,8],[3,6,9]] 示…

大佬们隔空互怼

阅读本文大概需要 1.14 分钟。1、最近国内各大互联网公司都在掀起一股大模型热潮&#xff0c;要想让这股热潮变得更持久更精彩&#xff0c;离不开互联网大佬们的添砖加瓦。比如上周搜狗的王小川跟百度的肖阳&#xff0c;两位互联网大佬隔空互怼的场景&#xff0c;一度让大家觉得…