FreeRTOS之任务延时列表的实现

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

#include "delay_lists.h"
#include "sys_tick.h"


List_t xDelayedTaskList1;
List_t xDelayedTaskList2;
List_t * volatile pxDelayedTaskList;
List_t * volatile pxOverflowDelayedTaskList;
volatile TickType_t xNextTaskUnblockTime		= ( TickType_t ) 0U;

/* 初始化延迟列表*/
void prvInitialiseDelayLists(void)
{
	vListInitialise( &xDelayedTaskList1 );
	vListInitialise( &xDelayedTaskList2 );

	pxDelayedTaskList = &xDelayedTaskList1;
	pxOverflowDelayedTaskList = &xDelayedTaskList2;
	
	xNextTaskUnblockTime = portMAX_DELAY;
}
/*将任务从就绪列表移除。
判断对应的位是否存在任务,如果不存在则将对应的位清0
就算出延迟时间,添加到延迟列表当中。*/
void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait )
{
    TickType_t xTimeToWake;
    
 
    const TickType_t xConstTickCount = xTickCount;

	if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
	{
        portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
	}

    xTimeToWake = xConstTickCount + xTicksToWait;
    listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );


    if( xTimeToWake < xConstTickCount )
    {
        vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
    }
    else
    {
        vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
        if( xTimeToWake < xNextTaskUnblockTime )
        {
            xNextTaskUnblockTime = xTimeToWake;
        }
    }	
}

void prvResetNextTaskUnblockTime( void )
{
    TCB_t *pxTCB;

	if( listLIST_IS_EMPTY( pxDelayedTaskList ) != 0 )
	{
		xNextTaskUnblockTime = portMAX_DELAY;
	} else
	{
		( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
		xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xStateListItem ) );
	}
}

delay_list.h的代码

#ifndef __DELAY_LISTS_H__
#define __DELAY_LISTS_H__


#include "portmacro.h"
#include "list.h"
#include "task.h"


extern List_t * volatile pxDelayedTaskList;
extern List_t * volatile pxOverflowDelayedTaskList;
extern volatile TickType_t xNextTaskUnblockTime;		

#define taskSWITCH_DELAYED_LISTS()\
{\
	List_t *pxTemp;\
	pxTemp = pxDelayedTaskList;\
	pxDelayedTaskList = pxOverflowDelayedTaskList;\
	pxOverflowDelayedTaskList = pxTemp;\
	prvResetNextTaskUnblockTime();\
}


void prvInitialiseDelayLists(void);
void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait );
void prvResetNextTaskUnblockTime( void );

#endif

2、修改 vTaskDelay()函数

void vTaskDelay(const TickType_t xTicksToDelay)
{
	TCB_t *pxTCB = NULL;
	
	pxTCB = pxCurrentTCB;
	
//	pxTCB->xTicksToDelay = xTicksToDelay;
//	taskRESET_READY_PRIORITY( pxTCB->uxPriority );/* 任务就绪对应位置0*/
	prvAddCurrentTaskToDelayedList( xTicksToDelay );
	portYIELD();
}

3、修改 xTaskIncrementTick()函数

void xTaskIncrementTick( void )
{
	TCB_t * pxTCB;
	TickType_t xItemValue;

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


	if( xConstTickCount == ( TickType_t ) 0U )/*溢出*/
	{
		/* ①需要将pxDelayedTaskList和pxOverflowDelayedTaskList对换。
		** ②计算出下一次延迟到达时间。
		*/
		taskSWITCH_DELAYED_LISTS();
	}


	if( xConstTickCount >= xNextTaskUnblockTime )
	{
		for( ;; )
		{
			if( listLIST_IS_EMPTY( pxDelayedTaskList ) != 0 )
			{
				xNextTaskUnblockTime = portMAX_DELAY;
				break;
			}else 
			{
				pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
				xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );

                if( xConstTickCount < xItemValue )
				{
					xNextTaskUnblockTime = xItemValue;
					break;
				}

				( void ) uxListRemove( &( pxTCB->xStateListItem ) );//从延迟列表中移除
				prvAddTaskToReadyList( pxTCB );//添加到就绪列表中
			}
		}
	}/* xConstTickCount >= xNextTaskUnblockTime */
    
    portYIELD();
}

4、修改main.c文件

int main(void)
{
 	/* 就绪列表初始化*/
	prvInitialiseTaskLists();
	/* 初始化延迟列表*/
	prvInitialiseDelayLists();

运行结果如下。(和上上一章运行结果一样,没有任何变化。)
在这里插入图片描述

在延迟处理方面和之前的有本质的改变。
①当任务要延迟时,从就绪列表中移除,然后添加到延迟列表当中,最后切换任务。
②当任务延迟结束时,从延迟列表中移除,然后添加到就绪列表当中,最后切换任务。
是为了下一章实现时间片做铺垫。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值