FreeRTOS入门教程(任务优先级,Tick)

文章目录

  • 前言
  • 一、什么是任务优先级
  • 二、FreeRTOS如何分辨出优先级最高可运行的任务
  • 三、FreeRTOS中的时钟节拍Tick
  • 四、什么是时间片
  • 五、相同优先级任务怎么进行切换
  • 六、任务优先级实验
  • 七、修改任务优先级
  • 总结


前言

本篇文章将带大家学习FreeRTOS中的任务优先级,并且了解什么是任务优先级,

一、什么是任务优先级

在FreeRTOS中,任务优先级用于确定任务的执行顺序和调度顺序。任务优先级越高,任务被调度执行的频率越高。FreeRTOS支持使用整数值来表示任务优先级,整数值越高,优先级越高。

FreeRTOS中任务优先级的范围通常是从0到configMAX_PRIORITIES-1,其中configMAX_PRIORITIES是一个配置常量,表示系统中支持的最大任务优先级数量。

在FreeRTOSconfig.h中可以查看到任务优先级的配置宏:
在这里插入图片描述

二、FreeRTOS如何分辨出优先级最高可运行的任务

1.通用方法:

使用C函数实现,对所有的架构都是同样的代码。对configMAX_PRIORITIES的取值没有限制。但
是configMAX_PRIORITIES的取值还是尽量小,因为取值越大越浪费内存,也浪费时间。
configUSE_PORT_OPTIMISED_TASK_SELECTION被定义为0、或者未定义时,使用此方法。

2.架构相关的优化的方法:

架构相关的汇编指令,可以从一个32位的数里快速地找出为1的最高位。使用这些指令,可以快速
找出优先级最高的、可以运行的任务。
使用这种方法时,configMAX_PRIORITIES的取值不能超过32。
configUSE_PORT_OPTIMISED_TASK_SELECTION被定义为1时,使用此方法

三、FreeRTOS中的时钟节拍Tick

FreeRTOS中的时钟节拍(Tick)是一个基本的时间单位,用于管理任务调度和时间相关功能。时钟节拍的概念在实时操作系统中非常重要,因为它提供了时间的基本度量单位,允许任务和定时器按照预定的时间间隔执行。

以下是有关FreeRTOS中时钟节拍的重要信息:

1.时钟节拍的单位:时钟节拍是一个抽象的时间单位,通常表示为一个整数值。它可以映射到实际时间,但时钟节拍的精度和长度是可配置的。在大多数情况下,时钟节拍是以毫秒为单位的,但它可以配置为更短或更长的时间间隔,具体取决于应用程序的需求。

2.时钟节拍计数器:FreeRTOS维护一个时钟节拍计数器,用于跟踪已经过去的时钟节拍数。这个计数器通常是一个32位的值,可以支持大范围的时间跟踪。

3.任务调度:任务的调度和切换通常发生在时钟节拍的倍数上。当时钟节拍计数器达到任务的时间间隔(通常称为任务的延迟或周期)时,任务可能会被置于就绪状态,以便在下一个任务切换点执行。

4.定时器:时钟节拍也用于定时器功能。通过设置定时器的周期为时钟节拍的倍数,可以实现定时任务和事件的触发。

5.配置和定制:FreeRTOS允许用户配置时钟节拍的频率和精度,以适应特定应用的需求。这可以通过修改FreeRTOS配置文件中的参数来完成。例如,可以配置时钟节拍为1毫秒,10毫秒,甚至更短的时间间隔,以满足实时性要求。

6.时钟节拍在FreeRTOS中扮演了关键的角色,它不仅用于任务调度,还用于实现定时等待、超时操作和时间相关的功能。

FreeRTOS中的Tick值通常被配置为1ms:

在这里插入图片描述

四、什么是时间片

时间片(Time slice)是操作系统调度算法中的概念,用于分配处理器时间给多个可运行的任务。它是指操作系统将处理器的执行时间划分为固定长度的小段,每个任务在一个时间片内获得处理器的执行时间。

五、相同优先级任务怎么进行切换

在FreeRTOS默认采用了时间片轮转调度的策略,给每一个任务都分配一个固定的时间片,这个时间片的大小也就是1ms,可以通过修改configTICK_RATE_HZ这个宏来修改时间片的大小。

时间片大小(毫秒) = 1秒 / configTICK_RATE_HZ

在这里插入图片描述

Task1执行完一个时间片后会发生一次tick中断,然后进入tick中断处理函数中,在tick中断中选择要执行的下一个中断,当执行完tick中断后就切换Task2执行。

六、任务优先级实验

// 任务句柄
TaskHandle_t Task1Handle;
TaskHandle_t Task2Handle;// 任务函数
void Task1(void* pvParameters) {while (1) {vTaskDelay(1000);printf("Task1 is running\n");}
}void Task2(void* pvParameters) {while (1) {vTaskDelay(1000);printf("Task2 is running\n");}
}int main(void) {// 创建两个任务xTaskCreate(Task1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, &Task1Handle);xTaskCreate(Task2, "Task2", configMINIMAL_STACK_SIZE, NULL, 2, &Task2Handle);// 启动调度器vTaskStartScheduler();while (1) {// 主循环为空,所有的任务由 FreeRTOS 调度}
}

