FreeRTOS(2)----任务管理

news2024/11/26 14:46:22

一,任务的基本概念

FreeRTOS是一个支持多任务的操作系统,多个任务可以共享一个优先级,当任务configUSE_TIME_SLICING 为 1,则可以使用时间调度的方式共享处理器。

简而言之,freertos任务就是一系列任务的集合。

二,任务调度器

在任何时刻都只可以运行一个任务,这个运行什么任务是由调度器来决定的,宏观看上去好像是一起在执行一堆任务,但实际上确实任务交替执行,当任务进行切入和切出的时候,通过TCB来保存当前的执行环境,当任务再次执行的时候,就可以在原来停止的地方继续执行。

freertos提供的任务调度器是抢占式调度,即优先级越高的任务优先执行且可以抢占低优先级的任务,0为空闲任务

当使能下面的语句,一般限定优先级最大为32。

#define configUSE_PORT_OPTIMISED_TASK_SELECTION         1                       /* 1: 使用硬件计算下一个要运行的任务, 0: 使用软件算法计算下一个要运行的任务, 默认: 0 */

当一个系统中存在多个任务的时候,下一个就绪的任务的选择也是一个重要的问题,freertos提供了两种寻找最高优先级任务的方法

方法一:在就绪链表中进行依次查询,因为在创建任务的时候,以及将优先级从高到低进行了排序,然后找到对应任务的TCB。

方法二:计算前导零指令CLZ,直接计算出最高优先级的任务【stm32可以使用】

三,任务状态迁移

上一篇文章已经讲解了freertos任务的四种状态,但每种任务之间的切换也需要好好理解

1.创建任务---->就绪态:当任务创建成功后,则会进入就绪态,表明任务已经准备就绪,等待任务调度器的调度。

2.就绪态---->运行态:当任务切换的时候,就绪列表中的最高优先级的任务就会被执行,从而进入运行态。

3.运行态---->就绪态:当有更高级的任务创建或者从回复过来,会发生任务调度,最高优先级的任务会进入运行态,原本运行的任务变为就绪态【被高优先级的任务给抢占了】。

4.运行态---->阻塞态:正在运行的任务发生阻塞,则会从就绪列表中删除,任务变为阻塞态,然后任务切换到最高优先级的任务执行。

5.阻塞态---->就绪态:当阻塞的任务被恢复后,被恢复的任务加入就绪队列,从阻塞态变为就绪态,当被恢复的任务优先级高于当前执行的任务,则会发生任务切换,从就绪态转为运行态。

6.变为挂起状态:通过vTaskSuspend()API函数将任何状态的任务挂起,被挂起的任务得不到cpu的使用权,也不会参与调度,除非从挂起态解除。

7.解除挂起状态:调用vTaskResume(),如果被恢复的任务优先级高于当前执行的任务,则会发生任务切换,从就绪态转为运行态。

四,常用任务函数讲解

1.任务挂起函数   vTaskSuSpend()

挂起的任务无法得到CPU的使用权,无论当前的任务处于什么优先级,任务都通过vTaskSuSpend()函数被挂起,除非从挂起态解除,否则无法参与调度。

2.vTaskSuspendAll()

这个函数是将所有的任务都挂起,相当于是挂起了任务调度器,调度器被挂起,中断还是会使能,如果中断需要进行上下文的切换,任务就会被挂起,当任务调度器恢复后,才会切换执行任务。

3.任务恢复函数   vTaskResume()

挂起的任务想要解除挂起态,就需要这个函数,任务恢复就是让挂起的任务重新进入就绪状态,恢复的任务保持之前挂起前的状态,然后继续运行,在就绪队列中,优先级最高的任务则会先执行,任务也需要进行上下文切换【因为优先级不同,所以原本就绪队列中的最高优先级被这个解除挂起状态的更高优先级任务给抢占了,所以CPU会将之前的内容保存起来,去加载新的任务的全部信息】

4.xTaskResumeFromISR()

vTaskSuspend() 函数而被挂起的任务,也只需调用一次 xTaskResumeFromISR()
xTaskResumeFromISR()
xTaskResumeFromISR() vTaskResume() 一样都是用于恢复被挂起的任务,不一样的
专 门 用 在 中 断 服 务 程 序 中 。 无 论 通 过 调 用 一 次 或 多 次
函数即可解挂。要想使用该函数必须在 FreeRTOSConfig.h 中 把 INCLUDE_vTaskSuspend
INCLUDE_vTaskResumeFromISR 都定义为 1 才有效。任务还没有处于挂起态的时候,调用
xTaskResumeFromISR() 函数是没有任何意义的。
5.任务删除函数   vTaskDelete()

 用于删除一个任务。当一个任务删除另外一个任务时,形参为要删除任 务创建时返回的任务句柄,如果是删除自身, 则形参为 NULL。 要想使用该函数必须在 FreeRTOSConfig.h 中把 INCLUDE_vTaskDelete 定义为 1,删除的任务将从所有就绪,阻塞, 挂起和事件列表中删除。
