【复习笔记】FreeRTOS(三)任务挂起和恢复

这篇具有很好参考价值的文章主要介绍了【复习笔记】FreeRTOS(三)任务挂起和恢复。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文是FreeRTOS复习笔记的第三节,任务挂起和恢复,使用的开发板是stm32f407VET6,创建两个任务,task1负责闪烁LED,task2负责按键控制,当按键按下时控制任务挂起,按键再次按下恢复任务,并通过串口打印任务状态。

上一篇文章: 【复习笔记】FreeRTOS(二)创建和删除任务


一、实验目的

首先回顾一下FreeRTOS的四个任务状态:就绪态、运行态、挂起态和阻塞态。他们之间的关系如下:
【复习笔记】FreeRTOS(三)任务挂起和恢复

图1 任务状态之间的转换
  • 就绪态:该任务在就绪列表中,就绪的任务已经具备执行的能力,只等待调度器进行调度,新创建的任务会初始化为就绪态。
  • 运行态:该状态表明任务正在执行,此时它占用处理器,FreeRTOS 调度器选择运行的永远是处于最高优先级的就绪态任务,当任务被运行的一刻,它的任务状态就变成了运行态。
  • 阻塞态:如果任务当前正在等待某个时序或外部中断,我们就说这个任务处于阻塞状态,该任务不在就绪列表中。包含任务被挂起、任务被延时、任务正在等待信号量、读写队列或者等待读写事件等。
  • 挂起态:处于挂起态的任务对调度器而言是不可见的,让一个任务进入挂起状态的唯一办法就是调用 vTaskSuspend()函数;而把 一 个挂起状态的任务恢复的唯一途径就是调用vTaskResume() 或 vTaskResumeFromISR()函数。我们可以这么理解挂起态与阻塞态的区别,当任务有较长的时间不允许运行的时候,我们可以挂起任务,这样子调度器就不会管这个任务的任何信息,直到我们调用恢复任务的 API 函数;而任务处于阻塞态的时候,系统还需要判断阻塞态的任务是否超时,是否可以解除阻塞。

本篇内容复习的是FreeRTOS中的任务恢复与挂起。
有时候我们需要将暂停某个任务的运行,过一段时间以后在重新运行,如果使用任务删除和重建的方法,那么任务中变量保存的值肯定丢了.FreeRTOS给我们提供了解决这种问题的方法,那就是任务的恢复与挂起,当莫个任务要停止运行一段时间的话就将这个任务挂起,当要重新运行这个任务的话就恢复这个任务的运行。FreeRTOS的主要用到3个API函数:

函数 作用
vTaskSuspend() 挂起一个任务,进入挂起态的任务永远都不会进入运行态
vTaskResume() 恢复一个任务,恢复运行被挂起的任务
xTaskResumeFromISR() 中断服务函数中恢复一个任务

1.任务挂起函数:

vTaskSuspend()

此函数用于将某个任务设置为挂起态,进入挂起态的任务永远都不会进入运行态。退出挂起态的唯一方法就是调用任务恢复函数vTaskResume()xTaskResumeFromISR()。

2.任务恢复函数:

vTaskResume()

将一个任务从挂起态恢复到就绪态,只有通过函数 vTaskSuspend()设置为挂起态的任务才可以使用 vTaskRexume()恢复。

3.中断服务函数中使用的任务恢复函数:

BaseType_t xTaskResumeFromISR()

此函数是 vTaskResume()的中断版本,用于在中断服务函数中恢复一个任务
返回值:
pdTrue:恢复运行的任务的任务优先级等于或者高于正在运行的任务(被中断打断的任务),在退出中断服务函数以后必须进行一次上下文切换。
pdFALSE: 恢复运行的任务的任务优先级低于当前正在运行的任务(被中断打断的任务),在退出中断服务函数的以后不需要进行上下文切换。

本次实验就是使用一个按键控制任务的挂起和恢复。

二、测试例程

主函数 main.c代码如下:


/**
  * @file    main.c
  * @author  HuiTanglang
  * @version V1.0
  * @date    2023.05
  * @brief   This file provides firmware functions to manage the following 
  *          functionalities of HuiTanglang;
 */
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "timer.h"
#include "key.h"
#include "FreeRTOS.h"
#include "task.h"

#define START_TASK_PRIO		1 //任务优先级	
#define START_STK_SIZE 		128  //任务堆栈大小
TaskHandle_t StartTask_Handler; //任务句柄
void start_task(void *pvParameters); //任务函数

#define TASK1_TASK_PRIO		2 //任务优先级
#define TASK1_STK_SIZE 		128  //任务堆栈大小	
TaskHandle_t TASK1Task_Handler; //任务句柄
void task1_task(void *p_arg); //任务函数