因为任务2的优先级比任务1的优先级高所以会先打印Task2 is running,然后再打印Task1 is running,以此往复。

七、修改任务优先级

uxTaskPriorityGet() 和 vTaskPrioritySet() 是FreeRTOS中用于获取和设置任务优先级的函数。

uxTaskPriorityGet() 函数用于获取任务的当前优先级。它接受一个参数,即任务句柄,返回一个 UBaseType_t 类型的值,表示任务的当前优先级。

vTaskPrioritySet() 函数用于设置任务的优先级。它接受两个参数,第一个参数是要设置优先级的任务句柄,第二个参数是要设置的优先级值。这个函数没有返回值。

以下是一个使用 uxTaskPriorityGet() 和 vTaskPrioritySet() 函数的示例代码:

TaskHandle_t Task1Handle;
TaskHandle_t Task2Handle;void Task1(void* pvParameters) {while (1) {// 获取任务优先级UBaseType_t priority = uxTaskPriorityGet(NULL);printf("Task1 priority: %u\n", priority);vTaskDelay(pdMS_TO_TICKS(1000));}
}void Task2(void* pvParameters) {while (1) {// 获取任务优先级UBaseType_t priority = uxTaskPriorityGet(NULL);printf("Task2 priority: %u\n", priority);// 设置任务优先级vTaskPrioritySet(Task1Handle, 2);vTaskDelay(pdMS_TO_TICKS(5000));// 恢复任务优先级vTaskPrioritySet(Task1Handle, 1);}
}int main(void) {xTaskCreate(Task1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, &Task1Handle);xTaskCreate(Task2, "Task2", configMINIMAL_STACK_SIZE, NULL, 2, &Task2Handle);vTaskStartScheduler();while (1) {// 主循环为空,所有的任务由 FreeRTOS 调度}

在这个示例代码中,我们创建了两个任务 Task1 和 Task2,并使用 uxTaskPriorityGet() 和 vTaskPrioritySet() 进行任务优先级的获取和设置。

在 Task1 中,我们首先使用 uxTaskPriorityGet(NULL) 获取当前任务的优先级,并通过 printf 打印出来。然后使用 vTaskDelay() 延迟1秒钟。

在 Task2 中,我们首先获取当前任务的优先级,然后通过 vTaskPrioritySet(Task1Handle, 2) 将 Task1 的优先级设置为2。接着延迟5秒钟后,再通过 vTaskPrioritySet(Task1Handle, 1) 恢复 Task1 的优先级为1。

通过运行这个示例代码,将会看到在任务的执行过程中,任务的优先级获取和设置操作被执行,并通过打印语句输出任务的优先级信息。

注意,在使用 uxTaskPriorityGet() 和 vTaskPrioritySet() 函数时,需要确保任务句柄是正确的,并且函数的调用时机是合适的,以避免潜在的问题和不一致性。

总结

本篇文章就讲解到这里。

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

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

相关文章

GPT-4科研实践:数据可视化、统计分析、编程、机器学习数据挖掘、数据预处理、代码优化、科研方法论

查看原文>>>GPT4科研实践技术与AI绘图 GPT对于每个科研人员已经成为不可或缺的辅助工具,不同的研究领域和项目具有不同的需求。例如在科研编程、绘图领域:1、编程建议和示例代码: 无论你使用的编程语言是Python、R、MATLAB还是其他语言&#x…

【SSL】用Certbot生成免费HTTPS证书

1. 实验背景 服务器:CentOS7.x 示例域名: www.example.com 域名对应的web站点目录: /usr/local/openresty/nginx/html 2. 安装docker # yum -y install yum-utils# yum-config-manager --add-repo https://download.docker.com/linux/ce…

web:[极客大挑战 2019]LoveSQL

题目 打开页面显示如下 查看源代码,查到一个check.php,还是get传参 尝试账号密码输入 题目名为sql,用万能密码 1or 11# 或 admin or 11 给了一段乱码,也不是flag 查看字段数 /check.php?usernameadmin order by 3%23&pass…

Word | 简单可操作的快捷公式编号、右对齐和引用方法

1. 问题描述 在理工科论文的写作中,涉及到大量的公式输入,我们希望能够按照章节为公式进行编号,并且实现公式居中,编号右对齐的效果。网上有各种各样的方法来实现,操作繁琐和简单的混在一起,让没有接触过公…

Redis学习笔记(常用数据类型,发布订阅,事务和锁机制,持久化,集群,雪崩,缓存击穿,分布式锁)

一、NoSQL数据库简介 解决扩展性问题,如果需要对功能进行改变(比如增删功能),用框架有一定的规范要求,无形中解决了扩展性问题。 Redis是一种典型的NoSQL数据库。 NoSQL的基础作用: 1. nginx负载均衡反向…

Armv9读取cache内容:Direct access to internal memory

10 访问cache Cortex-A720核心提供一种机制,通过IMPLEMENTATION DEFINED系统寄存器可以读取L1缓存、L2缓存和Translation Lookaside Buffer(TLB)。当缓存数据与系统内存数据之间的一致性异常时,您可以使用此机制来调查任何问题。 只有在EL3中才可以访问内部内存(cache)。…

排序:最佳归并树(优化外部排序中对磁盘的读写次数)

1.归并树的性质 每个初始归并段对应一个叶子结点,把归并段的块数作为叶子的权值归并树的WPL树中所有叶结点的带权路径长度之和归并过程中的磁盘I/O次数归并树的WPL*2 如下图: 每个初始归并段看作一个叶子结点,归并段的长度作为结点权值&a…

C/C++进程线程超详细详解

目录 前言 一、进程基础 1.进程概念 2.进程特征 3.进程状态(如图清晰可见) 4,进程的标识 实例代码如下: 5.进程的种类 实例shell脚本程序如下: 二、进程API 1.创建子进程 实例代码如下: 2.exec函数族 函数…

Socket网络编程练习题四:客户端上传文件(多线程版)

题目 想要服务器不停止,能接收很多客户上传的图片? 解决方案 可以使用循环或者多线程 但是循环不合理,最优解法是(循环多线程)改写 代码实战 客户端代码 package com.heima;import java.io.*; import java.net.S…

深度学习算法在工业视觉落地的思考

0.废话 距离上次的栈板识别的思考已经过去3个月,中间根据客户的需求和自己的思考,对软件又重新做了调整。但是整体上还是不满意。 0.1 老生常谈的工业视觉落地架构 对于软件架构,我实在没有太多的参考。没办法,公司根本不关心软…

使用华为eNSP组网试验⑵-通过端口地址进行静态路由

有了网络模拟器可以对很多网络应用场景进行模拟,既方便学习又有利于实际的网络实施。 之前因为没有用过,用过了才知道eNSP的好处。但是与思科模拟器不同,连接是自动连接,不能确定端口,比如使用指定的光纤端口或者RJ45的…

CSS详细基础(六)边框样式

本期是CSS基础的最后一篇~ 目录 一.border属性 二.边框属性复合写法 三.CSS修改表格标签 四.内边距属性 五.外边距属性 六.其他杂例 1.盒子元素水平居中 2.清除网页内外元素边距 3.外边距的合并与塌陷 4.padding不会撑大盒子的情况 七.综合案例——新浪导航栏仿真 …

QT按钮介绍

目录 按钮基类 QAbstractButton QPushButton QToolButton QRadioButton QCheckBox 按钮基类 QAbstractButton 这是按钮的基类,它是继承QWidget类 它可对当前的图标,标题等进行设置。 它有自己的一些信号与槽函数: /* 当按钮被激活时(即…

Chrome(谷歌浏览器)如何关闭搜索栏历史记录

目录 问题描述解决方法插件解决(亲测有效)自带设置解决步骤首先打开 地址 输入:chrome://flags关闭浏览器,重新打开Chrome 发现 已经正常 问题描述 Chrome是大家熟知的浏览器,但是搜索栏的历史记录如何自己一条条的删…

asp.net core mvc 文件上传,下载,预览

//文件上传用到了IformFile接口 1.1文件上传视图 <form action"/stu/upload" method"post" enctype"multipart/form-data"><input type"file" name"img" /><input type"submit" value"上传&…

国庆day1

发送数据 #include<myhead.h>//消息结构体 typedef struct {long msgtype; //消息类型char data[1024]; //消息正文 }Msg_ds;#define SIZE sizeof(Msg_ds)-sizeof(long) //正文大小 int main(int argc, const char *argv[]) {//1、创建key值key_t ke…

Microsoft Office无法重装报错30015-44(3) 0-2031(17004)

1.问题描述 由于迁移文件夹导致Microsoft office软件无法使用&#xff0c;于是准备卸载重装&#xff0c;但是点击OfficeSetup.exe出现报错30015-44(3) 关闭后出现以下报错0-2031(17004) 2. 尝试的解决方式 重启后仍然无法解决问题 2.1 参考官网解决办法 手动从控制面板&…

Spring源码分析(四) Aop全流程

一、Spring AOP基础概念 1、基础概念 连接点(Join point)&#xff1a;能够被拦截的地方&#xff0c;Spring AOP 是基于动态代理的&#xff0c;所以是方法拦截的&#xff0c;每个成员方法都可以称之为连接点&#xff1b;切点(Poincut)&#xff1a;每个方法都可以称之为连接点&…

Sentinel学习——CAP理论,微服务中的雪崩问题,和Hystix的解决方案 Sentinel的相关概念 + 下载运行

前言 Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入点&#xff0c;从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。 本篇博客介绍CAP理论&#xff0c;微…

【C++】单例模式

文章目录 一. 介绍二. 饿汉模式三. 懒汉模式四. 饿汉模式和懒汉模式对比 一. 介绍 单例模式是属于设计模式的一种&#xff0c;那什么是设计模式呢&#xff1f; 设计模式&#xff08;Design Pattern&#xff09;是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总…