延时的时长由形参 xTicksToDelay 决定,单位为系统节拍周期, 比如系统的时钟节拍周期为 1ms ,那么调用 vTaskDelay(1) 的延时时间则为 1ms

6.任务相对延时函数  vTaskDelete()

 freertos同时会运行多个任务,每个任务都是死循环,所以需要通过阻塞来让低优先级的任务执行,然后需要使能
#define INCLUDE_vTaskDelay                              1                       /* 任务延时 */

7.绝对延时函数  vTaskDelayUntil()

这个函数可以让每个任务执行固定的时间且不受外部影响,任务从开始到下一次开始的时间是绝对不变的。

代码如下:

/**
 ****************************************************************************************************
 * @file        freertos.c
 * @author      正点原子团队(ALIENTEK)
 * @version     V1.4
 * @date        2022-01-04
 * @brief       FreeRTOS 任务挂起与恢复实验
 * @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 实验平台:正点原子 精英F103开发板
 * 在线视频:www.yuanzige.com
 * 技术论坛:www.openedv.com
 * 公司网址:www.alientek.com
 * 购买地址:openedv.taobao.com
 *
 ****************************************************************************************************
 */

#include "freertos_demo.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"

/******************************************************************************************************/
/*FreeRTOS配置*/

/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define START_TASK_PRIO 1                   /* 任务优先级 */
#define START_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            StartTask_Handler;  /* 任务句柄 */
void start_task(void *pvParameters);        /* 任务函数 */

/* TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK1_PRIO      2                   /* 任务优先级 */
#define TASK1_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task1Task_Handler;  /* 任务句柄 */
void task1(void *pvParameters);             /* 任务函数 */

/* TASK2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK2_PRIO      3                   /* 任务优先级 */
#define TASK2_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task2Task_Handler;  /* 任务句柄 */
void task2(void *pvParameters);             /* 任务函数 */

/* TASK3 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK3_PRIO      4                   /* 任务优先级 */
#define TASK3_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task3Task_Handler;  /* 任务句柄 */
void task3(void *pvParameters);             /* 任务函数 */

/******************************************************************************************************/

/* LCD刷屏时使用的颜色 */
uint16_t lcd_discolor[11] = {WHITE, BLACK, BLUE, RED,
                             MAGENTA, GREEN, CYAN, YELLOW,
                             BROWN, BRRED, GRAY};

/**
 * @brief       FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{
    lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);
    lcd_show_string(10, 47, 220, 24, 24, "Task Susp & Resum", RED);
    lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);
    
    lcd_draw_rectangle(5, 110, 115, 314, BLACK);
    lcd_draw_rectangle(125, 110, 234, 314, BLACK);
    lcd_draw_line(5, 130, 115, 130, BLACK);
    lcd_draw_line(125, 130, 234, 130, BLACK);
    lcd_show_string(15, 111, 110, 16, 16, "Task1: 000", BLUE);
    lcd_show_string(135, 111, 110, 16, 16, "Task2: 000", BLUE);
    
    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       start_task
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           /* 进入临界区 */
    /* 创建任务1 */
    xTaskCreate((TaskFunction_t )task1,
                (const char*    )"task1",
                (uint16_t       )TASK1_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK1_PRIO,
                (TaskHandle_t*  )&Task1Task_Handler);
    /* 创建任务2 */
    xTaskCreate((TaskFunction_t )task2,
                (const char*    )"task2",
                (uint16_t       )TASK2_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK2_PRIO,
                (TaskHandle_t*  )&Task2Task_Handler);
    /* 创建任务3 */
    xTaskCreate((TaskFunction_t )task3,
                (const char*    )"task3",
                (uint16_t       )TASK3_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK3_PRIO,
                (TaskHandle_t*  )&Task3Task_Handler);
    vTaskDelete(StartTask_Handler); /* 删除开始任务 */
    taskEXIT_CRITICAL();            /* 退出临界区 */
}

