freeRtos学习笔记

freeRtos任务管理

freeRtos任务状态

freeRtos中任务有四种状态:就绪态、运行态、杜塞态、挂起态。


图 16-1(1): 创建任务→就绪态(Ready):任务创建完成后进入就绪态,表明任务已准备就绪,随时可以运行,只等待调度器进行调度。

图 16-1(2): 就绪态→运行态(Running):发生任务切换时,就绪列表中最高优先级的任务被执行,从而进入运行态。

图 16-1(3): 运行态→就绪态:有更高优先级任务创建或者恢复后,会发生任务调度,此刻就绪列表中最高优先级任务变为运行态,那么原先运行的任务由运行态变为就绪态,依然在就绪列表中,等待最高优先级的任务运行完毕继续运行原来的任务(此处可以看做是 CPU 使用权被更高优先级的任务抢占了)。

图 16-1(4): 运行态→阻塞态(Blocked):正在运行的任务发生阻塞(延时、读信号量等待)时,该任务会从就绪列表中删除,任务状态由运行态变成阻塞态,然后发生任务切换,运行就绪列表中当前最高优先级任务。

图 16-1(5): 阻塞态→就绪态:阻塞的任务被恢复后(任务恢复、延时时间超时、读信号量超时或读到信号量等),此时被恢复的任务会被加入就绪列表,从而由阻塞态变成就绪态;如果此时被恢复任务的优先级高于正在运行任务的优先级,则会发生任务切换,将该任务将再次转换任务状态,由就绪态变成运行态。

图 16-1(6) (7) (8): 就绪态、阻塞态、运行态→挂起态(Suspended):任务可以通过调用 vTaskSuspend() API 函数都可以将处于任何状态的任务挂起,被挂起的任务得不到CPU 的使用权,也不会参与调度,除非它从挂起态中解除。

图 16-1(9): 挂起态→就绪态: 把一个挂起状态的任务恢复的唯一途径就是调用 vTaskResume() 或 xTaskResumeFromISR() API 函数,如果此时被恢复任务的优先级高于正在运行任务的优先级,则会发生任务切换,将该任务将再次转换任务状态,由就绪态变成运行态。

freeRtos启动

void vTaskStartScheduler(void);

启动freeRtos的任务调度器,空闲任务和定时器任务是在调用这个函数后才自动创建的。

动态创建任务

BaseType_t xTaskCreate(  TaskFunction_t pxTaskCode,                    /* 任务入口函数 */const char * const pcName,                /* 任务名 */const configSTACK_DEPTH_TYPE usStackDepth,/* 任务栈大小 单位为字 */void * const pvParameters,                /* 任务入口参数 不用的时候配置为0  */UBaseType_t uxPriority,                   /* 任务任务优先级 空闲任务优先级0 */TaskHandle_t * const pxCreatedTask )      /* 任务控制块指针 */

函数 xTaskCreate 用于实现 FreeRTOS 操作系统的任务创建,并且还可以自定义任务栈的大小。

  • 第 1 个参数填创建任务的函数名。
  • 第 2 个参数是任务名,这个参数主要是用于调试目的,调试的时候方便看是哪个任务。
  • 第 3 个参数是任务栈大小,单位 word,也就是 4 字节。
  • 第 4 个参数是创建的任务函数的形参。
  • 第 5 个参数是任务优先级,越大优先级越高
  • 第 6 个参数是任务句柄,用于区分不同的任务。
  • 返回值:当任务创建成功,返回pdPASS,否则返回pdFALL.

删除任务

void vTaskDelete( TaskHandle_t xTaskToDelete )

使用这个函数要注意以下问题:

  1. 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1
    #define INCLUDE_vTaskDelete 1
  2. 如果用往此函数里面填的任务 ID 是 NULL,即数值 0 的话,那么删除的就是当前正在执行的任务,此任务被删除后, FreeRTOS 会切换到任务就绪列表里面下一个要执行的最高优先级任务。
  3. 在 FreeRTOS 中,创建任务所需的内存需要在空闲任务中释放, 如果用户在 FreeRTOS 中调用了这个函数的话,一定要让空闲任务有执行的机会, 否则这块内存是无法释放的。另外, 创建的这个任务在使用中申请了动态内存,这个内存不会因为此任务被删除而删除,这一点要注意, 一定要在删除前将此内存释放

