Appearance
支持任务多优先级
找到最高优先级的任务的任务块
c
/*
*************************************************************************
* 宏定义
*************************************************************************
*/
/* 将任务添加到就绪列表 */
#define prvAddTaskToReadyList( pxTCB ) \
taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
/* 查找最高优先级的就绪任务:通用方法 */
#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
/* uxTopReadyPriority 存的是就绪任务的最高优先级 */
#define taskRECORD_READY_PRIORITY( uxPriority ) \
{ \
if( ( uxPriority ) > uxTopReadyPriority ) \
{ \
uxTopReadyPriority = ( uxPriority ); \
} \
} /* taskRECORD_READY_PRIORITY */
/*-----------------------------------------------------------*/
#define taskSELECT_HIGHEST_PRIORITY_TASK() \
{ \
UBaseType_t uxTopPriority = uxTopReadyPriority; \
\
/* 寻找包含就绪任务的最高优先级的队列 */ \
while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \
{ \
--uxTopPriority; \
} \
\
/* 获取优先级最高的就绪任务的TCB,然后更新到pxCurrentTCB */ \
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
/* 更新uxTopReadyPriority */ \
uxTopReadyPriority = uxTopPriority; \
} /* taskSELECT_HIGHEST_PRIORITY_TASK */
/*-----------------------------------------------------------*/
/* 这两个宏定义只有在选择优化方法时才用,这里定义为空 */
#define taskRESET_READY_PRIORITY( uxPriority )
#define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
/* 查找最高优先级的就绪任务:根据处理器架构优化后的方法 */
#else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
/*-----------------------------------------------------------*/
#define taskSELECT_HIGHEST_PRIORITY_TASK() \
{ \
UBaseType_t uxTopPriority; \
\
/* 寻找最高优先级 */ \
portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
/* 获取优先级最高的就绪任务的TCB,然后更新到pxCurrentTCB */ \
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
} /* taskSELECT_HIGHEST_PRIORITY_TASK() */
/*-----------------------------------------------------------*/
#if 0
#define taskRESET_READY_PRIORITY( uxPriority ) \
{ \
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \
{ \
portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \
} \
}
#else
#define taskRESET_READY_PRIORITY( uxPriority ) \
{ \
portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \
}
#endif
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
添加一个新的任务到优先级队列之中
没有优化
taskRECORD_READY_PRIORITY( uxPriority )在当前优先级保存现在的优先级
taskSELECT_HIGHEST_PRIORITY_TASK()寻找最高优先级
优化方法: 有一个指令CLZ, 会返回一个数字最高的出现1前面的0的个数
taskRECORD_READY_PRIORITY( uxPriority )把当前优先级某一个位设置为1
taskSELECT_HIGHEST_PRIORITY_TASK()寻找最高优先级
taskRESET_READY_PRIORITY( uxPriority )清零某一个位
c
//设置在添加任务的时候是否使用优化
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* 检测优先级配置 */
#if( configMAX_PRIORITIES > 32 )
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
#endif
/* 根据优先级设置/清除优先级位图中相应的位 */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) __clz( ( uxReadyPriorities ) ) )
#endif /* taskRECORD_READY_PRIORITY */
使用优化方法时候的宏定义, 实际上就是31减去clz指令获得的数字, 得到第几位是1
- 修改任务控制块, 添加优先级变量
c
{
//栈顶
volatile StackType_t *pxTopOfStack;
//任务节点
ListItem_t xStateListItem;
StackType_t *pxStack; //任务栈的起始位置
char pcTaskName[configMAX_TASK_NAME_LEN];
TickType_t xTicksToDelay; /* 用于延时 */
//优先级
UBaseType_t uxPriority;
}tskTCB;
- 创建任务的时候传进去优先级
c
prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters,uxPriority, &xReturn, pxNewTCB);
c
/* 初始化优先级 */
if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
{
uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
}
pxNewTCB->uxPriority = uxPriority;
大于最大优先级, 就设置为最大优先级
- 实现自动添加到列表
c
/* 将任务添加到就绪列表 */
prvAddNewTaskToReadyList( pxNewTCB );
c
static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
{
/* 进入临界段 */
taskENTER_CRITICAL();
{
/* 全局任务计时器加一操作 */
uxCurrentNumberOfTasks++;
/* 如果pxCurrentTCB为空,则将pxCurrentTCB指向新创建的任务 */
if( pxCurrentTCB == NULL )
{
pxCurrentTCB = pxNewTCB;
/* 如果是第一次创建任务,则需要初始化任务相关的列表 */
if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
{
/* 初始化任务相关的列表 */
prvInitialiseTaskLists();
}
}
else /* 如果pxCurrentTCB不为空,则根据任务的优先级将pxCurrentTCB指向最高优先级任务的TCB */
{
if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )
{
pxCurrentTCB = pxNewTCB;
}
}
uxTaskNumber++;
/* 将任务添加到就绪列表 */
prvAddTaskToReadyList( pxNewTCB );
}
/* 退出临界段 */
taskEXIT_CRITICAL();
}
这一次创建任务的时候会自动修改当前的任务, 以及添加链表
还需要修改开启任务调度的函数
- 修改Delay函数
c
/* 将任务从就绪列表移除 */
//uxListRemove( &( pxTCB->xStateListItem ) );
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
暂时不能移除, 但是需要标志位清零, 因为现在通过扫描列表来实现延迟
- 修改修改任务的函数
c
void vTaskSwitchContext( void )
{
/* 获取优先级最高的就绪任务的TCB,然后更新到pxCurrentTCB */
taskSELECT_HIGHEST_PRIORITY_TASK();
}
- 计时器调用函数
c
/* 延时时间到,将任务就绪 */
if( pxTCB->xTicksToDelay ==0 )
{
taskRECORD_READY_PRIORITY( pxTCB->uxPriority );
}
总结
在创建函数的时候会把自身优先级设置为1
在调用delay函数之后会清除自身优先级, 然后进行函数切换
在时钟每次中断的时候会进行任务切换, 选择优先级最高的函数
切换函数的时候会调用xPortPendSVHandler函数, 在这个函数中会更新TCB然后更换函数
这里实现的每个优先级只能有一个函数
实际的FreeRTOS
c
#define taskSELECT_HIGHEST_PRIORITY_TASK() \
{ \
UBaseType_t uxTopPriority; \
\
/* Find the highest priority list that contains ready tasks. */ \
portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 );\
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );\
} /* taskSELECT_HIGHEST_PRIORITY_TASK() */
c
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \
{ \
List_t * const pxConstList = ( pxList ); \
/* Increment the index to the next item and return the item, ensuring */ \
/* we don't return the marker used at the end of the list. */ \
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \
{ \
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
} \
( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \
}
这一个宏定义会把首位的链表改为下一个链表