FreeRTOS的任务详解、创建与删除

目录

1、任务详解

1.1 什么是任务?

1.2 任务的特点

1.3 任务的状态

1.4 任务的优先级

1.5 任务的堆和栈

2、任务的创建与删除

2.1 相关API

2.2 函数解析

2.2.1 xTaxkCreate()

2.2.2 xTaskCreateStatic()

2.2.3 vTaskDelete()

3、实战案例

3.1 创建两个任务

3.2 配置LED引脚

3.3 相关代码


1、任务详解

1.1 什么是任务?

任务可以理解为进程/线程,创建一个任务,就会在内存开辟一个空间。

比如: 玩游戏、陪女朋友,都可以视为任务;Windows 系统中的 MarkText 、谷歌浏览器、记事本,都是任务。

在 FreeROTS 中,任务可以分配不同的优先级,并按照优先级进行调度。当一个任务没有工作可以做时,操作系统会将 CPU 时间分配给另一个优先级更高的任务,以确保系统的正常运行。

1.2 任务的特点

  1. 简单
  2. 没有使用限制
  3. 支持抢占
  4. 支持优先级
  5. 每个任务都拥有堆栈导致了 RAM 使用量增大
  6. 如果使用抢占的话的必须仔细的考虑重入的问题 

1.3 任务的状态

  • 运行态

        当一个任务正在运行时,那么就说这个任务处于运行态,处于运行态的任务就是当前正在使用处理器的任务。如果使用的是单核处理器的话那么不管在任何时刻永远都只有一个任务处于运行态。

  • 就绪态

        处于就绪态的任务是那些已经准备就绪(这些任务没有被阻塞或者挂起),可以运行的任务,
但是处于就绪态的任务还没有运行,因为有一个同优先级或者更高优先级的任务正在运行!

  • 阻塞态

        如果一个任务当前正在等待某个9外部事件的话就说它处于阻塞态,比如说如果某个任务调
用了函数 vTaskDelay()的话就会进入阻塞态,直到延时周期完成。任务在等待队列、信号量、事
件组、通知或互斥信号量的时候也会进入阻塞态。任务进入阻塞态会有一个超时时间,当超过
这个超时时间任务就会退出阻塞态,即使所等待的事件还没有来临!

  • 挂起态

        像阻塞态一样,任务进入挂起态以后也不能被调度器调用进入运行态,但是进入挂起态的任务没有超时时间。任务进入和退出挂起态通过调用函数 vTaskSuspend()和 xTaskResume()。

任务状态之间的转换如图

1.4 任务的优先级

每个任务都可以分配一个从0~(configMAX_PRIORITIES-1) 的优先级, configMAX_PRIORITIES 在文件 FreeRTOSConfig.h 中有定义,一共设置了32个优先级。

注意:数字越大,优先级约高,0为最低优先级

1.5 任务的堆和栈

FreeRTOS 之所以能正确的恢复一个任务的运行就是因为有任务堆栈在保驾护航,任务调度器在进行任务切换的时候会将当前任务的现场(CPU 寄存器值等)保存在此任务的任务堆栈中,等到此任务下次运行的时候就会先用堆栈中保存的值来恢复现场,恢复现场以后任务就会接着从上次中断的地方开始运行。

创建任务的时候需要给任务指定堆栈,如果使用的函数 **xTaskCreate()**创建任务(动态方法)的话那么任务堆栈就会由函数 xTaskCreate()自动创建。如果使用函数 **xTaskCreateStatic()**创建任务(静态方法)的话就需要程序员自行定义任务堆栈,然后堆栈首地址作为函数的参数 puxStackBuffer 传递给函数,如下:

TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
 								const char * const pcName,
 								const uint32_t ulStackDepth,
 								void * const pvParameters,
 								UBaseType_t uxPriority,
 								StackType_t * const puxStackBuffer, //在这里
 								StaticTask_t * const pxTaskBuffer )

2、任务的创建与删除

2.1 相关API

                                函数名称                                 函数作用
xTaskCreate()动态方式创建任务
xTaskCreateStatic()静态方式创建任务
vTaskDelete()删除任务

动态创建任务与静态创建任务的区别:动态创建任务的堆栈由系统分配,而静态创建任务的堆栈由用户自己传递(分配)。 通常情况下使用动态方式创建任务。