#define TASK2_TASK_PRIO		3 //任务优先级
#define TASK2_STK_SIZE 		128  //任务堆栈大小	
TaskHandle_t TASK2Task_Handler; //任务句柄
void task2_task(void *p_arg); //任务函数

int main(void)
{ 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	delay_init(168);		//初始化延时函数
	uart_init(115200);     	//初始化串口
//	EXTIX_Init();
	LED_Init();		        //初始化LED端口
	KEY_Init();
	//创建开始任务
    xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
    vTaskStartScheduler();          //开启任务调度
}
 

/**
  * @brief  开始任务任务函数
  * @param  None
  * @retval None  
  */
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区

    xTaskCreate((TaskFunction_t )task1_task,     
                (const char*    )"task1_task",   
                (uint16_t       )TASK1_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )TASK1_TASK_PRIO,
                (TaskHandle_t*  )&TASK1Task_Handler);  

	xTaskCreate((TaskFunction_t )task2_task,     
                (const char*    )"task2_task",   
                (uint16_t       )TASK2_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )TASK2_TASK_PRIO,
                (TaskHandle_t*  )&TASK2Task_Handler);  
				
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}


/**
  * @brief  显示任务1运行,而且LED 0.5s闪烁
  * @param  None
  * @retval None  
  */
void task1_task(void *pvParameters)
{

	u8 task_num=0;
	while(1)
	{
		task_num++;
		LED0=~LED0;
		printf("任务1运行次数%d\r\n",task_num);
        vTaskDelay(1000);
    }
	
}
	

/**
  * @brief  按键按下就删除任务1的执行程序,按一下挂起,再按一下恢复
  * @param  None
  * @retval None  
  */
void task2_task(void *pvParameters)
{

	u8 key1;
	u8 key_num=0;

	while(1)
	{
		   key1=KEY_Scan(0);
		if(key1==WKUP_PRES)
		{
			key_num++;

		}
		
		if(key_num%2==0 && key_num!=0)
		{  
	       vTaskResume(TASK1Task_Handler);	//恢复任务1

	       printf("恢复任务1的运行!\r\n");
		}
		if(key_num%2==1)
		{  
	        vTaskSuspend(TASK1Task_Handler);//挂起任务1

	       printf("挂起任务1的运行!\r\n");
		}

		vTaskDelay(1000);    
    }
}

按键驱动函数,key.c

#include "key.h"
#include "delay.h" 

/**
  * @brief  按键初始化函数,设置PA0为按键接口,按下就通过电阻接3.3上拉
  * @param  None
  * @retval None  
  */
void KEY_Init(void)
{
	
	GPIO_InitTypeDef  GPIO_InitStructure;
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA,时钟 

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//WK_UP对应引脚PA0--K1按键
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;//下拉
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA0
 
} 

/**
  * @brief  按键处理函数,返回按键值
  * @param  mode:0,不支持连续按;1,支持连续按;
  * @retval 0,没有任何按键按下
  * @retval 1,WKUP按下 --对应K1按键
  */
u8 KEY_Scan(u8 mode)
{	 
	static u8 key_up=1;//按键按松开标志
	if(mode)key_up=1;  //支持连按		  
	if(key_up&&(WK_UP==1))
	{
		delay_ms(10);//去抖动 
		key_up=0;
		if(WK_UP==1) return WKUP_PRES;
	}
	else if(WK_UP==0)key_up=1; 	    
 	return 0;// 无按键按下
}

三、实验效果

本实验使用的开发板是stm32f407VET6最小系统板。【复习笔记】FreeRTOS(三)任务挂起和恢复
实验效果如下:

【复习笔记】FreeRTOS(三)任务挂起和恢复
可以看到led在闪烁,接上串口,通过串口工具可以看到打印的任务1运行次数,每过1秒次数加1。当第一次按下按键时,LED停止闪烁,串口显示挂起任务1状态。当再次按下按键时,LED恢复闪烁,通过串口可以看到打印的任务1运行次数,运行次数是从挂起之前的次数开始计数,起到了一个恢复计数的功能。

本节主要是通过一个小实验,学习和掌握FreeRTOS任务挂起和恢复相关API函数使用。
完整程序放在gitee上:程序下载地址文章来源地址https://www.toymoban.com/news/detail-471230.html

