FreeRTOS学习笔记【11】-----任务列表

根据b站up freeRTOS源码

数据结构

1 TCB(task control block)

typedef struct tskTaskControlBlock       /* The old naming convention is used to prevent breaking kernel aware debuggers. */
{
    volatile StackType_t * pxTopOfStack; /**< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
    //指向任务栈顶部的指针
    ListItem_t xStateListItem;                  /**< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
    //用于将任务链接到不同状态列表(就绪、阻塞、挂起)的列表项。
    ListItem_t xEventListItem;                  /**< Used to reference a task from an event list. */
    //用于将任务链接到事件列表的列表项。
    UBaseType_t uxPriority;                     /**< The priority of the task.  0 is the lowest priority. */
    //任务的优先级,数值越小优先级越低。
    StackType_t * pxStack;                      /**< Points to the start of the stack. */
    //指向任务栈起始地址的指针
    char pcTaskName[ configMAX_TASK_NAME_LEN ];
} tskTCB;

2 任务列表项

struct xLIST_ITEM
{
    listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE           /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
    
    configLIST_VOLATILE TickType_t xItemValue;          /**< The value being listed.  In most cases this is used to sort the list in ascending order. */
    
    struct xLIST_ITEM * configLIST_VOLATILE pxNext;     /**< Pointer to the next ListItem_t in the list. */
    
    struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /**< Pointer to the previous ListItem_t in the list. */
    
    void * pvOwner;                                     /**< Pointer to the object (normally a TCB) that contains the list item.  There is therefore a two way link between the object containing the list item and the list item itself. */
    //指向“拥有”该 list item 的对象。通常是一个任务控制块(TCB)。
    struct xLIST * configLIST_VOLATILE pxContainer;     /**< Pointer to the list in which this list item is placed (if any). */
    //指列表项所处的列表(就绪列表、delay列表、挂起列表)
    listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE          /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
    
};
typedef struct xLIST_ITEM ListItem_t;

3 列表头

typedef struct xLIST
{
    listFIRST_LIST_INTEGRITY_CHECK_VALUE      /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
    
    configLIST_VOLATILE UBaseType_t uxNumberOfItems; /**< Number of items in the list. */
    
    ListItem_t * configLIST_VOLATILE pxIndex; /**< Used to walk through the list.  Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */
    //指向列表的指针
    MiniListItem_t xListEnd;                  /**< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */
    //尾节点
    listSECOND_LIST_INTEGRITY_CHECK_VALUE     /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
    
} List_t;

列表代码

1 列表初始化

freeRTOS的列表变量:

PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; 
/**< 用于存储就绪态(Ready)的任务列表. */
PRIVILEGED_DATA static List_t xDelayedTaskList1;                         
/**< 用于存储延迟(Delayed)的任务 */
PRIVILEGED_DATA static List_t xDelayedTaskList2;                         
/**< xDelayedTaskList2 用于存储那些延迟时间超过了当前 tick 计数范围的任务. */
PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList;              
/**< 当前正在使用的延迟任务列表.延迟时间超过了当前 tick 计数器的范围时,这些任务会被放入  */
PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList;      
/**< 指向当前用于存储溢出延迟任务的列表. */
PRIVILEGED_DATA static List_t xPendingReadyList;                         
/**< 用于存储那些由于某些事件(如信号量释放、队列操作等)而变为就绪态的任务 */

2 列表初始化

pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );

pxList->xListEnd.xItemValue = portMAX_DELAY;
//0xffffffffU 
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );

pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );

pxList->uxNumberOfItems = ( UBaseType_t ) 0U;

3 Insert 函数

void vListInsert( List_t * const pxList,
                  ListItem_t * const pxNewListItem )

pxList 要插入的列表,
pxNewListItem 要插入的列表项

	ListItem_t * pxIterator;
	//将新列表项插入在pxIterator指向位置的后面
    pxNewListItem->pxNext = pxIterator->pxNext;
    pxNewListItem->pxNext->pxPrevious = pxNewListItem;
    pxNewListItem->pxPrevious = pxIterator;
    pxIterator->pxNext = pxNewListItem;

那么,pxIterator的是如何定位的呢?

	//如果value最大,就放在尾结点的前面
    if( xValueOfInsertion == portMAX_DELAY )
    {
        pxIterator = pxList->xListEnd.pxPrevious;
    }
    else
    {
    	//初始化,迭代器指向尾部
    	//停止条件,迭代器的下一个节点的值小于等于当前值
    	//否则 迭代器指向下一个节点
        for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); 
            pxIterator->pxNext->xItemValue <= xValueOfInsertion; 
            pxIterator = pxIterator->pxNext )
        {
            /* There is nothing to do here, just iterating to the wanted
             * insertion position. */
        }

4 InsertEnd函数

这里的End是对于遍历而言的End,
listGET_OWNER_OF_NEXT_ENTRY中,需要对list进行遍历

    do {                                                                                       \
        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 )->xListEnd.pxNext;                       \
        }                                                                                      \
        ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner;                                         \
    } while( 0 )

InsertEnd 函数存在的含义是:

并不是把当前要插入的项插到列表尾
而是要把列表放在遍历时最后一个遍历的位置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值