挂起任务

void vTaskSuspend(TaskHandle xTaskToSuspend);

函数 vTaskSuspend 用于实现 FreeRTOS 操作系统的任务挂起。
第 1 个参数填要挂起任务的句柄
使用这个函数要注意以下问题:

  1. 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1
    #define INCLUDE_vTaskSuspend 1
  2. 如果用往此函数里面填的任务 ID 是 NULL,即数值 0 的话,那么挂起的就是当前正在执行的任务,
    此任务被挂起后, FreeRTOS 会切换到任务就绪列表里面下一个要执行的高优先级任务。
  3. 多次调用此函数的话,只需调用一次 vTaskResume 即可将任务从挂起态恢复。

恢复挂起任务

void vTaskResume(TaskHandle xTaskToResume);
BaseType_t xTaskResumeFromISR(TaskHandle xTaskToResume);

函数 vTaskResume 用于实现 FreeRTOS 操作系统的任务挂起
第 1 个参数填要恢复任务的句柄
使用这个函数要注意以下问题:

  1. 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1
    #define INCLUDE_vTaskSuspend 1
  2. 多次调用函数 vTaskSuspend 的话,只需调用一次 vTaskResume 即可将任务从挂起态恢复。
  3. 此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序中使用的
    xTaskResumeFromISR(), 以后缀 FromISR 结尾。
  4. xTaskResumeFromISR()返回值:如果恢复挂起任务后会导致任务调度返回pdTRUE

修改任务优先级

void vTaskPrioritySet(TaskHandle xTask, UBaseType_t uxNewPriority);

函数 vTaskPrioritySet 用于实现 FreeRTOS 任务优先级的修改。
第 1 个参数是任务句柄,用于区分不同的任务。
第 2 个参数是给任务配置的新优先级。
使用这个函数要注意以下问题:

  1. 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1
    #define INCLUDE_vTaskPrioritySet 1
  2. 如果第一个参数里面填的是 NULL,即数值 0 的话,那么配置的就是当前正在执行的任务。
  3. 如果被修改的任务的优先级,修改后高于正在执行的任务, 将执行任务切换,切换到修改好的高优先级任务。
  4. 第二个参数数值不可大于等于 FreeRTOSConfig.h 文件中的宏定义:
    #define configMAX_PRIORITIES 配置的数值。

获取任务优先级

UBaseType_t uxTaskPriorityGet(TaskHandle xTask);
UBaseType_t uxTaskPriorityGetFromISR(TaskHandle_t xTask);

函数 vTaskPriorityGet 用于获取 FreeRTOS 任务优先级。
第 1 个参数是任务句柄,用于区分不同的任务。
使用这个函数要注意以下问题:

  1. 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1
    #define INCLUDE_vTaskPriorityGet 1
  2. 如果第1个参数里面填的是 NULL,即数值 0 的话,那么获取的优先级就是当前正在执行的任务。
  3. 此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序中使用的
    uxTaskPriorityGetFromISR(), 以后缀 FromISR 结尾。

切换任务

taskYIELD()

调用 taskYIELD() 宏可以立刻进行任务调度,切换到就绪的最高优先级任务

获取当前系统时间

volatile TickType_t xTaskGetTickCount(void);
volatile TickType_t xTaskGetTickCountFromISR(void);

函数 xTaskGetTickCount 用于获取系统当前运行的时钟节拍数。
使用这个函数要注意以下问题:

  1. 此函数用于在任务代码里面调用, 如果在中断服务程序里面调用的话, 需要使用函数
    xTaskGetTickCountFromISR, 这两个函数切不可混用

任务延时

void vTaskDelay(TickType_t xTickToDelay);

函数 vTaskDelay 用于任务的延迟。
参数 xTicksToDelay 用于设置延迟的时钟节拍个数,范围 1- 0xFFFFFFFF。 延迟时间的最大值在
portmacro.h 文件里面有定义:
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t )0xffffffffUL
即延迟时间的范围是: 1- 0xFFFFFFFF
延时后会进行任务调度

任务绝对延时

void vTaskDelayUntil(TickType_t* pxPreviousWakeTime, TickType_t xTimeIncrement);

函数 vTaskDelayUntil 用于周期性延迟。
 第 1 个参数,存储任务上次处于非阻塞状态时刻的变量地址。
 第 2 个参数,周期性延迟时间。