/**
 * @brief       task1
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void task1(void *pvParameters)
{
    uint32_t task1_num = 0;
    printf("进入任务1\r\n");
    while (1)
    {
        lcd_fill(6, 131, 114, 313, lcd_discolor[++task1_num % 11]);
        lcd_show_xnum(71, 111, task1_num, 3, 16, 0x80, BLUE);
			  printf("lalala\r\n");
        vTaskDelay(500);
    }
}

/**
 * @brief       task2
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void task2(void *pvParameters)
{
    uint32_t task2_num = 0;
    printf("进入任务2\r\n");
    while (1)
    {
        lcd_fill(126, 131, 233, 313, lcd_discolor[11 - (++task2_num % 11)]);
        lcd_show_xnum(191, 111, task2_num, 3, 16, 0x80, BLUE);
        printf("nenene\r\n");
        vTaskDelay(500);
    }
}

/**
 * @brief       task3
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void task3(void *pvParameters)
{
    uint8_t key = 0;
    
    while (1)
    {
        key = key_scan(0);
        
        switch (key)
        {
            case KEY0_PRES:                     /* 挂起任务1 */
            {
                vTaskSuspend(Task2Task_Handler);
							  printf("任务2挂起\r\n");
                break;
            }
            case WKUP_PRES:                     /* 恢复任务1 */
            {
                vTaskResume(Task2Task_Handler);
							printf("任务2恢复\r\n");
                break;
            }
            default:
            {
                break;
            }
        }
        
        vTaskDelay(10);
    }
}

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

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

相关文章

day05_Java中的运算符

