FreeRTOS学习笔记—任务挂起和恢复

文章目录

  • 一、任务挂起和恢复API函数
    • 1.1 vTaskSuspend()函数
    • 1.2 vTaskResume()函数
    • 1.3 xTaskResumeFromISR()函数
  • 二、任务挂起和恢复
    • 2.1 任务1挂起解挂任务2
    • 2.2 中断中解挂任务1
  • 三、补充内容
    • 3.1 FreeRTOS数据类型
    • 3.2 中断优先级分组
    • 3.3 错误问题

一、任务挂起和恢复API函数

在项目中有时我们会遇到某些任务需要暂停一段时间,过一段时间在重新运行的情况。任务挂起和恢复就满足了这种需求。当某个任务需要暂停一段时间时,可以将其挂起。当需要重新运行时,再恢复就可以了。。FreeRTOS 的任务挂起和恢复API函数如下

任务恢复和挂起API函数

1.1 vTaskSuspend()函数

该函数的功能是于将某个任务设置为挂起态。任务进入挂起态后,就永远都不会进入运行态。除非调用任务恢复函数 vTaskResume()或 xTaskResumeFromISR()。任务挂起函数有以下输入参数

  • xTaskToSuspend
    要挂起的任务的任务句柄。如果需要挂起任务自身,该参数写NULL。

任务挂起函数无返回值。

1.2 vTaskResume()函数

该函数的功能是将一个任务从挂起态恢复到就绪态。任务恢复函数有以下输入参数

  • xTaskToResume
    需要恢复的任务的任务句柄。

任务恢复函数也没有返回值。

1.3 xTaskResumeFromISR()函数

该函数的功能是在中断服务函数中恢复一个任务。该函数有以下输入参数

  • xTaskToResume
    要恢复的任务的任务句柄。

该函数有以下返回值

  • pdTRUE
    恢复运行的任务的任务优先级等于或者高于正在运行的任务(被中断打断的任务),这意味着在退出中断服务函数以后必须进行一次上下文切换。
  • pdFALSE
    恢复运行的任务的任务优先级低于当前正在运行的任务(被中断打断的任务),这意味着在退出中断服务函数的以后不需要进行上下文切换。

二、任务挂起和恢复

2.1 任务1挂起解挂任务2

任务创建可以见上一篇,任务创建与删除。这里直接修改任务1。任务1修改为,运行10次任务1之后,将任务2挂起。再运行10次后,解挂任务2。任务1函数如下

void taks1_task (void *pxCreatedTask)
{u8 task1Cunt = 0;   // 任务1运行次数计数变量while (1){task1Cunt = task1Cunt + 1;   // task1运行次数加1Med_Led_StateReverse(LED0);   // LED0状态取反vTaskDelay(500);   // 延时500ms// 运行5次后if (task1Cunt == 10){// 挂起任务2vTaskSuspend(TASK2Task_Handler);}if (task1Cunt == 20){// 解挂任务2vTaskResume(TASK2Task_Handler);}}
}

2.2 中断中解挂任务1

最开始尝试在外部中断中挂起和解挂任务1,发现挂起任务1时,程序异常。查询后发现,在中断中不能使用挂起函数。因此调整了一下,任务2运行5次后,挂起任务1。通过外部中断,解挂任务1。

在中断中解挂任务时注意,需要判断一下函数xTaskResumeFromISR()的返回值。如果函数xTaskResumeFromISR()返回值为pdTRUE,那么说明要恢复的这个任务的任务优先级等于或者高于正在运行的任务(被中断打断的任务),所以在退出中断的时候一定要进行上下文切换

外部中断程序配置如下

/**==============================================================================*函数名称:Exit_Init*函数功能:初始化外部中断*输入参数:无*返回值:无*备  注:无*==============================================================================*/
void Exit_Init (void)
{NVIC_InitTypeDef NVIC_InitStructure;EXTI_InitTypeDef  EXTI_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);   // 开启AFIO时钟GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);   //选择GPIO管脚用作外部中断线路//EXTI0 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;   //EXTI0中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=6;   //抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;   //子优先级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   //IRQ通道使能NVIC_Init(&NVIC_InitStructure);	   //根据指定的参数初始化VIC寄存器EXTI_InitStructure.EXTI_Line=EXTI_Line0;   // EXIT0EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;   // 中断EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;   // 上升沿触发EXTI_InitStructure.EXTI_LineCmd=ENABLE;   // 使能EXTI_Init(&EXTI_InitStructure);
}

外部中断的中断服务函数如下

/**==============================================================================*函数名称:EXTI0_IRQHandler*函数功能:外部中断0中断服务函数*输入参数:无*返回值:无*备  注:无*==============================================================================*/// 任务1的任务句柄
extern TaskHandle_t TASK1Task_Handler;void EXTI0_IRQHandler(void)
{BaseType_t YieldRequired;	// 如果EXIT0中断标志位被置1if(EXTI_GetITStatus (EXTI_Line0)==1){YieldRequired = xTaskResumeFromISR(TASK1Task_Handler);   // 恢复任务1if(YieldRequired == pdTRUE){// 执行一次任务调度portYIELD_FROM_ISR(YieldRequired);}}EXTI_ClearITPendingBit (EXTI_Line0);   // 清除中断标志位
}

