<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
2009-5-11
也看了一些代码,至此才发现如果不对这个
tskTCB
结构有一定的认识,接下来根本就
无法再走下去了。故在此深刻研究下这个结构,该结构的定义如下:【在
task.c
文件中】其他很多地方都直接
typedef void tskTCB
了
typedef struct tskTaskControlBlock
{
/*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */
volatile portSTACK_TYPE *pxTopOfStack;
/*< List item used to place the TCB in ready and blocked queues. */
xListItem xGenericListItem;
/*< List item used to place the TCB in event lists. */
xListItem xEventListItem;
/*< The priority of the task where 0 is the lowest priority. */
unsigned portBASE_TYPE uxPriority;
/*< Points to the start of the stack. */
portSTACK_TYPE *pxStack;
/*< Descriptive name given to the task when created. Facilitates debugging only. */
signed portCHAR pcTaskName[ configMAX_TASK_NAME_LEN ];
#if ( portSTACK_GROWTH > 0 )
/*< Used for stack overflow checking on architectures where the stack grows up from low memory. */
portSTACK_TYPE *pxEndOfStack;
#endif
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
unsigned portBASE_TYPE uxCriticalNesting;
#endif
#if ( configUSE_TRACE_FACILITY == 1 )
/*< This is used for tracing the scheduler and making debugging easier only. */
unsigned portBASE_TYPE uxTCBNumber;
#endif
#if ( configUSE_MUTEXES == 1 )
unsigned portBASE_TYPE uxBasePriority;
#endif
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
pdTASK_HOOK_CODE pxTaskTag;
#endif
} tskTCB;
一个
task
在创建完
TCP
和初始化栈之后,一般情况下就会被放入
readytask
链表中。上面的结构对我来说,比较难理解的应该是两个
xListItem
元素的变量了,不管如何,先看下这个结构的实现吧:
* Definition of the only type of object that a list can contain.
struct xLIST_ITEM
{
/*< The value being listed. In most cases this is used to sort the list in descending order. */
portTickType xItemValue;
/*< Pointer to the next xListItem in the list. */
volatile struct xLIST_ITEM * pxNext;
/*< Pointer to the previous xListItem in the list. */
volatile struct xLIST_ITEM * pxPrevious;
/*< 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. */
void * pvOwner;
/*< Pointer to the list in which this list item is placed (if any). */
void * pvContainer;
};
/* For some reason lint wants this as two separate definitions. */
typedef struct xLIST_ITEM xListItem;
嗯,到这里还算明白了一些,上面的两个
xListItem
变量是用来在某个什么时候作为一个
item
填充队列或链表。好了,问题来了,那具体是在什么时候,什么地方被加入的呢?
还记得
prvInitialiseTaskLists
,前面提到过,但是没有深入讲解。这里就分析一下。
(1)
针对所有优先级,每个优先级创建一个链表,这个链表中存放的是该优先级已
ready
的
task
。
(2)
一个
xDelayedTaskList1
链表
(3)
一个
xDelayedTaskList2
链表,主要是为了防止前面一个链表中
item
不够用的情况
(4)
一个
xPendingReadyList
链表
(5)
两个可选的链表:
xTasksWaitingTermination
和
xSuspendedTaskList
从名字上可以看出这些链表的作用所在。那接下来就有必要说下
xList
这个结构体,其定义如下:
* Definition of the type of queue used by the scheduler.
typedef struct xLIST
{
volatile unsigned portBASE_TYPE uxNumberOfItems;
/*< Used to walk through the list. Points to the last item returned by a call to pvListGetOwnerOfNextEntry (). */
volatile xListItem * pxIndex;
/*< 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. */
volatile xMiniListItem xListEnd;
} xList;
这里说明一下,通过对各个使用
xList
的函数分析,该结构中的
xListEnd
是个环形链表。
struct xMINI_LIST_ITEM
{
portTickType xItemValue;
volatile struct xLIST_ITEM *pxNext;
volatile struct xLIST_ITEM *pxPrevious;
};
这样就可以理解
xList
结构中的
pxIndex
的使用了,具体可参考
vListInsertEnd
的实现。同时
vListInitialise
函数的实现就可想而知了,以及
vListInsert
和
vListRemove
都一块解决掉了。
嗯,是的,至此
freertos
中的三个重要的文件:
queue.c
、
list.c
、
task.c
,我们已经解决了一个了。
转载于:https://blog.51cto.com/bluefish/158397