IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> FreeRTOS任务启动流程实践 -> 正文阅读

[嵌入式]FreeRTOS任务启动流程实践


前言

最近熟悉一款基于M4内核的国产芯片,移植FreeRTOS v10.3.1,学习并实践任务启动的流程,做如下实践笔记。


一、移植FreeRTOS框架

系统的移植部分不做详细说明,移植完成后如下图所示。

在这里插入图片描述

二、任务创建步骤

1.定义任务实体函数

代码如下(示例):

//任务必须是死循环,且无返回值。
static void Task1_Crt(void)
{
	printf("create task1.\n");
	while(1)
	{
		printf("task1.\n");
		vTaskDelay(500);
	}
}
static void Task2_Crt(void)
{
	printf("create task2.\n");
	while(1)
	{
		printf("task2.\n");
		vTaskDelay(1000);
	}
}

2.创建任务

2.1 定义任务栈

2.1.1定义静态任务栈

则需要优先定义Stack,栈空间从SRAM分配,地址由编译器决定。
代码如下(示例):

//main.c
static StackType_t CreateAppTask_Stack[128]; //定义任务栈
//FreeRTOSConfig.h
/* Memory allocation related definitions. */
//1: 内存静态分配
#define configSUPPORT_STATIC_ALLOCATION         0

2.1.2定义动态任务堆

则需定义Heap内存,从SRAM划分一块连续内存,于 heap_x.c 中实现。

代码如下(示例):

//FreeRTOSConfig.h
//1: 内存动态分配,没有配置此选项时系统默认使用动态分配方式
#define configSUPPORT_DYNAMIC_ALLOCATION        1
//堆大小
#define configTOTAL_HEAP_SIZE		            ( ( size_t ) ( 15 * 1024 ) )
//1: 允许应用程序将堆放在内存中的任意位置
#define configAPPLICATION_ALLOCATED_HEAP        0
//heap_4.c
/* Allocate the memory for the heap. */
#if( configAPPLICATION_ALLOCATED_HEAP == 1 )
	/* The application writer has already defined the array used for the RTOS
	heap - probably so it can be placed in a special segment or address. */
	extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#else
	static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#endif /* configAPPLICATION_ALLOCATED_HEAP */


void *pvPortMalloc( size_t xWantedSize )
{
	//...
	if( pxEnd == NULL )
	{
		prvHeapInit(); //调用 ucHeap[]
	}
	//...
}
//tasks.c
void xTaskCreate()
{
	//...
	pvPortMalloc();
	//...
}

2.2.定义任务控制块TCB

2.2.1 静态任务TCB

实例化TCB空间

//main.c
//CreateAppTask任务控制块
static StaticTask_t CreateAppTask_TCB; 
static TaskHandle_t AppTaskCreate_Handle = NULL;  

2.2.2 动态任务TCB

异于静态创建,无需预先定义TCB空间,但需定义一个TCB指针,即Task_handle

//main.c
//创建任务句柄
static TaskHandle_t AppTaskCreate_Handle = NULL;  

2.3创建任务

2.3.1静态创建

//main.c
//空闲任务
static StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE];
static StaticTask_t IdleTaskTCB;

//定时器任务
static StackType_t TimerTaskStack[configTIMER_TASK_STACK_DEPTH];
static StaticTask_t TimerTaskTCB;

//开始任务
#define START_TASK_PRIO		1
#define START_STK_SIZE 		128  
StackType_t StartTaskStack[START_STK_SIZE];
StaticTask_t StartTaskTCB;
TaskHandle_t StartTask_Handler;
void start_task(void *pvParameters);

//任务1变量声明
#define TASK1_TASK_PRIO		2
#define TASK1_STK_SIZE 		128  
StackType_t Task1TaskStack[TASK1_STK_SIZE];
StaticTask_t Task1TaskTCB;
TaskHandle_t Task1Task_Handler;
void task1_task(void *pvParameters);

