FreeRTOS时间片调度

news2024/11/26 10:35:04

1. 时间片调度简介

同等优先级任务轮流地享有相同的 CPU 时间(可设置), 叫时间片。在FreeRTOS中,一个时间片就等于SysTick 中断周期。

  • 像我们的源码,滴答定时器是 1ms 中断一次,那么一个时间片的时间就是 1ms。
  • 可设置:设置的就是滴答定时器的中断周期(中断频率)。

在这里插入图片描述

运行条件:

  1. 创建三个任务:Task1、Task2、Task3
  2. Task1、Task2、Task3的优先级均为1;即3个任务同等优先级

运行过程如下:

  1. 首先Task1运行完一个时间片后,切换至Task2运行
  2. Task2运行完一个时间片后,切换至Task3运行
  3. Task3运行过程中(还不到一个时间片),Task3阻塞了(系统延时或等待信号量等),此时直接切换到下一个任务Task1
  4. Task1运行完一个时间片后,切换至Task2运行

Task3 只执行不到一个时间片,那下一次再回到 Task3 的时候,怎么样?它剩下的时间片不会要了,同样的也只给它一个时间片的时间去执行。

总结:

  1. 同等优先级任务,轮流执行;时间片流转
  2. 一个时间片大小,取决为滴答定时器中断频率
  3. 注意没有用完的时间片不会再使用,下次任务 Task3 得到执行还是按照一个时间片的时钟节拍运行

2. 时间片调度实验

实验目的:学会对FreeRTOS 时间片调度使用
实验设计:将设计三个任务:start_task、task1、task2,其中task1和task2优先级相同均为2。

为了使现象明显,将滴答定时器的中断频率设置为 50ms 中断一次,即一个时间片 50ms

三个任务的功能如下:
start_task:用来创建其他的2个任务
task1:通过串口打印task1的运行次数
task2:通过串口打印task2的运行次数

注意:使用时间片调度需把宏 configUSE_TIME_SLICING 和 configUSE_PREEMPTION 置1

2.1 宏设置

把宏 configUSE_TIME_SLICING(时间片调度) 和 configUSE_PREEMPTION(抢占式调度) 置1

2.2 滴答定时器中断频率设置

#define configTICK_RATE_HZ                              20                      /* 定义系统时钟节拍频率, 单位: Hz, 无默认需定义 */

1000Hz 对应 1ms,20Hz 对应 50 ms(倒数关系)。也就是说现在一个时间片的时间就是 50 ms。

2.3 任务函数实现

freertos_demo.c

#include "freertos_demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./SYSTEM/delay/delay.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"

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

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

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


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

/**
 * @brief       FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{    
    xTaskCreate((TaskFunction_t         )   start_task,
                (char *                 )   "start_task",
                (configSTACK_DEPTH_TYPE )   START_TASK_STACK_SIZE,
                (void *                 )   NULL,
                (UBaseType_t            )   START_TASK_PRIO,
                (TaskHandle_t *         )   &start_task_handler );
    vTaskStartScheduler();
}


void start_task( void * pvParameters )
{
    taskENTER_CRITICAL();               /* 进入临界区 */
    xTaskCreate((TaskFunction_t         )   task1,
                (char *                 )   "task1",
                (configSTACK_DEPTH_TYPE )   TASK1_STACK_SIZE,
                (void *                 )   NULL,
                (UBaseType_t            )   TASK1_PRIO,
                (TaskHandle_t *         )   &task1_handler );
                
    xTaskCreate((TaskFunction_t         )   task2,
                (char *                 )   "task2",
                (configSTACK_DEPTH_TYPE )   TASK2_STACK_SIZE,
                (void *                 )   NULL,
                (UBaseType_t            )   TASK2_PRIO,
                (TaskHandle_t *         )   &task2_handler );
    vTaskDelete(NULL);
    taskEXIT_CRITICAL();                /* 退出临界区 */
}

