栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

FreeRTOS复习笔记(二) —— 任务

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

FreeRTOS复习笔记(二) —— 任务

FreeRTOS复习笔记(二) —— 任务

一、创建任务

1.本例程思路:

1). 调用 xTaskCreateStatic 函数静态创建任务 LED_Task;
LED_Task 控制 LED 每间隔一段时间翻转一次
2). 调用 xTaskCreate 函数动态创建任务 AppTaskCreate_Task;
AppTaskCreate_Task 动态创建任务 LED_Task 与 LED2_Task;
LED_Task 与 LED2_Task 分别控制 LED 与 LED2 每隔一段时间翻转一次

本篇将静态创建与动态创建写入同一段代码,使用 _USE_STATIC_MODE 与 _USE_DYNAMIC_MODE 进行区分

其中,
动态创建方式,初始化相关资源(中断, GPIO等)后,直接调用任务创建函数 xTaskCreate 创建任务,随后开启任务调度器即可(任务函数执行的内容自行实现);
而静态创建方式,需要手动开辟存储空间(任务堆栈, 任务控制块,包括IdleTask与TimerTask),随后可以直接调用 xTaskCreateStatic 函数创建任务,调用 vTaskStartScheduler 函数开启任务调度器

启动任务调度器后,任务调度器会自动创建一个IdleTask任务,以保证始终能有一个任务在运行,所以使用静态方式创建任务时需要手动为IdleTask分配空间(实现 vApplicationGetIdleTaskMemory 函数)

2.代码编写

#include "stm32f10x.h"

#include "dr_usart.h"
#include "dr_led.h"

#include "FreeRTOS.h"
#include "task.h"



#if defined(_USE_STATIC_MODE)
	#define USER_DEFAULT_STACK_SIZE  ((unsigned short)128) //任务堆栈大小
	
	
	StackType_t  Idle_Task_Stack[USER_DEFAULT_STACK_SIZE];                  //
	StaticTask_t Idle_Task_TCB;                                             //
	
	
	StackType_t  Timer_Task_Stack[USER_DEFAULT_STACK_SIZE];                 //
	StaticTask_t Timer_Task_TCB;                                            //
	
	
	StackType_t  LED_Task_Stack[USER_DEFAULT_STACK_SIZE];                   //
	StaticTask_t LED_Task_TCB;                                              //
	TaskHandle_t LED_Task_Handle;
	void LED_Task(void *);
#endif

#if defined(_USE_DYNAMIC_MODE)
	
	void AppTaskCreate_Task(void *);
	void LED_Task(void *);
	void LED2_Task(void *);
#endif


int main(void)
{
	
	
	
	NVIC_Priority_Group_Config();                                        
	
	
	USART1_Config();                                                     
	
	
	LED_GPIO_Config();                                                   
	
	

	
#if defined(_USE_STATIC_MODE)
	LED_Task_Handle = xTaskCreateStatic( LED_Task,        //指向任务函数
										 "LED_Task",      //任务名称
										 USER_DEFAULT_STACK_SIZE, //任务堆栈大小
										 (void *)NULL, 1, //任务参数, 任务优先级
										 LED_Task_Stack,  //任务堆栈地址
										 &LED_Task_TCB ); //任务控制块地址
#endif

	
#if defined(_USE_DYNAMIC_MODE)
	
	xTaskCreate(AppTaskCreate_Task, "AppTaskCreate_Task", 128, NULL, 1, NULL);
#endif

	
	vTaskStartScheduler();
	
	while(1);
}

#if defined(_USE_DYNAMIC_MODE)


void AppTaskCreate_Task(void *pvParameters)
{
	
	taskENTER_CRITICAL();
	
	
	xTaskCreate(LED_Task, "LED_Task", 128, NULL, 2, NULL);
	
	
	xTaskCreate(LED2_Task, "LED2_Task", 128, NULL, 3, NULL);
	
	
	vTaskDelete(NULL);
	
	
	taskEXIT_CRITICAL();
}

#endif


void LED_Task(void *pvParameters)
{
	for(;;)
	{
		
		GPIOA->ODR ^= ((uint16_t)0x0100);
		
		
		vTaskDelay(50);
	}
}

#if defined(_USE_DYNAMIC_MODE)


void LED2_Task(void *pvParameters)
{
	for(;;)
	{
		
		GPIOA->ODR ^= ((uint16_t)0x0040);
		
		
		vTaskDelay(50);
	}
}

