基于正点原子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 实验现象

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

相关推荐
chushiyunen7 分钟前
dom操作笔记、xml和document等
xml·java·笔记
chushiyunen10 分钟前
tomcat使用笔记、启动失败但是未打印日志
java·笔记·tomcat
汇能感知14 分钟前
光谱相机的光谱数据采集原理
经验分享·笔记·科技
人人题37 分钟前
汽车加气站操作工考试答题模板
笔记·职场和发展·微信小程序·汽车·创业创新·学习方法·业界资讯
小脑斧爱吃鱼鱼1 小时前
鸿蒙项目笔记(1)
笔记·学习·harmonyos
阿linlin1 小时前
OpenCV--图像预处理学习01
opencv·学习·计算机视觉
张张张3122 小时前
4.2学习总结 Java:list系列集合
java·学习
SuperW2 小时前
linux课程学习二——缓存
学习
lulinhao2 小时前
HCIA/HCIP基础知识笔记汇总
网络·笔记
杉之3 小时前
SpringBlade 数据库字段的自动填充
java·笔记·学习·spring·tomcat