FreeRTOS学习笔记-基于stm32(6)时间片调度实验

1、什么是时间片调度

        在任务优先级相同的时候,CPU会轮流使用相同的时间去执行它,即时间片调度。这个相同的时间就是时间片。而时间片的大小就是SysTick的中断周期(SysTick的中断周期可以修改)

        比如有三个相同优先级的任务在运行,时间片大小为10ms。那么CPU前10ms执行task1,然后用10ms执行task2,再花10ms执行task3,再回到task1执行10ms,这样的轮流执行被称之为时间片流转。如果期间有一个任务执行到一半被挂载了,那么CPU就会立马抛弃这个任务执行下一个任务。

2、时间片调度实验

        代码内容为:将时间片设置为50ms,然后创建task1和task2来不断在串口打印他们的运行次数。

步骤1:

        要想使用时间片必须先将这两个宏置1,这两个宏在 FreeRTOSConfig.h 中;

#define configUSE_PREEMPTION		1           //1使用抢占式内核,0使用协程
#define configUSE_TIME_SLICING		1			//1使能时间片调度(默认式使能的)

步骤2:

        在 FreeRTOSConfig.h 中找到此宏,修改1000为20;因为1000hz对应的 SysTick 中断周期即时间片大小是1ms。我们要改为50ms,就应该将1000hz / 50 = 20hz;

#define configTICK_RATE_HZ	   	(20)      //时钟节拍频率,这里设置为1000,周期就是1ms

步骤3:

        创建任务:

        需要注意的是:

        1、我们使用的是delay_ms(10)而不是vTaskDelay(10),因为后者会挂载当前任务转而执行另一个任务,这样就起不到50ms流转的效果了。而10ms的延时会让CPU停止工作。所以我们每50ms进行一次任务切换,然后每执行一次任务会延时10ms,所以每次任务中按理应该执行5遍while循环。又因为 printf 比较耗时,再加上其他代码的执行,实际每次任务while循环会执行4~5次

        2、因为实际每次任务while循环会执行4~5次,所以有时候在串口打印数据打印一半就可能会产生任务切换执行另一个任务,然后导致串口打印出现问题。所以我们在每次串口打印的时候加上临界段保护

/*START_TASK任务配置*/
#define START_TASK_PRIO         1
#define START_TASK_STACK_SIZE   128     //128字=128*4字节
TaskHandle_t start_task_handler;
void start_task( void * pvParameters );/*TASK1任务配置*/
#define TASK1_PRIO         2
#define TASK1_STACK_SIZE   128     //128字=128*4字节
TaskHandle_t task1_handler;
void task1( void * pvParameters );/*TASK2任务配置*/
#define TASK2_PRIO         2
#define TASK2_STACK_SIZE   128     //128字=128*4字节
TaskHandle_t task2_handler;
void task2( void * pvParameters );/*入口函数*/
void freertos_demo(void)
{xTaskCreate(	(TaskFunction_t )    start_task,                //任务函数(char *         )    "start_task",              //任务名称(uint16_t       )    START_TASK_STACK_SIZE,     //任务堆栈大小(void *         )    NULL,                      //传递给任务函数的参数(UBaseType_t    )    START_TASK_PRIO,           //任务优先级(TaskHandle_t * )    &start_task_handler );     //任务句柄 vTaskStartScheduler();         //开启任务调度器
}void start_task( void * pvParameters )
{taskENTER_CRITICAL();       //进入临界区printf("start_task正在运行\r\n");xTaskCreate(	(TaskFunction_t )    task1,                //任务函数(char *         )    "task1",              //任务名称(uint16_t       )    TASK1_STACK_SIZE,     //任务堆栈大小(void *         )    NULL,                 //传递给任务函数的参数(UBaseType_t    )    TASK1_PRIO,           //任务优先级(TaskHandle_t * )    &task1_handler );     //任务句柄xTaskCreate(	(TaskFunction_t )    task2,                //任务函数(char *         )    "task2",              //任务名称(uint16_t       )    TASK2_STACK_SIZE,     //任务堆栈大小(void *         )    NULL,                 //传递给任务函数的参数(UBaseType_t    )    TASK2_PRIO,           //任务优先级(TaskHandle_t * )    &task2_handler );     //任务句柄vTaskDelete(NULL);      //vTaskDelete(start_task_handler);taskEXIT_CRITICAL();        //退出临界区
}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);}
}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);}
}

3、运行结果

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

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

相关文章

【linux kernel】linux内核hid触摸源码hid-multitouch.c剖析