/* 任务一,通过串口打印task1的运行次数 */
void task1( void * pvParameters )
{
    uint32_t task1_num = 0;
    while(1)
    {
        taskENTER_CRITICAL();               /* 进入临界区 */
        printf("task1运行次数:%d\r\n",++task1_num);
        taskEXIT_CRITICAL();                /* 退出临界区 */
        delay_ms(10);
    }
}


/* 任务二,通过串口打印task2的运行次数 */
void task2( void * pvParameters )
{
    uint32_t task2_num = 0;
    while(1)
    {
        taskENTER_CRITICAL();               /* 进入临界区 */
        printf("task2运行次数:%d\r\n",++task2_num);
        taskEXIT_CRITICAL();                /* 退出临界区 */
        delay_ms(10);
    }
}
  • 调用系统延时函数是会引起任务调度的,因为会把当前正在运行的任务挂载到阻塞列表,那这样的话,我们就体现不到我们一个时间片 50ms 这样的一个作用了,我们现在知道它的运行次数,那任务一阻塞立马就跳到下一个任务,那这样的话现象就不明显了,所以呢我们这里要用死等(死延时)函数,它就不会实现任务调度这些了。

死等(死延时)函数是没有进入阻塞的,是一直在运行的,我们调用这个延时函数是不会进行任务调度的,所以任务一直在就绪列表里面,这时候它不会进入阻塞状态,理论上的话任务会一直在运行。

  • delay_ms() + printf() > 10ms,所以一个时间片正常能运行 4~5 次,那这个就是正常范围了。

注意:在 printf 函数执行到一半时进行任务切换将会导致数据就乱了,所以避免这种情况建议大家最好是加上临界区保护,保证 printf 函数执行完再执行任务切换。

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

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

相关文章

如何选择一款靠谱的短网址工具,避坑指南

选择一款靠谱的短网址服务是非常重要的。这不仅关乎到你的个人体验,更直接影响到你的业务发展和流量转化。想象一下,你精心策划了一场营销活动,通过短网址分享给了众多用户,然而因为短网址服务的不稳定,用户无法打开链…

多个线程交替打印ABC

多个线程交替打印ABC package 多个线程交替打印ABC;import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier;/*** Created with IntelliJ IDEA.** Author: AlenXu* Date: 2024/03/20/10:10* Description:*/ public class ThreadLoopP…

Hack The Box-Devvortex

目录 信息收集 nmap whatweb WEB web信息收集 wfuzz 漏洞探索 漏洞发现 反弹shell 提权 get user hashcat get root 信息收集 nmap 端口信息收集┌──(root?ru)-[~/kali/hackthebox] └─# nmap -p- 10.10.11.242 --min-rate 10000 Starting Nmap 7…

javase Set集合

Collection子接口2:Set 5.1 Set接口概述 Set接口是Collection的子接口,Set接口相较于Collection接口没有提供额外的方法 Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败。 Set集合…

红黑树简单介绍

1. 概念介绍 红黑树是一种自平衡二叉查找树,由于自平衡的特性,保证了最坏情况下在O(logn)时间复杂度内完成查找、增加、删除等操作,性能表现稳定。 在JDK中,TreeMap、TreeSet以及JDK1.8的HashMap底层都采用…

数据之王国:解析Facebook的大数据应用

引言 作为全球最大的社交媒体平台之一,Facebook拥有庞大的用户群体和海量的数据资源。这些数据不仅包括用户的个人信息和社交行为,还涵盖了广告点击、浏览记录等多方面内容。Facebook通过巧妙地利用这些数据,构建了强大的大数据应用系统&…

面向航天器大数据安全传输的发布/订阅系统设计

源自:系统工程与电子技术 作者:覃润楠 彭晓东 谢文明 惠建江 冯渭春 姜加红 “人工智能技术与咨询” 发布 摘 要 针对航天器试验任务过程监控的在轨故障诊断状态检测、健康状态评估与航天器寿命预测等多个环节中, 海量试验数据在传输、共享、处…

若依 无法导入表名过长的表格

原因 在mapper文件中,有很多转换的语句,使用的是nvarchar类型,nvarchar类型的长度很长,但是默认长度是30位。超过30位就会被截断 解决方案 找到mapper文件中所有对表名转换的地方,把长度扩大到100