到了这里,关于【复习笔记】FreeRTOS(三)任务挂起和恢复的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32 CubeMX (第一步Freertos任务管理:创建、删除、挂起、恢复)

    学习使用Freertos第一步 FreeRTOS 任务管理,您需要掌握以下几个关键函数: 1. xTaskCreate() :用于创建一个任务,需要指定任务函数、任务名称、任务栈大小和优先级等参数。 2. vTaskDelete() :用于删除一个任务,可以由任务自身或其他任务调用。 3. vTaskDelay() :用于使当前任务进

    2024年02月12日
    浏览(50)
  • 【FreeRTOS】——中断优先级设置&中断相关寄存器&临界段代码保护&调度器挂起与恢复

    目录 前言: 一、中断优先级设置 二、中断相关寄存器(STM32-Cortex M3) 三、临界段代码保护 四、任务调度器的挂起和恢复 总结: 博客笔记根据正点原子视频教程编辑,仅供学习交流使用! ①中断概念回顾 让CPU打断正常运行的程序,转而去处理紧急的事件(程序),就叫中

    2024年02月10日
    浏览(53)
  • FreeRTOS如何解决访问冲突/线程不安全(临界段、互斥锁、挂起调度、看门人任务)

    在多任务(多线程)系统中,存在一个隐患,那就是多线程的访问(在FreeRTOS中就是任务)。当一个任务A开始访问一个资源(外设、一块内存等),但是A还没有完成访问,B任务运行了,也开始访问,这就会造成数据破坏、错误等问题。 例如: 两个任务试图写入一个液晶显示

    2024年02月07日
    浏览(166)
  • Windows线程挂起和Context

    1、SuspendThread用来暂停一个线程的执行,线程暂停时,不会被调度执行 2、ResumeThread用来恢复一个暂停线程的执行(一个暂停的线程无法调用这个方法来恢复自己, 3、因为暂停的线程不可能被执行)暂停县城总是立即被暂停,而不管被暂停的线程执行到了哪个指令 线程内核对象

    2024年02月13日
    浏览(31)
  • 【linux】Debian挂起和休眠

    在Debian桌面系统中,挂起和休眠是两种不同的状态,它们之间有一些区别。 挂起(Suspend)是将当前系统的状态保存到RAM(内存)中,然后关闭所有硬件设备,除了RAM之外。在这种状态下,系统几乎不耗电,因为RAM也需要很少的电量。当您重新打开计算机时,系统会从RAM中恢

    2024年02月21日
    浏览(38)
  • 如何在 Linux 中禁用挂起和休眠模式

    在本文中,我们将引导您了解如何在 Linux 系统上禁用 挂起 和 休眠 模式。但在我们这样做之前,让我们简要概述一下这两种模式。 当您暂停Linux系统时,您基本上会激活或将其置于睡眠模式。屏幕熄灭,即使计算机保持开机状态。此外,您的所有文档和应用程序都保持打开

    2024年02月03日
    浏览(30)
  • 【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行

    个人主页 : zxctscl 如有转载请先通知 上一篇博客中提到 【Linux】进程初步理解,这次继续来分享与进程有关的知识。 Linux的进程状态就是struct task_struct内部的一个属性。 为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在

    2024年04月14日
    浏览(38)
  • mac上使用虚拟机vm, 里面的镜像挂起会占用电脑的内存吗, 挂起和关机的区别是什么, 会影响正常电脑的内存和硬盘使用吗

    在Mac(或任何其他操作系统)上使用虚拟机(如VMware Fusion、Parallels Desktop、VirtualBox等)时,“挂起”(Suspend)和“关机”(Power Off或Shut Down)是两种不同的虚拟机状态,它们对主机系统的资源使用有所不同。 挂起(Suspend) : 当你挂起虚拟机时,虚拟机的当前状态(包括内存

    2024年02月08日
    浏览(46)
  • FreeRTOS学习笔记—任务创建和删除

    🎀 文章作者:二土电子 🌸 关注文末公众号获取其他资料和工程文件! 🐸 期待大家一起学习交流! FreeRTOS 的任务创建和删除相关的API函数有下面几个 xTaskCreate() 使用动态的方法创建一个任务 xTaskCreateStatic() 使用静态的方法创建一个任务 xTaskCreateRestricted() 创建一个使用 M

    2024年02月12日
    浏览(36)
  • FreeRTOS学习笔记——四、任务的定义与任务切换的实现

    本章是我们真正从从0 到1 写FreeRTOS 的第一章, 属于基础中的基础 必须要学会创建任务,并重点掌握任务是如何切换 因为任务的切换是由汇编代码来完成的,所以代码看起来比较难懂,但是会尽力把代码讲得透彻 如果本章内容学不会, 后面的内容根本无从下手 在这章中: 我

    2024年02月07日
    浏览(62)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包