//任务2声明变量
#define TASK2_TASK_PRIO		3	
#define TASK2_STK_SIZE 		128 
StackType_t Task2TaskStack[TASK2_STK_SIZE];
StaticTask_t Task2TaskTCB;
TaskHandle_t Task2Task_Handler;
void task2_task(void *pvParameters);
//空闲任务
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, 
								   StackType_t **ppxIdleTaskStackBuffer, 
								   uint32_t *pulIdleTaskStackSize)
{
	*ppxIdleTaskTCBBuffer=&IdleTaskTCB;
	*ppxIdleTaskStackBuffer=IdleTaskStack;
	*pulIdleTaskStackSize=configMINIMAL_STACK_SIZE;
}
//定时器任务
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, 
									StackType_t **ppxTimerTaskStackBuffer, 
									uint32_t *pulTimerTaskStackSize)
{
	*ppxTimerTaskTCBBuffer=&TimerTaskTCB;
	*ppxTimerTaskStackBuffer=TimerTaskStack;
	*pulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH;
}

2.3.2 动态创建

//main.c
//创建 AppTaskCreate 任务
xReturn = xTaskCreate( (TaskFunction_t )AppTaskCreate,       
			  (const char* )"AppTaskCreate",        
			  (uint16_t )512,                
			  (void* )NULL,                  
			  (UBaseType_t )1,                
			  (TaskHandle_t* )&AppTaskCreate_Handle);  
			  
if (pdPASS == xReturn)
	vTaskStartScheduler(); 
else 
	return -1;
static TaskHandle_t Task1Create_Handle = NULL;
static TaskHandle_t Task2Create_Handle = NULL;
TaskFunction_t AppTaskCreate()
{
	BaseType_t xReturn = pdPASS;
	xReturn = xTaskCreate( (TaskFunction_t )Task1_Crt,       
			  (const char* )"Taks1",        
			  (uint16_t )512,                
			  (void* )NULL,                  
			  (UBaseType_t )2,                
			  (TaskHandle_t* )&Task1Create_Handle);  
	if(1){};
		printf("Re1:%d\n", (int)xReturn);
			  
	xReturn = xTaskCreate( (TaskFunction_t )Task2_Crt,       
			  (const char* )"Task2",        
			  (uint16_t )512,                
			  (void* )NULL,                  
			  (UBaseType_t )3,                
			  (TaskHandle_t* )&Task2Create_Handle);  
	if(1){};
		printf("Re2:%d\n", (int)xReturn);
			  
	vTaskDelete(AppTaskCreate_Handle); 
}

2.3.3 整体代码

/************************************
*	Create task, prime conditions are concrete objects, defination of TCB, also the task of creation.
*	
*/
static void Task1_Crt(void)
{
	printf("create task1.\n");
	while(1)
	{
		printf("task1.\n");
		vTaskDelay(500);
	}
}

static void Task2_Crt(void)
{
	printf("create task2.\n");
	while(1)
	{
		printf("task2.\n");
		vTaskDelay(1000);
	}
}

#if !(configSUPPORT_DYNAMIC_ALLOCATION & configSUPPORT_STATIC_ALLOCATION)
static TaskHandle_t StartTaskCreate_Handle = NULL;	//static/dynamic task
static TaskHandle_t Task1Create_Handle = NULL;
static TaskHandle_t Task2Create_Handle = NULL;
TaskFunction_t StartTaskCreate(void)
{
	BaseType_t xReturn = pdPASS;
	taskENTER_CRITICAL();

	xReturn = xTaskCreate( (TaskFunction_t )Task1_Crt,       
			  (const char* )"Taks1",        
			  (uint16_t )512,                
			  (void* )NULL,                  
			  (UBaseType_t )2,                
			  (TaskHandle_t* )&Task1Create_Handle);  
	if(1){};
		printf("Re1:%d\n", (int)xReturn);
			  
	xReturn = xTaskCreate( (TaskFunction_t )Task2_Crt,       
			  (const char* )"Task2",        
			  (uint16_t )512,                
			  (void* )NULL,                  
			  (UBaseType_t )3,                
			  (TaskHandle_t* )&Task2Create_Handle);  
	if(1){};
		printf("Re2:%d\n", (int)xReturn);
			  
	vTaskDelete(AppTaskCreate_Handle);
	taskEXIT_CRITICAL();
}
#else
//idle
static StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE];
static StaticTask_t IdleTaskTCB;

