FreeRTOS之任务切换

1、 编写任务列表。
1.1、在FreeRTOS文件夹下新建task_list.c和task_list.h文件,添加到工程中。
1.2、 撸代码

#include "task_lists.h"
List_t pxReadyTasksLists[ configMAX_PRIORITIES ];
//初始就绪链表======================================================
void prvInitialiseTaskLists( void )
{
	UBaseType_t uxPriority;
	
	for (uxPriority=0; uxPriority<configMAX_PRIORITIES; uxPriority++)
	{
		vListInitialise(&pxReadyTasksLists[uxPriority]);
	}
}

2、 编写芯片相关的函数
2.1、 在FreeRTOS文件夹下新建port.c和port.h,添加到工程中。
2.2、 撸代码
①pxPortInitialiseStack 函数是栈的初始化
②prvStartFirstTask 触发 vPortSVCHandler
③xPortStartScheduler启动调度器。
④ vPortSVCHandler处理函数
⑤xPortPendSVHandler处理函数。是由#define portYIELD() 触发

3、 编写任务相关的函数
3.1、 在FreeRTOS文件夹下新建task.c和task.h,添加到工程中。
3.1、 撸代码

#include "task.h"


TCB_t * volatile pxCurrentTCB=NULL;

static void prvInitialiseNewTask( 	TaskFunction_t pxTaskCode,			/* 任务入口*/	        
									const char * const pcName,			/* 任务名称*/  
									const uint32_t ulStackDepth,		/* 任务栈大小,单位为字*/     
									void * const pvParameters,			/* 任务形参*/     
									TaskHandle_t * const pxCreatedTask,	/* 任务栈的起始地址*/
									TCB_t *pxNewTCB )  					/* 任务控制块*/
{
	StackType_t *pxTopOfStack;
	UBaseType_t x;
	
	/* 获取栈顶地址*/
	pxTopOfStack = pxNewTCB->pxStack + (ulStackDepth-(uint32_t)1);
	/* 向下做8字节对齐*/
	pxTopOfStack = ( StackType_t * ) ( ( ( uint32_t ) pxTopOfStack ) & ( ~( ( uint32_t ) 0x0007 ) ) );
	
	/* 将任务的名字存储在TCB中*/
	for (x=0; x<configMAX_TASK_NAME_LEN; x++)
	{
		pxNewTCB->pcTaskName[x] = pcName[x];
		if (pcName[x]==0x00)
			break;
	}
	pxNewTCB->pcTaskName[configMAX_TASK_NAME_LEN-1] = '\0';
	
	vListInitialiseItem(&(pxNewTCB->xStateListItem));
	listSET_LIST_ITEM_OWNER(&(pxNewTCB->xStateListItem),pxNewTCB);
	
	pxNewTCB->pxTopOfStack = pxPortInitialiseStack(pxTopOfStack,pxTaskCode,pvParameters);
	
	/* 让任务句柄指向任务控制块*/
	if ( (void*)pxCreatedTask !=NULL)
	{
		pxCreatedTask[0] = (TaskHandle_t)pxNewTCB;
	}
	
}
TaskHandle_t xTaskCreateStatic(	TaskFunction_t pxTaskCode,
					            const char * const pcName,
					            const uint32_t ulStackDepth,
					            void * const pvParameters,
					            StackType_t * const puxStackBuffer,
					            TCB_t * const pxTaskBuffer )
{
	TCB_t *pxNewTCB;
	TaskHandle_t xReturn = NULL;
	
	if ( pxTaskBuffer!=NULL && puxStackBuffer!=NULL)
	{
		pxNewTCB = (TCB_t*)pxTaskBuffer;
		pxNewTCB->pxStack = (StackType_t*)puxStackBuffer;
		prvInitialiseNewTask(	pxTaskCode,		/* 任务入口*/	        
								pcName,			/* 任务名称*/          
								ulStackDepth,	/* 任务栈大小,单位为字*/      
								pvParameters,	/* 任务形参*/     
								&xReturn,		/* 任务句柄*/       
								pxNewTCB);		/* 任务控制块*/
	}
	return xReturn;
}


extern TCB_t Task1TCB;
extern TCB_t Task2TCB;
void vTaskStartScheduler( void )
{
	pxCurrentTCB = &Task1TCB;
	/* 启用调度器*/
	xPortStartScheduler();
	//理论是不会到这里
	while(1){}
	
}
void vTaskSwitchContext( void )
{    
    if( pxCurrentTCB == &Task1TCB )
    {
        pxCurrentTCB = &Task2TCB;
    } else
    {
        pxCurrentTCB = &Task1TCB;
    }
}

4、编写2个任务

4.1、 在User文件夹下新建app_task.c和app_task.h,添加到工程中。
4.1、 撸代码

#include "app_task.h"
uint32_t flag1=0;
uint32_t flag2=0;
void delay (uint32_t count)
{
    for(; count!=0; count--);
}
void Task1_Entry( void *p_arg )
{
    for( ;; )
    {
        flag1 = 1;
        delay( 100 );
        flag1 = 0;
        delay( 100 );

        portYIELD();

    }
}
void Task2_Entry( void *p_arg )
{
    for( ;; )
    {
        flag2 = 1;
        delay( 100 );
        flag2 = 0;
        delay( 100 );

        portYIELD();
    }
}

5、 修改mian.c

#include "portmacro.h"
#include "list.h"
#include "task_lists.h"
#include "task.h"
#include "app_task.h"
#include "port.h"


TaskHandle_t Task1_Handle;
#define TASK1_STACK_SIZE                    20
StackType_t Task1Stack[TASK1_STACK_SIZE];
TCB_t Task1TCB;

TaskHandle_t Task2_Handle;
#define TASK2_STACK_SIZE                    20
StackType_t Task2Stack[TASK2_STACK_SIZE];
TCB_t Task2TCB;


int main(void)
{
 	/* 就绪列表初始化*/
	prvInitialiseTaskLists();
	
	
	/* 创建任务1*/
	Task1_Handle = xTaskCreateStatic(Task1_Entry,"task1",TASK1_STACK_SIZE,0,Task1Stack,&Task1TCB);
	/* 插入就绪列表*/
	vListInsertEnd( &( pxReadyTasksLists[1] ), &( ((TCB_t *)(&Task1TCB))->xStateListItem ) );
	/* 创建任务2*/
	Task2_Handle = xTaskCreateStatic(Task2_Entry,"task2",TASK2_STACK_SIZE,0,Task2Stack,&Task2TCB);
	/* 插入就绪列表*/
	vListInsertEnd( &( pxReadyTasksLists[2] ), &( ((TCB_t *)(&Task2TCB))->xStateListItem ) );
	
	/*启动任务*/
	vTaskStartScheduler();
	
	//理论是不会到这里
	while(1){}
}

项目结构如下:
在这里插入图片描述

运行结果如下

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值