文章目录 一、内核中通用hid触摸驱动二、probe过程剖析(1)hid_parse()函数(2)hid_hw_start()函数(3)hid_connect()函数三、hid-multitouch.c应用场景一、内核中通用hid触摸驱动 在linux内核中,为HID触摸面板实现了一个通用的驱动程序,位于/drivers/hid/hid-multitouch.c文件…

在思科和华为上实现两个主机A,B A能ping通B,B不能ping通A

1.华为实验的topo如下 常规状态下任意两台主机都是可以ping通的 此时的需求是PC4能ping通PC2和PC3但是PC2和PC3不能ping通PC4 这里需要用到ACL策略 在接口上调用 验证: PC4能ping通PC2和PC3 PC2和PC3不能ping通PC4 2.思科类似 正常情况下是都能互相ping通 加上ac…

AI换脸原理(7)——人脸分割参考文献TernausNet: 源码解析

1、介绍 这篇论文相对来说比较简单,整体是通过使用预训练的权重来提高U-Net的性能,实现对UNet的改进。该方法也是DeepFaceLab官方使用的人脸分割方法。在介绍篇我们已经讲过了UNet的网络结构和设计,在进一步深入了解TernausNet之前,我们先简单回顾下UNet。 U-Net的主要结构…

STC8增强型单片机开发——C51版本Keil环境搭建

一、目标 了解C51版本Keil开发环境的概念和用途掌握C51版本Keil环境的安装和配置方法熟悉C51版本Keil开发环境的使用 二、准备工作 Windows 操作系统Keil C51 安装包(可以从Keil官网下载)一款8051单片机开发板 三、搭建流程 环境搭建的基本流程&#xf…

吴恩达2022机器学习专项课程C2(高级学习算法)W1(神经网络):2.5 更复杂的神经网络

目录 示例填写第三层的层数1.问题2.答案 公式:计算任意层的激活值激活函数 示例 层数有4层,不包括输入层。 填写第三层的层数 1.问题 你能把第二个神经元的上标和下标填写出来吗? 2.答案 根据公式g(wxb),这里的x对应的是上…

【C语言】内存函数的概念,使用及模拟实现

Tiny Spark get dazzling some day. 目录 1. memcpy-- 函数原型-- 函数使用-- 函数的模拟实现 2.memmove-- 函数原型-- 函数使用-- 函数的模拟实现 3. memset-- 函数原型-- 函数使用-- 函数的模拟实现 4. memcmp-- 函数原型-- 函数使用-- 函数的模拟实现 1. memcpy 使用需包含…

在国企分公司做信息宣传新闻投稿的经验分享

作为一名国企分公司的信息宣传工作者,我亲历了从传统投稿方式到数字化转型的全过程,这段经历既充满了挑战,也收获了成长。回首最初的日子,那些用邮箱投稿的时光,至今仍让我感慨万千。 初尝辛酸,邮箱投稿的艰难岁月 刚接手信息宣传工作时,我满腔热情,却很快被现实的冷水浇了个透…

场景文本检测识别学习 day08(无监督的Loss Function、代理任务、特征金字塔)

无监督的Loss Function(无监督的目标函数) 根据有无标签,可以将模型的学习方法分为:无监督、有监督两种。而自监督是无监督的一种无监督的目标函数可以分为以下几种: 生成式网络的做法,衡量模型的输出和固…

【仪酷LabVIEW AI工具包案例】使用LabVIEW AI工具包+YOLOv5结合Dobot机械臂实现智能垃圾分类

‍‍🏡博客主页: virobotics(仪酷智能):LabVIEW深度学习、人工智能博主 🎄所属专栏:『仪酷LabVIEW AI工具包案例』 📑上期文章:『【YOLOv9】实战二:手把手教你使用TensorRT实现YOLOv…

新版Idea配置仓库教程

这里模拟的是自己搭建的本地仓库环境,基于虚拟机搭建利用gogs创建的仓库 1、Git环境 你需要准备好git和仓库可以使用github 、gitee等 1.1 拉取代码 本项目使用 Git 进行版本控制,在 gogs 上创建一个个人使用的 git 仓库: http://192.168.…

【C++】详解STL容器之一的 vector

目录 概述 迭代器 数据结构 优点和缺点 接口介绍 begin end rbegin rend resize reseve insert erase 其他一些接口 模拟实现 框架 获取迭代器 深浅拷贝 赋值重载 reseve resize 拷贝构造 构造 析构 insert erase 其他 概述 vector是STL的容器之一。…

漏扫神器Invicti V2024.4.0专业版

前言 Invicti Professional是Invicti Security公司推出的一个产品,它是一种高级的网络安全扫描工具。Invicti Professional旨在帮助组织发现和修复其网络系统中的潜在安全漏洞和弱点。它提供了全面的漏洞扫描功能,包括Web应用程序和网络基础设施的漏洞扫…