2.2 函数解析

2.2.1 xTaxkCreate()

此函数用来创建一个任务,任务需要 RAM 来保存与任务有关的状态信息(任务控制块),任务也需要一定的 RAM 来作为任务堆栈。如果使用函数xTaskCreate()来创建任务的话那么这些所需的 RAM就会自动的从FreeRTOS的堆中分配,因此必须提供内存管理文件,默认我们使用heap_4.c 这个内存管理文件,而且宏 configSUPPORT_DYNAMIC_ALLOCATION 必须为 1

新创建的任务默认就是就绪态的如果当前没有比它更高优先级的任务运行那么此任务就会立即进入运行态开始运行,不管在任务调度器启动前还是启动后,都可以创建任务。此函数也是我们以后经常用到的。

1. pxTaskCode:指向任务函数的指针,任务必须实现为永不返回(即连续循环);

2. pcName:任务的名字,主要是用来调试,默认情况下最大长度是16;

3. pvParameters:指定的任务栈的大小;

4. uxPriority:任务优先级,数值越大,优先级越大;

5. pxCreatedTask:用于返回已创建任务的句柄可以被引用。

                        返回值                      描述                
pdPASS任务创建成功
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY任务创建失败

官方案例:

/* Task to be created. */
void vTaskCode( void * pvParameters )
{
    /* The parameter value is expected to be 1 as 1 is passed in the
    pvParameters value in the call to xTaskCreate() below.
    configASSERT( ( ( uint32_t ) pvParameters ) == 1 );
    for( ;; )
    {
        /* Task code goes here. */
    }
}
/* Function that creates a task. */
void vOtherFunction( void )
{
    BaseType_t xReturned;
    TaskHandle_t xHandle = NULL;
    /* Create the task, storing the handle. */
    xReturned = xTaskCreate(
                    vTaskCode, /* Function that implements the task. */
                    "NAME", /* Text name for the task. */
                    STACK_SIZE, /* Stack size in words, not bytes. */
                    ( void * ) 1, /* Parameter passed into the task. */
                    tskIDLE_PRIORITY,/* Priority at which the task is created. */
                    &xHandle ); /* Used to pass out the created task's handle. */
    if( xReturned == pdPASS )
    {
        /* The task was created. Use the task's handle to delete the task. */
        vTaskDelete( xHandle );
    }
}
2.2.2 xTaskCreateStatic()

使用此函数创建的任务所需的RAM需要用户来提供 。

如果要使用此函数的话需要将宏configSUPPORT_STATIC_ALLOCATION定义为1。

	StackType_t StartTaskStack[START_STK_SIZE];			//任务堆栈
	
	xTaskCreateStatic((TaskFunction_t	)start_task,		//任务函数
					  (const char* 	)"start_task",		    //任务名称
					  (uint32_t 		)START_STK_SIZE,	//任务堆栈大小
					  (void* 		  	)NULL,				//传递给任务函数的参数
					  (UBaseType_t 	)START_TASK_PRIO, 	    //任务优先级
					  (StackType_t*   )StartTaskStack,	    //任务堆栈
					  (StaticTask_t*  )&StartTaskTCB);	    //任务控制块
	vTaskStartScheduler();          //开启任务调度 

函数返回值就是任务句柄

2.2.3 vTaskDelete()
void vTaskDelete(TaskHandle_t xTaskToDelete);

只需将待删除的任务句柄传入该函数,即可将该任务删除。

当传入的参数为NULL,则代表删除任务自身(当前正在运行的任务)。

任务被删除以后就不能再使用此任务的句柄:如果此任务是使用动态方法创建的,也就是使用函数 xTaskCreate()创建的,那么在此任务被删除以后,此任务之前申请的堆栈和控制块内存会在空闲任务中被释放掉,因此当调用函数 vTaskDelete()删除任务以后必须给空闲任务一定的运行时间。

用户分配给任务的内存需要用户自行释放掉:比如某个任务中用户调用函数 pvPortMalloc()分配了 500 字节的内存,那么在此任务被删除以后用户也必须调用函数 vPortFree()将这 500 字节的内存释放掉,否则会导致内存泄露

3、实战案例