#endif

#if defined(_USE_STATIC_MODE)


void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
									StackType_t **ppxIdleTaskStackBuffer,
									uint32_t *pulIdleTaskStackSize )
{
	*ppxIdleTaskTCBBuffer = &Idle_Task_TCB;          //指向任务控制块
	*ppxIdleTaskStackBuffer = Idle_Task_Stack;       //指向任务堆栈
	*pulIdleTaskStackSize = USER_DEFAULT_STACK_SIZE; //任务堆栈大小
}


void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer,
									 StackType_t **ppxTimerTaskStackBuffer,
									 uint32_t *pulTimerTaskStackSize )
{
	*ppxTimerTaskTCBBuffer = &Timer_Task_TCB;
	*ppxTimerTaskStackBuffer = Timer_Task_Stack;
	*pulTimerTaskStackSize = USER_DEFAULT_STACK_SIZE;
}

#endif

3.调用逻辑分析仪观察(动态时,两个LED应同时翻转)

静态创建(任务:LED_Task)


动态创建(任务:LED_Task,LED2_Task)

经验证,程序运行结果与预想一致

二、任务挂起与恢复

1.本例程思路:

分别创建两个任务,LEDTask 与 KEYTask,LEDTask 控制 LED 每隔一段时间翻转一次,KEYTask 检测 KEY_GPIO(PA0) 的状态,第一次出现下降沿时调用 vTaskSuspend 函数挂起 LEDTask,第二次出现下降时调用 vTaskResume 函数沿恢复 LEDTask,依次循环

2.代码编写

#include "stm32f10x.h"

#include "dr_usart.h"
#include "dr_led.h"
#include "dr_key.h"

#include "FreeRTOS.h"
#include "task.h"


TaskHandle_t LEDTask_Handle = NULL;


void AppTaskCreateTask(void *);
void LEDTask(void *);
void KEYTask(void *);


int main(void)
{
	
	
	
	NVIC_Priority_Group_Config();                                        
	
	
	USART1_Config();                                                     
	
	
	LED_GPIO_Config();                                                   
	
	
	KEY_GPIO_Config();
	
	

	
	xTaskCreate(AppTaskCreateTask, "AppTaskCreateTask", 128, NULL, 1, NULL);

	
	vTaskStartScheduler();
	
	while(1);
}


void AppTaskCreateTask(void *pvParameters)
{
	
	taskENTER_CRITICAL();
	
	
	xTaskCreate(LEDTask, "LEDTask", 128, NULL, 2, &LEDTask_Handle);
	
	xTaskCreate(KEYTask, "KEYTask", 128, NULL, 3, NULL);
	
	vTaskDelete(NULL);
	
	taskEXIT_CRITICAL();
}


void LEDTask(void *pvParameters)
{
	for (;;)
	{
		
		GPIOA->ODR ^= ((uint16_t)0x0100);
		
		
		printf("LED %srn", ((GPIOA->IDR & 0x0100) != 0) ? "is running." : "stops running.");
		
		
		vTaskDelay(50);
	}
}


void KEYTask(void *pvParameters)
{
	uint8_t level_high = 0;
	uint8_t level_low  = 0;
	uint8_t edge_fall  = 0;
	uint8_t edge_rise  = 0;
	
	uint8_t _switch = 0;
	
	for (;;)
	{
		if ( (GPIOA->IDR & 0x0001) != 0 ) 
		{
			if(level_low == 1)
				edge_rise = 1; 
				
			level_low  = 0;
			level_high = 1;
		} 
		
		if ( (GPIOA->IDR & 0x0001) == 0 ) 
		{
			if(level_high == 1)
				edge_fall  = 1; 
				
			level_high = 0; 
			level_low  = 1;
		} 
		
		if(edge_fall)
		{
			if(_switch == 0) 
			{
				_switch = 1;
				
				printf("--- Suspend ---.n");
			
				
				vTaskSuspend(LEDTask_Handle);
			}
			else
			{
				_switch = 0;
			
				printf("--- Resume ---.n");
				
				
				vTaskResume(LEDTask_Handle);
			}
		}
	
		edge_fall = 0;
		edge_rise = 0;
		
		(void)edge_rise;
	
		
		vTaskDelay(20);
	}
}

3.调用逻辑分析仪观察

经验证,程序运行结果与预想一致

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/690087.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号