三、补充内容

3.1 FreeRTOS数据类型

在portmacro.h头文件,里面定义了2个数据类型

  • TickType_t
    FreeRTOS中断计数值类型,可以是16位也可以是32位,对于32位CPU来说TickType_t最好为32位。
  • BaseType_t
    能够让CPU运行效率最高的数据类型。对于32位CPU,BaseType_t就是uint32_t 。16位CPU就是uint16_t ,8位CPU就是uint8_t 。

3.2 中断优先级分组

优先级分组:中断控制器(NVIC)允许定义每个中断优先级的比特被分割成定义中断的优先级比特和定义中断的次优先级比特。为简单起见,必须将所有位定义为抢占优先位。如果不是这样(如果某些位表示次优先级),下面的断言将失败。

简单来说,就是在设置优先级分组时,需要将全部的位都设置为抢占优先级。否则会导致程序异常。

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);   // 设置系统中断优先级分组4	

3.3 错误问题

在编译时发现有下面的错误提示

错误提示

该错误是因为“task.h”必须出现在“FreeRTOS.h”下面。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入理解Go语言中的并发编程【27】【Goroutine的使用、定时器、select】

文章目录 Goroutine池worker pool(goroutine池) 定时器定时器 selectselect多路复用 Goroutine池 worker pool(goroutine池) 本质上是生产者消费者模型可以有效控制goroutine数量,防止暴涨需求: 计算一个…

瑞吉外卖-Day01

title: 瑞吉外卖-Day01 abbrlink: ‘0’ date: 2023-04-1 18:00:00 瑞吉外卖-Day01 课程内容 软件开发整体介绍 瑞吉外卖项目介绍 开发环境搭建 后台登录功能开发 后台退出功能开发 1. 软件开发整体介绍 作为一名软件开发工程师,我们需要了解在软件开发过程中的开发流…

从小白到大神之路之学习运维第53天--------tomcat-web应用——————供开发的商城框架

第三阶段基础 时 间:2023年7月5日 参加人:全班人员 内 容: Tomcat应用服务 WEB服务 目录 实验环境:(四台服务器) 安装tomcat服务: NginxTomcat 负载均衡集群部署: 安装ng…

Python 利用深度学习识别空间推理验证码(一)

注意:本文会比较长,因为空间推理验证码本身比较复杂,我会详细的讲解,我是如何一步一步拆分空间推理的思想去实现的,另外,这里只介绍第一种思想来解决空间推理验证码,实际上,解决该验证码的方法也比较多,这第一种,我会讲解的比较简单,通俗易懂。 注意:下面数据集使用…

HttpRunner自动化之请求中带有 headers 的接口和发送POST请求

headers 可通过headers 添加头部信息,如下图 # 发送请求头headers的接口 - config:name: 百度接口用例base_url: https://www.baidu.com- test:name: 发送百度接口的头部信息request:url: /smethod: GETheaders:Accept: text/html,application/xhtmlxml,applicati…

gitHub

gitHub ** 创建一个仓库 git initgit add .git commit -m “first commit”git branch -M maingit remote add origin gitgithub.com:Dylanmenglliao/demo.gitgit push -u origin main ** 已存在仓库,建立关联 7. git remote add origin gitgithub.com:Dylanme…

遥感云大数据在灾害、水体与湿地领域典型案例及GPT模型

详情点击链接:遥感云大数据在灾害、水体与湿地领域典型案例实践及GPT模型 第一:基础 一:平台及基础开发平台 GEE平台及典型应用案例; GEE开发环境及常用数据资源; ChatGPT、文心一言等GPT模型 JavaScript基础&am…

【Hello mysql】 数据库基础

Mysql专栏:Mysql 本篇博客简介:简单的介绍mysql相关的一些基础知识和在Linux环境下的安装 让大家对于mysql有一个初步的认知 数据库基础 数据库基础数据库定义数据库再理解软件角度文件角度总结 主流数据库mysql安装卸载不要的环境获取mysql官方yum源安装…

java中预览pdf或者图片

GetMapping("preview1")ApiOperation(value "根据文件名实现预览功能")public void previewFile1( HttpServletResponse response) throws IOException {String filePath"C:\\Users\\Harbor Lau\\Desktop\\哈哈\\""11月燃油费(公开).pdf&q…

C# int[,] 和 int[,,]

如标题; 在C#中这两个是定义二维和三维数组的;这和C语言的写法不同; C语言定义二维数组是, int a[5][3]; 看下C#的多维数组;输出数组其中一个值; using System;class Program {static void Main(string[…

Django - 定时任务框架【django-apscheduler】基本使用详解(二)

一. 前言 一个网页会有很多数据是不需要经常变动的,比如说首页,变动频率低而访问量大,我们可以把它静态化,这样就不需要每次有请求都要查询数据库再返回,可以减少服务器压力 我们可以使用Django的模板渲染功能完成页面…

学习Kotlin~类

类 类的field 类定义的每一个属性,kotlin都会产生一个filed,一个setter(),一个getter()field用来存储属性数据,不能直接定义,kotlin会封装,保护它里面数据,只暴露给getter和setter使用只有可变属性才有setter方法需要…