基于正点原子FreeRTOS学习笔记——时间片调度实验

目录

一、时间片调度介绍

二、实验演示

1、宏修改

1.1、滴答定时器宏

1.2、调度器宏

2、实验程序

2.1.1、任务1,任务2不加临界区程序

[2.1.2 实验现象](#2.1.2 实验现象)

2.2.1、任务1,任务2加临界区程序

[2.2.2 实验现象](#2.2.2 实验现象)


一、时间片调度介绍

时间片:同等优先级任务轮流地享有相同的CPU时间

在FreeRTOS中,一个时间片等于SysTick中断周期。如果需要修改时间片时间长短,就要修改滴答定时器中断频率。

如果任务提前结束,直接进行下一个任务,没有用完的时间不会在使用,无论是下一个任务还是本任务再次执行都按一个时间片节拍运行。

运行过程:

1、Task1运行完一个时间片后,切换到Task2运行

2、Task2运行完一个时间片后,切换到Task3运行

3、Task3运行过程中,Task3阻塞了(系统延时或等待信号量等),此时直接切换到下一个任务

二、实验演示

1、宏修改

1.1、滴答定时器宏

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

实验要求一个时间片是50ms,则设置为20Hz

1.2、调度器宏

#define configUSE_PREEMPTION 1 /* 1: 抢占式调度器, 0: 协程式调度器, 无默认需定义 */

#define configUSE_TIME_SLICING 1 /* 1: 使能时间片调度, 默认: 1 */

都设置为1

2、实验程序

2.1.1、任务1,任务2不加临界区程序

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

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

void start_task( void * pvParameters );

#define TASK1_STACK_SIZE 128
#define TASK1_PRIO       2
TaskHandle_t task1_handler;
void task1( void * pvParameters );

#define TASK2_STACK_SIZE 128
#define TASK2_PRIO       2
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(); 		/*退出临界区*/				 
}

void task1( void * pvParameters )
{
	uint32_t task1_num = 0;
	while(1)
	{
		printf("task1运行次数:%d\r\n",++task1_num);
		delay_ms(10);//FreeRTOS的延迟函数会将任务挂载到阻塞列表,导致任务提前结束
								//而delay_ms()只会死等		
	}
}

void task2( void * pvParameters )
{
	uint32_t task2_num = 0;
	while(1)
	{
		printf("task2运行次数:%d\r\n",++task2_num);
		delay_ms(10);		
	}
	
	
}

2.1.2 实验现象

打印出运行次数,但是会出现打印的不完整。因为本次任务未执行完,调度器切换到下一个任务

2.2.1、任务1,任务2加临界区程序

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

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

void start_task( void * pvParameters );

#define TASK1_STACK_SIZE 128
#define TASK1_PRIO       2
TaskHandle_t task1_handler;
void task1( void * pvParameters );

#define TASK2_STACK_SIZE 128
#define TASK2_PRIO       2
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(); 		/*退出临界区*/				 
}

void task1( void * pvParameters )
{
	uint32_t task1_num = 0;
	while(1)
	{
		taskENTER_CRITICAL();/*进入临界区*/
		printf("task1运行次数:%d\r\n",++task1_num);
		delay_ms(10);//FreeRTOS的延迟函数会将任务挂载到阻塞列表,导致任务提前结束
								//而delay_ms()只会死等
		taskEXIT_CRITICAL(); 		/*退出临界区*/			
	}
}

void task2( void * pvParameters )
{
	uint32_t task2_num = 0;
	while(1)
	{
		taskENTER_CRITICAL();/*进入临界区*/
		printf("task2运行次数:%d\r\n",++task2_num);
		delay_ms(10);
		taskEXIT_CRITICAL(); 		/*退出临界区*/			
	}
	
	
}

2.2.2 实验现象

可以看到由于临界区保护,都打印出了完整的信息

相关推荐
A懿轩A37 分钟前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
云边有个稻草人41 分钟前
【优选算法】—复写零(双指针算法)
笔记·算法·双指针算法
南宫生8 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
sanguine__9 小时前
Web APIs学习 (操作DOM BOM)
学习
冷眼看人间恩怨9 小时前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
数据的世界0111 小时前
.NET开发人员学习书籍推荐
学习·.net
四口鲸鱼爱吃盐11 小时前
CVPR2024 | 通过集成渐近正态分布学习实现强可迁移对抗攻击
学习
OopspoO13 小时前
qcow2镜像大小压缩
学习·性能优化
A懿轩A14 小时前
C/C++ 数据结构与算法【栈和队列】 栈+队列详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·栈和队列
居居飒14 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin