Project02:FreeRTOS挂起任务和恢复任务(两种方式)

时间:2022-07-03 04:41:20

码云项目:https://gitee.com/bigvan_tech/FreeRTOS_STM32Project.git

FreeRTOS_STM32Project

基于STM32的FreeRTOS工程,硬件平台基于启明IMT407G(V3.1)开发板,使用STM32CubeMX进行时钟和外围设备的初始化配置,但不使用STM32CubeMX的FreeRTOS中间件,FreeRTOS代码仍采用手动移植,使用MDK-ARM集成开发环境,使用SystemView作为可视化分析工具。

本文介绍了FreeRTOS创建任务和删除任务,并借助SystemView进行可视化分析。

主要参考资料(排名不分先后):

《FreeRTOS中文实用教程》
《FreeRTOS Kernel Developer Guide》
《FreeRTOS Kernel Reference Manual》
《安富莱 STM32-V5开发板_FreeRTOS教程(V1.0)》
《正点原子 STM32F407 FreeRTOS开发手册V1.1》

本文为经验之谈,若有不对的地方还望指正!


一、使用到的API函数

 
---------------------------------------------------------------------------------------------------
++ vTaskSuspend() 挂起一个任务。
---------------------------------------------------------------------------------------------------
#include "FreeRTOS.h"
#include "task.h"
void vTaskSuspend(TaskHandle_t pxTaskToSuspend);
---------------------------------------------------------------------------------------------------
函数 vTaskSuspend 用于实现 FreeRTOS 操作系统的任务挂起。
● 第 1 个参数填要挂起任务的句柄
使用这个函数要注意以下问题:
1、使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1
#define INCLUDE_vTaskSuspend 1
2、如果用往此函数里面填的任务 ID 是 NULL,即数值 0 的话,那么挂起的就是当前正在执行的任务,
此任务被挂起后,FreeRTOS 会切换到任务就绪列表里面下一个要执行的高优先级任务。
3、多次调用此函数的话,只需调用一次 vTaskResume 即可将任务从挂起态恢复。
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
++ vTaskResume() 恢复一个任务的运行。
---------------------------------------------------------------------------------------------------
#include "FreeRTOS.h"
#include "task.h"
void vTaskResume(TaskHandle_t pxTaskToResume);
---------------------------------------------------------------------------------------------------
函数 vTaskResume 用于实现 FreeRTOS 操作系统的任务恢复
● 第 1 个参数填要恢复任务的句柄
使用这个函数要注意以下问题:
1、使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1
#define INCLUDE_vTaskSuspend 1
2、多次调用函数 vTaskSuspend 的话,只需调用一次 vTaskResume 即可将任务从挂起态恢复。
3、此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序中使用的
xTaskResumeFromISR(),以后缀 FromISR 结尾。
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
++ xTaskResumeFromISR() 中断服务函数中恢复一个任务的运行。
---------------------------------------------------------------------------------------------------
#include "FreeRTOS.h"
#include "task.h"
BaseType_t xTaskResumeFromISR(TaskHandle_t pxTaskToResume);
---------------------------------------------------------------------------------------------------
函数 vTaskResumeFromISR 用于实现 FreeRTOS 操作系统的任务恢复。
● 第 1 个参数填要恢复任务的句柄
使用这个函数要注意以下问题:
1、使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1
#define INCLUDE_xResumeFromISR 1
2、多次调用函数 vTaskSuspend 的话,只需调用一次 vTaskResumeFromISR 即可将任务从挂起态恢复。
3、如果用户打算采用这个函数实现中断与任务的同步,要注意一种情况,如果此函数的调用优先于函数
vTaskSuspend 被调用,那么此次同步会丢失,这种情况下建议使用信号量来实现同步。
4、此函数是用于中断服务程序中调用的,故不可以在任务中使用此函数,任务中使用的是 vTaskResume。
---------------------------------------------------------------------------------------------------


