根据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 函数存在的含义是:
并不是把当前要插入的项插到列表尾 而是要把列表放在遍历时最后一个遍历的位置
评论前必须登录!
注册