跟着野火视频学习FreeRTOS——支持多优先级

前言

本节就是关于对任务切换方式这一部分的补充。之前是定义了taskYILED()函数实现两个任务轮流切换,还不支持多优先级。

在本节之前,FreeRTOS还没有支持多优先级,只支持两个任务互相切换,从此,开始加入优先级的功能。在FreeRTOS中,数字优先级越小,逻辑优先级越小。

1、如何支持多优先级

就绪列表是一个数组,存的是就绪任务的TCB,数组下标对应任务优先级,优先级越低对应数组下标越小,空闲任务优先级最小对应为0的链表。

任务创建的时候会根据任务的优先级将任务插入到就绪列表的不同位置。相同优先级的任务插入到就绪列表中的同一条链表中,这是下一节的支持时间片。

pxCurrenTCB是一个全局的TCB指针,用于指向优先级最高的就绪任务的TCB,即当前正在运行的TCB。那么要想让任务支持优先级,只要解决在任务切换的时候,让pxCurrenTCB指向最高优先级的就绪任务的TCB即可。

前面是手动让pxCurrenTCB在任务1、2和空闲任务中轮转,现在改成pxCurrenTCB
在任务切换的时候指向最高优先级的就绪任务的TCB即可。

问题的关键是:如何找到最高优先级的就绪任务的TCB。

2、查找最高优先级的就绪任务

寻找最高优先级的就绪任务相关代码在task.c中实现

/*查找最高优先级的就绪任务:通用方法*/
#if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
    /*uxTopReadyPriority存的是就绪任务的最高优先级*/
    #define taskRECORD_READY_PRIORITY( uxTopReadyPriority, uxPriority ) \
    { \
        /*uxTopReadyPriority存的是就绪任务的最高优先级*/ \
        if( uxPriority > uxTopReadyPriority ) \
        { \
            uxTopReadyPriority = uxPriority; \
        } \
    }/* taskRECORD_READY_PRIORITY*/

    /*-----------------------------------------------*/

    #DEFINE TASKELECT_HIGHEST_PRIORITY_TASK()\
    {
        ubEASEtYPE_T uxTopReadyPriority = uxTopReady ;\
        /*寻找包含就绪任务的最高优先级的队列*/\
        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 */

    }

2.1、通用方法

1、taskRECORD_READY_PRIORITY()

用于更新 uxTopReadyPriority的值。 uxTopReadyPriority 是一个在 task.c 中定义的静态变量, 用于表示创建的任务的最高优先级。

2、taskSELECT_HIGHEST_PRIORITY_TASK()

用于寻找优先级最高的就绪任务, 实质就是更新 uxTopReadyPriority 和 pxCurrentTCB 的值。
 

2.2、优化方法

1. taskRECORD_READY_PRIORITY()
2. taskRESET_READY_PRIORITY()
3. taskSELECT_HIGHEST_PRIORITY_TASK()
 

3.修改代码,支持多优先级

3.1、修改任务控制块

typedef struct tskTaskControlBlock
{
    volatile StackType_t *pxTopOfStack; /* 栈顶 */

    ListItem_t xStateListItem; /* 任务节点 */

    StackType_t *pxStack; /* 任务栈起始地址 */
    /* 任务名称,字符串形式 */
    char pcTaskName[ configMAX_TASK_NAME_LEN ];

    TickType_t xTicksToDelay;
    UBaseType_t uxPriority;
} tskTCB;

3.2、修改xTaskCreateStatic()函数

3.3、修改 vTaskStartScheduler()函数

3.4、修改 vTaskDelay()函数

3.5、修改 vTaskSwitchContext()函数

在新的任务切换函数 vTaskSwitchContext()中,不再是手动的让 pxCurrentTCB 指针在
任 务 1 、 任 务 2 和 空 闲 任 务 中 切 换 , 而 是 直 接 调 用 函 数
taskSELECT_HIGHEST_PRIORITY_TASK()寻找到优先级最高的就绪任务的 TCB,然后更
新到 pxCurrentTCB。

3.6、修改 xTaskIncrementTick()函数

在原来的基础上增加:当任务延时时间到,将任务就绪。
 

你可能感兴趣的:(学习)