//timer
static StackType_t TimerTaskStack[configTIMER_TASK_STACK_DEPTH];
static StaticTask_t TimerTaskTCB;

//start
#define START_TASK_PRIO		1
#define START_STK_SIZE 		128  
StackType_t StartTaskStack[START_STK_SIZE];
StaticTask_t StartTaskTCB;
TaskHandle_t StartTask_Handler;

//1
#define TASK1_TASK_PRIO		2
#define TASK1_STK_SIZE 		128  
StackType_t Task1TaskStack[TASK1_STK_SIZE];
StaticTask_t Task1TaskTCB;
TaskHandle_t Task1Task_Handler;


//2
#define TASK2_TASK_PRIO		3	
#define TASK2_STK_SIZE 		128 
StackType_t Task2TaskStack[TASK2_STK_SIZE];
StaticTask_t Task2TaskTCB;
TaskHandle_t Task2Task_Handler;

TaskFunction_t StartTaskCreate(void)
{
    taskENTER_CRITICAL();         
    //1
	Task1Task_Handler=xTaskCreateStatic((TaskFunction_t	)Task1_Crt,		
										(const char* 	)"task1_task",		
										(uint32_t 		)TASK1_STK_SIZE,	
										(void* 		  	)NULL,				
										(UBaseType_t 	)TASK1_TASK_PRIO, 	
										(StackType_t*   )Task1TaskStack,	
										(StaticTask_t*  )&Task1TaskTCB);	
   //2
	Task2Task_Handler=xTaskCreateStatic((TaskFunction_t	)Task2_Crt,		
										(const char* 	)"task2_task",		
										(uint32_t 		)TASK2_STK_SIZE,	
										(void* 		  	)NULL,				
										(UBaseType_t 	)TASK2_TASK_PRIO, 	
										(StackType_t*   )Task2TaskStack,	
										(StaticTask_t*  )&Task2TaskTCB);
    vTaskDelete(StartTask_Handler); //del start
    taskEXIT_CRITICAL();          
}

//idle
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, 
								   StackType_t **ppxIdleTaskStackBuffer, 
								   uint32_t *pulIdleTaskStackSize)
{
	*ppxIdleTaskTCBBuffer=&IdleTaskTCB;
	*ppxIdleTaskStackBuffer=IdleTaskStack;
	*pulIdleTaskStackSize=configMINIMAL_STACK_SIZE;
}
//timer
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, 
									StackType_t **ppxTimerTaskStackBuffer, 
									uint32_t *pulTimerTaskStackSize)
{
	*ppxTimerTaskTCBBuffer=&TimerTaskTCB;
	*ppxTimerTaskStackBuffer=TimerTaskStack;
	*pulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH;
}
#endif

int main()
{
	BaseType_t xReturn = pdPASS;
	Sys_Init(); 
	Reback_Boot();
	UART_Debug_Init(SCI1,g_ips_clk, 115200);
	Printf_Version();
//	App_Demo();
#if !(configSUPPORT_DYNAMIC_ALLOCATION & configSUPPORT_STATIC_ALLOCATION)
	xReturn = xTaskCreate( (TaskFunction_t )StartTaskCreate,       
				  (const char* )"StartTaskCreate",        
				  (uint16_t )512,                
				  (void* )NULL,                  
				  (UBaseType_t )1,                
				  (TaskHandle_t* )&AppTaskCreate_Handle);  
#else
	StartTask_Handler = xTaskCreateStatic((TaskFunction_t )StartTaskCreate, 
						(const char* )"StartTaskCreate",
						(uint32_t )START_STK_SIZE,
						(void* )NULL,
						(UBaseType_t )START_TASK_PRIO, 
						(StackType_t*   )StartTaskStack,
						(StaticTask_t*  )&StartTaskTCB);
#endif
	if (pdPASS == xReturn)
		vTaskStartScheduler(); 
	else 
		return -1;
}

2.4启动现象

在这里插入图片描述


参考

  1. 启动流程-孤情剑客
  2. 静态任务-匿名
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-03-03 16:31:24  更:2022-03-03 16:33:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 8:22:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码