使用这个函数要注意以下问题:

  1. 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1
    #define INCLUDE_vTaskDelayUntil 1
  2. 用户要注意此函数跟 vTaskDelay 的区别是,例如在两个相同任务,用户处理程序运行需要50ms,然后分别使用vTaskDelay()和vTaskDelayUntil()进行200ms的延时,使用vTaskDelay()做200ms延时,整个任务运行状况就是先用户处理消耗50ms,再延时200ms,也就是250ms任务运行一次;而使用vTaskDelayUntil()进行200ms的延时,整个任务运行状况就是先用户处理消耗50ms,再延时150ms,也就是200ms任务运行一次;

下面是一个使用vTaskDelay()实现vTaskDelayUntil()的过程。

void vTaskA(void *pvParame)
{TickType_t xDelay, xNextTime;/* 200ms执行一次该任务 */const TickType_t xFrequency = 200;/* 获取 xFrequency 个时钟节拍后的时间 */xNextTime = xTaskGetTickCount() + xFrequency;while(1){/* 如果用户函数需要运行50ms */..../* 计算实际需要延时的时间  200 - 50 = 150 */xDelay = xNextTime - xTaskGetTickCount();xNextTime += xFrequency;if(xDelay <= xFrequency){vTaskDelay(xDelay);}}
}void vTaskB(void *pvParame)
{TickType_t xLastWakeTime;/* 200ms执行一次该任务 */const TickType_t xFrequency = 200;while(1){/* 如果用户函数需要运行50ms */....vTaskDelayUntil(&xLastWakeTime, xFrequency);}}

调度器挂起

void vTaskSuspendAll(void);

函数 vTaskSuspendAll 用于实现 FreeRTOS 调度器挂起。
使用这个函数要注意以下问题:

  1. 注意和进入临界区不同,这里只是关掉了任务调度器,只能运行当前任务,但是并没有关中断,中断服务函数还是可以运行的。
  2. 调度锁开启函数 vTaskSuspendAll 和调度锁关闭函数 xTaskResumeAll 一定要成对使用。
  3. 切不可在调度锁开启函数 vTaskSuspendAll 和调度锁关闭函数 xTaskResumeAll 之间调用任何会引
    起任务切换的 API, 比如 vTaskDelayUntil、 vTaskDelay、 xQueueSend 等(调用了也不会执行调度)。

调度器恢复

BaseType_t xTaskResumeAll(void);

函数 xTaskResumeAll 用于实现 FreeRTOS 调度器恢复
由于调度器操作可以进行嵌套,如果执行了两次调度器挂起,那么在第一次执行调度器恢复函数时,此函数返回 pdFALSE,调度器并没有恢复,第二次执行调度器恢复函数才会返回pdTRUE,调度器才会恢复正常。
使用这个函数要注意以下问题:

  1. 注意和进入临界区不同,这里只是关掉了任务调度器,只能运行当前任务,但是并没有关中断,中断服务函数还是可以运行的。
  2. 调度锁开启函数 vTaskSuspendAll 和调度锁关闭函数 xTaskResumeAll 一定要成对使用。
  3. 切不可在调度锁开启函数 vTaskSuspendAll 和调度锁关闭函数 xTaskResumeAll 之间调用任何会引
    起任务切换的 API, 比如 vTaskDelayUntil、 vTaskDelay、 xQueueSend 等(调用了也不会执行调度)

本文参考 freertos官方文档 https://freertos.org/a00110.html
《野火-FreeRTOS 内核实现与应用开发实战指南》
《安富莱 STM32-V6 开发板 FreeRTOS 教程》