电脑所有文档底色变绿?记好这4个方法就足够!

“这是怎么回事呢?怎么我的电脑里面所有文档底色都变绿了呢?我应该怎么操作才可以解决这个问题呀?” 在使用电脑的过程中,有时我们可能会遇到电脑所有文档底色变绿的情况。这种情况不仅影响了文档的阅读体验,还可能对视…

Visual Studio - 添加快捷键图标

Visual Studio - 添加快捷键图标 1. Text Editor Toolbar Options -> Add or Remove Buttons -> Customize2. Toolbars3. Commands -> Debug4. Add Command...References 1. Text Editor Toolbar Options -> Add or Remove Buttons -> Customize 2. Toolbars B…

【CSS】html滚动条相关

1.滚动条样式 ::-webkit-scrollbar {width: 10px;height: 10px;z-index: 101; } ::-webkit-scrollbar-thumb {border-radius: 5px;background: #cecece; } ::-webkit-scrollbar-track {// background: #f5f5f5be;background: rgba(33, 85, 163, 0); } ::-webkit-scrollbar-but…

热插拔技术详解(下)

4、热插拔导致的浪涌问题及其防治 (1)浪涌的概念 浪涌(Electrical Surge)顾名思义就是瞬间出现超出稳定值的峰值,它包括浪涌电压和浪涌电流。 浪涌电压是指超出正常工作电压的瞬间过电压;浪涌电流是指电源…

基于springboot+vue的疫情信息管理系统

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 ​主要内容:毕业设计(Javaweb项目|小程序|Pyt…

AI助手 - 月之暗面 Kimi.ai

前言 这是 AI工具专栏 下的第四篇,这一篇所介绍的AI,也许是截至今天(204-03-19)国内可访问的实用性最强的一款。 今年年初,一直看到有人推荐 Kimi,不过面对雨后春笋般的各类品质的AI,说实话也有…

IP地址的分配:数字世界的地址规划者

在互联网的世界里,IP地址扮演着类似于房屋地址的角色,是用于标识和定位互联网上每个连接到网络的设备的唯一标识符。然而,这些IP地址并非随意分配,而是经过精心规划和管理的。本文将探讨IP地址的分配方式,揭示数字世界…

媒体邀约专访的意义?怎么做

传媒如春雨,润物细无声,大家好,我是51媒体网胡老师。 媒体邀约专访是指企业、组织或个人主动邀请媒体进行专题访谈的一种公关活动。这种活动对于提升品牌形象、传播信息、增强公众认知度和信任度等方面都有重要作用。以下是媒体邀约专访的一…

zabbix监控FortiGate防火墙 FortiGate配置SNMP

SNMP(Simple Network Management Protocol)是一种常用的监控方式。在Zabbix中,可以通过配置SNMP来监控网络设备和服务器。具体步骤如下: 1.FortiGate防火墙开启SNMP 登录防火墙,配置SNMP: 团体名称&#…

【探索Linux】—— 强大的命令行工具 P.28(网络编程套接字 —— 简单的UDP网络程序模拟实现)

阅读导航 引言一、UDP协议二、UDP网络程序模拟实现1. 预备代码⭕makefile文件⭕打印日志文件⭕打开指定的终端设备文件,并将其作为标准错误输出的目标文件描述符 2. UDP 服务器端实现(UdpServer.hpp)3. UDP 客户端实现(main函数&a…

使用Redis做缓存的小案例

如果不了解Redis,可以查看本人博客:Redis入门 Redis基于内存,因此查询速度快,常常可以用来作为缓存使用,缓存就是我们在内存中开辟一段区域来存储我们查询比较频繁的数据,这样,我们在下一次查询…

服装行业实现数字化转型,只需上线这个系统!

近年来,内卷、降本增效等词频频冲上热搜,随着经济的周期性下行,服装企业的竞争愈发激烈,小单快返时代的到来,加速了服装行业的重新洗牌。在这样的大环境下,服装企业数字化转型几乎成了取得确定性增长的唯一…