在Java中提供了丰富的运算符 其按照功能分:算术运算符、赋值运算符、比较运算符、逻辑运算、条件运算符按照操作数个数分:一元运算符(单目运算符)、二元运算符(双目运算符)、三元运算符 (三目…

python 元类

目录 元类type介绍使用元类创建类直接使用type继承type 类和对象的创建过程元类有什么用使用元类实现一个单例模式 元类type介绍 我们知道在python中一切皆对象,即使是类,也是对象,那么类这个对象是的类是谁呢?那就是元类。 通过…

Autosar NM网络管理机制(三大三小模式切换、NM网络报文的帧格式解析、NM中用到的定时器配置)

网络管理机制 AUTOSAR网络管理机制其实十分简单,概括下来三句话: 需要通信就发网络报文,否则就停发网络报文,所有节点同睡同醒。 下图是网络管理的状态机: 网络管理包括三个模式:Network Mode、Prepare …

【指针初阶 2023516】

#include <stdio.h>int main() {int a 100;int * pa &a;//pa是专门用来存放地址&#xff08;指针&#xff09;的&#xff0c;这里的pa就被称为指针变量char* pc &a;//指针变量在32为平台下是4个字节//指针变量在64为平台下是8个字节//int arr[10];//printf(&q…

计算机图形学-GAMES101-3

一、transformation-变换 &#xff08;1&#xff09;Scale 缩放变换示意图 图形每个像素对应坐标的计算公式 写成缩放矩阵的形式 非均匀缩放 &#xff08;2&#xff09;Reflection Matrix 镜面变换示意图 图形每个像素对应坐标的计算公式 写成镜像矩阵的形式 …

阿里HR:年轻人你把握不住.....

前言 去阿里面试测试工程师&#xff0c;这里面水太深&#xff0c;什么未来规划&#xff0c;职业发展的东西都是虚拟的&#xff0c;作者还太年轻&#xff0c;没有那个经历&#xff0c;把握不住。项目只有几个&#xff0c;开心快乐就行&#xff0c;不PK&#xff0c;文明PK。 很…

文心一言 VS chatgpt (17)-- 算法导论4.1 3~4题

三、在你的计算机上实现最大子数组问题的暴力算法和递归算法。请指出多大的问题规模n0是性能交叉点一一从此之后递归算法将击败暴力算法?然后&#xff0c;修改递归算法的基本情况一一当问题规模小于 n0 时采用暴力算法。修改后&#xff0c;性能交叉点会改变吗? 文心一言&…

进程间通信(匿名管道、命名管道、共享内存)

目录 匿名管道 创建管道---pipe() 命名管道 创建FIFO FIFO 操作 用命名管道实现server&client通信 共享内存 1.创建共享内存函数shmget() 2.获得共享内存地址函数shmat() 3.删除共享内存函数shmdt() 4.共享内存控制函数shmctl() 在Linux下的多个进程间的通信机制…

Unittest单元测试框架之unittest的第三方库paramunittest参数化基础及应用

一、unittest参数化介绍 参数化测试用于当需要使用多组不同的测试数据测试同一个方法的时候 paramunittest是unittest实现参数化的一个专门的模块&#xff0c;可以传入多组参数&#xff0c;自动生成多个用例 实现unittest参数化的方式有多种&#xff0c;如ddt、paramunittest等…

Linux-进程信号

Linux-进程信号 一&#xff0c;信号入门信号的概念生活中的信号技术应用角度的信号使用kill -l 查看信号列表信号的处理方式 二&#xff0c;信号产生通过终端按键产生信号Core Dumpcode dump标志位 通过系统调用向进程发信号killraiseabort 由软件条件产生信号SIGPIPESIGALRM 硬…

三届跻身世界级,长沙国际工程机械展的突破之路

文 | 智能相对论 作者 | 易不二 长沙正在成为全球工程机械企业争相奔赴的产业“盛宴”。 近日完美落幕的第三届长沙国际工程机械展&#xff0c;留下了全球30多个国家、1500余家企业“同台竞技”的精彩亮相&#xff0c;并达成了536亿元的现场交易额。 卡特彼勒、日立、沃尔沃…

2022年蓝桥杯:第十三届蓝桥杯大赛软件赛省赛C/C++大学B组真题(考后回顾,文末附真题链接)

目录 第十三届蓝桥杯大赛软件赛省赛C/C大学B组真题&#xff08;考后回顾&#xff09;试题 A: 九进制转十进制试题 B: 顺子日期试题 C: 刷题统计试题 D: 修剪灌木试题 E: X 进制减法试题 F: 统计子矩阵试题 G: 积木画试题 H: 扫雷试题 I: 李白打酒加强版试题 J: 砍竹子 第十三届…

【JavaStript】

目录 &#x1f437;1. JavaScript 的书写形式 &#x1f6e9;1.1 行内式 &#x1f49b; 1.2 内嵌式 &#x1f357;1.3 外部式 &#x1f37f;2. JavaScricpt 的一些常用语句 &#x1f6f4;2.1 输入&#xff1a;prompt &#x1f47d;2.2 输出&#xff1a;alert &#x1f…

Linux线程间的同步和互斥 进程间传统通信方式 5.16

Linux线程间的同步和互斥 同步&#xff1a;有顺序的考虑 按照约定的顺序相互配合完成一件事情&#xff08;红绿灯&#xff09; {释放 产生 资源1&#xff08;V操作&#xff09;&#xff1b;&#xff1b;申请 资源-1&#xff08;p操作&#xff09;} 信号量代表某一类资源&am…

RocketMQ整理

RocketMQ在阿里云上的商业版本,集成了阿里内部一些更深层次的功能及运维定制。开源版本,功能上略有缺失,但大体上是一样的。 使用Java开发,便于深度定制。最早叫MetaQ。消息吞吐量虽然依然不如Kafka,但是却比RabbitMQ高很多。在阿里内部,RocketMQ集群每天处理的请求数超过…

监控需求来源及主流方案对比

我们从开始了解监控系统来说&#xff0c;首先我们要先了解监控的需求来源&#xff0c;即监控系统都可以用于做什么? 监控需求来源 其实最初的需求很简单&#xff0c;即"系统出问题了我们要能及时感知"。后面随着技术的不断发展&#xff0c;我们对监控系统提出了更…

Linux的超级用户及权限

目录 一:Linux下的两个用户 二&#xff1a;权限 1&#xff1a;目录文件 文件创建的默认权限 2&#xff1a;普通文件 一:Linux下的两个用户 在使用Linux的时候会有两个身份,第一个是普通用户,普通用户在很多方面是受阻的,原因就是权限不够,在这种情况下就有一个超级用户,也…

iOS图片系列一 图片的基本属性

图片在项目的开发中使用频率很高&#xff0c;但是绝大部分都是作为普通的展示或者偶尔需要裁剪&#xff0c;并不需要对图片做什么特别的处理&#xff0c;最近做了一个项目对于图片的需求功能比较多&#xff0c;踩了很多坑的同时也对图片的使用有了更深的理解&#xff0c;整理下…

C++面经:初始化全局变量和未初始化全局变量有什么区别

全局变量初始化而且初始值不为0&#xff0c;那么这样的全局变量是放在内存的.data段的&#xff0c;如果全局变量初始值为0或者未初始化&#xff0c;那么这样的全局变量是放在.bss段的。 考点&#xff1a; 考察C/C语言内存模型&#xff0c;.data&#xff0c;.bss段存放的内容。 …

Windows shell环境: 从git bash切换到msys2

文章目录 1. 目的2. msys2 环境 (Environment)3. 升级 MSYS2: 使用 pacman 滚动式升级整个系统4. 在 Windows Terminal 中增加显示 MSYS25. 使用 zsh6. VSCode 中的配置增加 MSYS2 终端配置 git 路径 7. 安装 C/C 依赖库安装 ag查询 bison 和 flex 的安装目录 8. References 1.…