freeRtos学习笔(2)任务管理相关推荐

  1. freeRtos学习笔(4)消息队列

    freeRtos学习笔记 freeRtos消息队列 为什么要用消息队列 消息队列可以在任务与任务间,中断与任务间传递信息.为什么不用全局数组?全局数组也可以传递信息,但是和消息队列相比,消息队列有一下 ...

  2. freeRtos学习笔(3)临界区管理

    freeRtos学习笔记 freeRtos临界区管理 freeRtos临界区 代码的临界段也称为临界区,一旦这部分代码开始执行,则不允许任何中断打断.为确保临界段代码的执行不被中断,在进入临界段之前须 ...

  3. freeRtos学习笔(1)内核剪裁

    freeRtos学习笔记 freeRtos内核剪裁 #define configCPU_CLOCK_HZ 系统主频 #define configTICK_RATE_HZ 时钟节拍 #define co ...

  4. FreeRTOS 学习三:任务管理

    FreeRTOS之:任务管理 作者:老鹏 时间:2016/12/12 1. 简介: 在 FreeRTOS 中没有线程和进程的区别,只有一个被翻译成任务的程序,相当于进程的概念,拥有独立的栈空间. 对于 ...

  5. 1、野火freertos学习笔记

    野火freertos学习笔记 1.任务 1.1 栈 1.2 任务的切换 taskYIELD(); 1.3 临界段 2.空闲任务 3.任务优先级 4.任务延时的表现 5.时间片 5.1抢占式.协做式 6 ...

  6. FreeRTOS学习记录

    FreeRTOS学习记录 前言 FreeRTOS学习记录 在STM32CubeMX中配置FreeRTOS 前言 本人小白,最近学习了FreeRTOS操作系统,打算做一点记录. 学习的过程中虽然做了点练 ...

  7. freertos 创建互斥量_STM32CubeMX+FreeRTOS学习[6] 互斥量(Lu)

    FreeRTOS 学习之六:互斥量 前提:默认已经装好 MDK V5 和 STM32CubeMX ,并安装了 STM32F1xx 系列的支持包. 硬件平台: STM32F1xx 系列. 目的:学习互斥 ...

  8. FreeRtos学习笔记(11)查找就绪任务中优先级最高任务原理刨析

    FreeRtos学习笔记(11)查找就绪任务中优先级最高任务原理刨析 怎么查找就绪任务中优先级最高的? tasks.c中声明了一个全局变量 uxTopReadyPriority,任务从其他状态进入就绪 ...

  9. freeRtos学习笔记 (9) 移植和CPU利用率统计

    freeRtos学习笔记 (9) 移植和CPU利用率统计 使用官方固件移植 首先准备一个能跑的裸机工程 注意,freertos需要使用systick定时器,而stm32HAL库默认使用systick作 ...

最新文章

  1. Spring Boot+Maven实现车牌训练、识别系统
  2. ISME:Micrarchaeota和Parvarchaeota古菌门的代谢多样性
  3. C 语言编程 — 内存对齐
  4. 单例模式(winform唯一页面)
  5. QT设置控件背景为透明
  6. php逆波兰表达式,PHP根据数字的字符表达式计算出结果(转换成逆波兰式再求解)[转]...
  7. 《Effective C#》Item 17:减少装箱(Boxing)和拆箱(Unboxing)操作
  8. http接口服务方结合策略模式实现总结
  9. kafka彻底删除topic(cleanup policy)、清除特定topic数据
  10. 如何在ashx页面获取Session值 (仅供个人参考)
  11. 用户微信好友关系属于个人隐私吗?深圳南山法院说不属于...
  12. 陌陌宣布由总裁兼COO王力担任公司新任CEO
  13. 一个关于指针+记录数据类型的使用技巧
  14. 2020-12-28 learning opencv3: 十一:resize, pyrDown, buildPyramid, pyrUp
  15. 计算机一级在线考试软件,全国计算机等级考试一级MS OFFICE练习软件
  16. java开源cad_.Net开源项目(包含CAD支持)
  17. Node.JS 字符分割
  18. 使用jqery模拟网易严选购物车功能
  19. 名帖176 苏轼 行书《杜甫堂成诗卷》
  20. 双心一键获取winsxs的写入权限,解决VC运行库安装error1935错误

热门文章

  1. android edittext 限制文本框输入的长度和提示信息
  2. python自定义函数画图_利用Python绘图和可视化(长文慎入)
  3. 男子商场抱起小女孩致其坠落 警方:嫌疑人被刑拘
  4. 云计算之KVM虚拟化实战
  5. 降低http请求次数
  6. Android 打开屏幕旋转
  7. CentOS6 kvm添加网卡桥接口脚本
  8. 地址栏射击游戏!对,你没看错,就是在地址栏上玩的游戏,有图有真相!
  9. python_5.fit()函数,transform()函数,与fit_transform()函数
  10. 关于Apache mod_rewrite的中文配置、使用和语法介绍(实现URL重写和防盗链功能)