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

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

相关推荐
程序员大雄学编程1 小时前
「机器学习笔记7」决策树学习:从理论到实践的全面解析(上)
笔记·决策树·机器学习
larry_dongy1 小时前
【学习记录】vscode+ros2+cpp调试
vscode·学习
递归不收敛2 小时前
吴恩达机器学习课程(PyTorch适配)学习笔记:1.5 决策树与集成学习
pytorch·学习·机器学习
菜鸟‍2 小时前
【论文学习】2025年图像处理顶会论文
图像处理·人工智能·学习
Logintern092 小时前
【学习篇】Redis 分布式锁
redis·分布式·学习
聪明的笨猪猪2 小时前
Java Spring “Bean” 面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
A9better2 小时前
嵌入式开发学习日志38——stm32之看门狗
stm32·嵌入式硬件·学习
bnsarocket3 小时前
Verilog和FPGA的自学笔记3——仿真文件Testbench的编写
笔记·fpga开发·verilog·自学
丰锋ff3 小时前
2025 年真题配套词汇单词笔记(考研真相)
笔记·考研
Vizio<5 小时前
《基于 ERT 的稀疏电极机器人皮肤技术》ICRA2020论文解析
论文阅读·人工智能·学习·机器人·触觉传感器