这里创建两个任务进行点灯,其中两个任务对应的点灯速率不同。

3.1 创建两个任务

这里直接讲述使用Cubemx创建任务的操作,关于FreeRTOS移植到STM32F103C8T6可查看上一篇文章FreeRTOS介绍-CSDN博客

点击Middleware找到FreeRTOS,点击Task and Queues

进行创建任务配置

配置任务1

配置任务2

3.2 配置LED引脚

查看板子原理图,得到LED的引脚编号

引脚配置

3.3 相关代码

打开freertos.c

//找到设置的任务函数名称,在其中的循环中进行代码改写
void StartTaskLED1(void const * argument)
{
  for(;;)
  {
	HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);
    osDelay(500);
  }
}
 
void StartTaskLED2(void const * argument)
{
  for(;;)
  {
	HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);
    osDelay(1000);
  }
}

最终LED1以500ms闪烁,LED2以1s闪烁。

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

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

相关文章

达梦数据刷盘测试

达梦数据库为了保证数据故障恢复的一致性,REDO 日志的刷盘必须在数据页刷盘之前进行。 下面我们通过测试来验证是不是这样 执行我们事先准备的SHELL脚本 可以看到第一次strings文件没有输出,说明刚写的数据在数据库的BUFFER缓冲区内,还没有刷…

RN阴影组件使用

yarn add react-native-shadow yarn add react-native-svg // 这个是必须的,阴影依赖这个包四周都有阴影,如下设置 import React from react; import {StyleSheet, View, Text} from react-native; import {BoxShadow} from react-native-shadow;const App () > {const …

3GBJ5016A-ASEMI电焊机专用3GBJ5016A

编辑:ll 3GBJ5016A-ASEMI电焊机专用3GBJ5016A 型号:3GBJ5016A 品牌:ASEMI 封装:3GBJ-5 正向电流(Id):50A 反向耐压(VRRM):1600V 正向浪涌电流&#xf…

“找不到mfcm80u.dll”错误怎么办?一文了解原因和解决办法!

在使用Windows操作系统时,许多用户可能会遇到各种DLL文件缺失或损坏的问题。其中,“找不到mfc80u.dll”错误就是比较常见的一种。 下面小编就给大家分享出现“找不到mfc80u.dll”错误的原因和解决办法,帮助您快速解决此问题。 一、mfc80u.dl…

漏洞管理是如何在攻击者之前识别漏洞从而帮助人们阻止攻击的

漏洞管理 是主动查找、评估和缓解组织 IT 环境中的安全漏洞、弱点、差距、错误配置和错误的过程。该过程通常扩展到整个 IT 环境,包括网络、应用程序、系统、基础设施、软件和第三方服务等。鉴于所涉及的高成本,组织根本无法承受网络攻击和数据泄露。如果…

mysql数据库调优篇章1

目录 1.认识数据库中日志的作用2.增加mysql数据库中my.ini 基本配置3.增加my.ini中参数配置4.查看已经执行过的sql语句过去执行时间5.找出慢查询的sql6. SHOW VARIABLES LIKE ‘innodb_read_io_threads’; SHOW VARIABLES LIKE ‘innodb_write_io_threads’; SHOW VARIABLES LI…

森林消防—高扬程水泵,高效、稳定、可靠!/恒峰智慧科技

森林,作为地球的“绿色肺叶”,不仅为我们提供了丰富的自然资源,更是维持生态平衡的重要一环。然而,随着全球气候的变化和人为活动的增加,森林火灾频发,给生态环境和人民生命财产安全带来了巨大威胁。在森林…

17 空闲空间管理

目录 假设 底层机制 分割与合并 追踪已分配空间的大小 嵌入空闲列表 让堆增长 基本策略 最优匹配 首次匹配 下次匹配 其他方式 分离空闲列表 伙伴系统 小结 分页是将内存成大小相等的内存块,这样的机制下面,很容易去管理这些内存&#xff0c…

代码随想录Day 37|Leetcode|Python|● 1049. 最后一块石头的重量 II ● 494. 目标和 ● 474.一和零

1049. 最后一块石头的重量 II 有一堆石头&#xff0c;用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x < y。那么粉碎的可能结…

【C++】详解STL容器之一的deque和适配器stack,queue

