FreeRTOS之空闲任务与阻塞延时的实现

1、 修改TCB控制块,在后面添加TickType_t xTicksToDelay;

typedef struct tskTaskControlBlock{
	volatile StackType_t *pxTopOfStack;
	ListItem_t xStateListItem;
	StackType_t *pxStack;
	char pcTaskName[configMAX_TASK_NAME_LEN];
	TickType_t xTicksToDelay; /*  用于延时 */
}taskTCB;

2、 编写空闲任务相关
2.1、 在FreeRTOS文件夹下新建idle_task.c和idle_task.h,添加到工程中。
2.2、 撸代码

#include "task.h"
#include "portable.h"
#include "idle_task.h"


#define configMINIMAL_STACK_SIZE  ( ( unsigned short ) 128 )
StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE];
TCB_t IdleTaskTCB;


uint32_t idle_task_flag1=0;
static void prvIdleTask( void *p_arg )
{
	uint32_t temp=0;
	( void ) p_arg;
    
    for(;;)
    {
		temp++;
		if (temp>6000)
		{
			temp=0;
			idle_task_flag1++;
			idle_task_flag1 = idle_task_flag1&0x01;
		}

    }
}
void AppTaskCreateIdleTask(void)
{
	xTaskCreateStatic(prvIdleTask,"IdleTask",configMINIMAL_STACK_SIZE,0,IdleTaskStack,&IdleTaskTCB);
	/* 插入就绪列表*/
	vListInsertEnd( &( pxReadyTasksLists[0] ), &( ((TCB_t *)(&IdleTaskTCB))->xStateListItem ) );

}

3、实现阻塞延时。在task.c文件下编写vTaskDelay ()函数。

void vTaskDelay(const TickType_t xTicksToDelay)
{
	TCB_t *pxTCB = NULL;
	
	pxTCB = pxCurrentTCB;
	
	pxTCB->xTicksToDelay = xTicksToDelay;
	
	taskYIELD();
}

4、 修改 vTaskSwitchContext()函数

void vTaskSwitchContext( void )
{
	if (pxCurrentTCB==&IdleTaskTCB)
	{
		if (Task1TCB.xTicksToDelay == 0)
		{
			pxCurrentTCB = &Task1TCB;
		}else if (Task2TCB.xTicksToDelay == 0)
		{
			pxCurrentTCB = &Task2TCB;
		}
	}else if (pxCurrentTCB==&Task1TCB)
	{
		if (Task2TCB.xTicksToDelay == 0)
		{
			pxCurrentTCB = &Task2TCB;
		}else
		{
			pxCurrentTCB = &IdleTaskTCB;
		}
	}else if (pxCurrentTCB==&Task2TCB)
	{
		if (Task1TCB.xTicksToDelay == 0)
		{
			pxCurrentTCB = &Task1TCB;
		}else
		{
			pxCurrentTCB = &IdleTaskTCB;
		}
	}
}

5、 编写SysTick中断服务函数
5.1、 在FreeRTOS文件夹下新建sys_tick.c和sys_tick.h,添加到工程中。
5.2、 撸代码


#include "sys_tick.h"
#include "port.h"
#include "task.h"
#include "task_lists.h"


// SysTick 中断服务函数======================================

#define configCPU_CLOCK_HZ			( ( unsigned long ) 25000000 )	
#define configTICK_RATE_HZ			( ( TickType_t ) 100 )
	
	
#define portNVIC_SYSTICK_LOAD_REG			( * ( ( volatile uint32_t * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CTRL_REG			( * ( ( volatile uint32_t * ) 0xe000e010 ) )

#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
#define portNVIC_SYSTICK_CLK_BIT	( 1UL << 2UL )

#define portNVIC_SYSTICK_INT_BIT			( 1UL << 1UL )
#define portNVIC_SYSTICK_ENABLE_BIT			( 1UL << 0UL )
void vPortSetupTimerInterrupt(void)
{

    portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
    
 
    portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | 
                                  portNVIC_SYSTICK_INT_BIT |
                                  portNVIC_SYSTICK_ENABLE_BIT ); 
}
static volatile TickType_t xTickCount 				= ( TickType_t ) 0U;
void xTaskIncrementTick( void )
{
    TCB_t *pxTCB = NULL;
    BaseType_t i = 0;
    

    const TickType_t xConstTickCount = xTickCount + 1;
    xTickCount = xConstTickCount;

    

	for(i=0; i<configMAX_PRIORITIES; i++)
	{
        pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &pxReadyTasksLists[i] ) );
		if(pxTCB->xTicksToDelay > 0)
		{
			pxTCB->xTicksToDelay --;
		}
	}
    
    portYIELD();
}

6、 在port.c文件添加如下代码

void xPortSysTickHandler( void )
{

    vPortRaiseBASEPRI();
    
    xTaskIncrementTick();

    vPortClearBASEPRIFromISR();
}

7、 修改Task1_Entry和Task2_Entry函数

uint32_t flag1=0;
uint32_t flag2=0;
void Task1_Entry( void *p_arg )
{
    for( ;; )
    {
        flag1 = 1;
        vTaskDelay(2);//delay( 100 );
        flag1 = 0;
        vTaskDelay(2);//delay( 100 );
        //portYIELD();
    }
}
void Task2_Entry( void *p_arg )
{
    for( ;; )
    {
        flag2 = 1;
        vTaskDelay(2);//delay( 100 );
        flag2 = 0;
        vTaskDelay(2);//delay( 100 );
        //portYIELD();
    }
}

8、 修改main.c

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 ) );
	/* 创建空闲任务*/
	AppTaskCreateIdleTask();
	/* 初始化 SysTick*/
	vPortSetupTimerInterrupt();
	/*启动任务*/
	vTaskStartScheduler();
	
	//理论是不会到这里
	while(1){}
}

运行结果如下
在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值