二、工程描述


 
创建任务Task1在优先级3上,创建任务Task0A、Task0B在优先级2上,创建任务Task2A、Task2B在优先级4上。
进入任务Task0A、Task0B、Task2A、Task2B后,各自挂起自己(Suspend)。
进入任务Task1后恢复(Resume)Task0A和Task2A。
通过按键KEY0和按键KEY2,按键中断恢复(ResumeFromISR)Task0B和Task2B。
延时使用vTaskDelay()以让任务Task1在延迟期间保持在阻塞态。

具体代码见码云代码托管平台:https://gitee.com/bigvan_tech/FreeRTOS_STM32Project/tree/master/Project02

三、分析

从contexts看,Task1工作于优先级3,Task0A,Task0B工作于优先级2,Task2A,Task2B工作于优先级4。

Project02:FreeRTOS挂起任务和恢复任务(两种方式)

借助SystemView中Events栏,可以进行细节分析。


第一种情况,不在中断中恢复任务:


Project02:FreeRTOS挂起任务和恢复任务(两种方式)上图为进入任务Task1后恢复(Resume)Task0A和Task2A:

3845、Task1开始运行。
3846、Task1中恢复Task0A。

3847、Task0A进入就绪态,但是Task0A优先级低于Task1,Task1继续运行。

3848、Task1中恢复Task2A。

3849、Task2A进入就绪态,Task2A优先级高于Task1。

3850、Task2A开始运行。

3851、Task2A挂起自己。

3852、Task2A进入阻塞态。

3853、Task1开始运行。

3854、Task1执行延迟函数。
3855、调度器使Task1进入阻塞态。
3856、因为Task1进入阻塞态,Task0A得以执行。

3857、Task0A挂起自己。

3858、Task0A进入阻塞态。

3859、进入空闲任务。


第二种情况,中断中恢复任务:


Project02:FreeRTOS挂起任务和恢复任务(两种方式)

Project02:FreeRTOS挂起任务和恢复任务(两种方式)

上两图为中断恢复(ResumeFromISR)Task2B:

21302、中断中恢复Task2B。
21303、Task2B进入就绪态。
22149、由于Task2B优先级高于Task1,因此调度器使Task2B开始运行。
22150、Task2B挂起自己。
22151、Task2B进入阻塞态。
22152、Task1开始运行。

22153 ~ 22166、同第一种情况。


Project02:FreeRTOS挂起任务和恢复任务(两种方式)

Project02:FreeRTOS挂起任务和恢复任务(两种方式)

上两图为中断恢复(ResumeFromISR)Task0B:
10076、中断中恢复Task0B。
10077、Task0B进入就绪态。
10959、由于Task0B优先级低于Task1,因此调度器使Task1开始运行。

10960、Task1中恢复Task0A。

10961、Task0A进入就绪态,但是Task0A优先级低于Task1,Task1继续运行。

10962、Task1中恢复Task2A。

10963、Task2A进入就绪态,Task2A优先级高于Task1。

10964、Task2A开始运行。

10965、Task2A挂起自己。

10966、Task2A进入阻塞态。

10967、Task1开始运行。

10968、Task1执行延迟函数。
10969、调度器使Task1进入阻塞态。
10970、因为Task1进入阻塞态,Task0B比Task0A早进入就绪态,因此Task0B得以执行。

10971、Task0B挂起自己。

10972、Task0B进入阻塞态。

10973、Task0A挂起自己。

10974、Task0A进入阻塞态。

10975、进入空闲任务。


四、小结:


1、Task1(优先级3)中恢复Task0A,由于Task0A优先级低于Task1,Task0A并不会立即执行,恢复Task2A后,Task2A具有高优先级,所以会立即得到执行。执行完Task2A,Task1继续执行,当执行到延迟函数,Task1进入阻塞态,Task0A才会执行。

2、中断中恢复Task0B和Task2B,Task0B和Task2B进入就绪态,但Task0B和Task2B并不会立即执行,等到下一个调度(Scheduler)时刻到来后,Task0B和Task2B才会运行,其中由于Task2B具有高优先级,所以调度(Scheduler)时刻到来后会立即执行Task2B,由于Task0B具有低优先级,只有等到Task1进入阻塞态,Task0B才会运行。