目录 deque的概述 deque空间的结构 deque的迭代器 deque的数据设计 deque的优缺点 适配器的概念 ​编辑 stack的概述 stack的模拟实现 queue的概述 queue的模拟实现 deque的概述 deque的设计参考了另外两大容器vector和list。可参考下面两篇文章 详解vector&#x…

Java 语法 (杂七杂八的知识)

面向对象三大特性 封装, 多态, 继承 基本数据类型 一字节 (Byte) 占八位 (bit) JDK, JRE, JVM JDK (Java Development Kit) : Java 开发工具包, 包括了 JRE, 编译器 javac, 和调试工具 Jconsole, jstack 等 JRE (Java Runtime Environment) : Java 运行时环境, 包括了 JVM , …

ssm115乐购游戏商城系统+vue

毕业生学历证明系统 设计与实现 内容摘要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统毕业生学历信息管理难…

【Linux系统】进程控制

再次理解进程 进程&#xff1a;内核的相关管理数据结构(task_struct(进程控制块PCB)&#xff0c;mm_struct(地址空间)&#xff0c;页表) 代码和数据 那么如何理解进程具有独立性&#xff1f; 我们之前已经学习过进程控制块啊&#xff0c;地址空间啊&#xff0c;页表啊&…

什么是期货?期货的基础知识有哪些?

期货是一种标准化的远期合约&#xff0c;允许买卖双方在未来特定时间以预定价格交易货物或金融资产。也是一种金融衍生品&#xff0c;它为市场参与者提供了一种管理价格波动风险和进行投资的工具。 期货的基础知识有哪些 期货市场是一个复杂的金融环境&#xff0c;对于初学者来…

程序猿敲代码费脑掉头发?来看看铁打的便捷,Baidu Comate智能代码助手

前言&#xff1a;Baidu Comate 前世今生 Baidu Comate 安装教程 官网安装教程 手动安装教程 登录使用 插件功能初体验 代码生成指令板块 简易代码生成 代码解释 代码补充 代码注释 多种类智能问答&知识集调用 Paddle团队官方知识集 前言&#xff1…

设计模式(2)——工厂方法模式

目录 1. 摘要 2. 需求案例(设计一个咖啡店的点餐系统) 2.1 咖啡父类及其子类 2.2 咖啡店类与咖啡类的关系 3. 普通方法实线咖啡店点餐系统 3.1 定义Coffee父类 3.2 定义美式咖啡类继承Coffee类 3.3 定义拿铁咖啡继承Coffee类 3.4 定义咖啡店类 3.5 编写测试类 4. 简…

影响视频视觉质量的因素——各类视觉伪影

模糊效应&#xff08;Blurring Artifact&#xff09; 图像模糊&#xff08;blurring&#xff09;&#xff1a;平滑图像的细节和边缘产生的现象&#xff0c;模糊对于图像来说&#xff0c;是一个低通滤波器&#xff08;low-pass filter&#xff09;。一般而言&#xff0c;用户更…

VisualGDB:Linux静态库项目创建、编译及库的使用

接上篇《VisualGDB&#xff1a;Linux动态库项目创建、编译及库的使用》&#xff0c;静态库的创建和使用与动态库基本无差别&#xff0c;唯一需要做的就是指定项目生成静态库。 一、指定项目生成静态库 二、重新构建和编译项目 这里注意&#xff0c;同样要copy一个libxxx.so格式…

服务器数据恢复—RAID5磁盘阵列两块盘离线的数据恢复过程

服务器故障&#xff1a; 服务器中有一组由多块硬盘组建的raid5磁盘阵列&#xff0c;服务器阵列中2块硬盘先后掉线导致服务器崩溃。 服务器数据恢复过程&#xff1a; 1、将故障服务器中所有磁盘编号后取出&#xff0c;由硬件工程师对掉线的两块磁盘进行物理故障检测&#xff0c…

Linux 文件

文章目录 文件操作回顾(C/C)系统调用接口 管理文件认识一切皆文件C/C的文件操作函数与系统调用接口的关系……重定向与缓冲区 -- 认识重定向与缓冲区 -- 理解使用重定向缓冲区实现一个简单的Shell(加上重定向)标准输出和标准错误(在重定向下的意义) 磁盘文件磁盘存储文件操作系…