FreeRTOS学習ノート-01 Listとその応用
17872 ワード
(FreeRTOS v 9.0.0に対して)
List_t
リストリストリストリストtはFreeRTOSのデータ構造の組織で重要な役割を果たしています.ソースを読むには、まずこの構造を読まなければなりません.
task.cでは、TCBタスク制御ブロックを管理するために、以下の大域変数を定義している.
List_t
リストリストリストリストtはFreeRTOSのデータ構造の組織で重要な役割を果たしています.ソースを読むには、まずこの構造を読まなければなりません.
struct xLIST_ITEM /* */
{
TickType_t xItemValue; /* , , List */
struct xLIST_ITEM * pxNext;/* */
struct xLIST_ITEM * pxPrevious;/* */
void * pvOwner;/* , tcb , List tcb, List tcb */
void * pvContainer;/* List, List */
};
typedef struct xLIST_ITEM ListItem_t;
struct xMINI_LIST_ITEM
{
TickType_t xItemValue;
struct xLIST_ITEM * pxNext;
struct xLIST_ITEM * pxPrevious;
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;
/* uxNumberOfItems ; pxIndex , ; xListEnd , */
typedef struct xLIST
{
UBaseType_t uxNumberOfItems;
ListItem_t * pxIndex;
MiniListItem_t xListEnd;
} List_t;
#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )
#define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner )
#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) )
#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue )
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue )
#define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext )
#define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext )
#define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )
#define listLIST_IS_EMPTY( pxList ) ( ( BaseType_t ) ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) )
#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems )
/* ( owner, )
* pxIndex , , pxIndex */
#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; \
}
/* , , */
#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner )
#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( BaseType_t ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) )
#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pvContainer )
/* , */
#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY )
/* */
void vListInitialise( List_t * const pxList );
/* */
void vListInitialiseItem( ListItem_t * const pxItem );
/* , */
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem );
/* pxIndex , listGET_OWNER_OF_NEXT_ENTRY , */
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem );
/* */
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove );
/*-----------------------------------------------------------*/
void vListInitialise( List_t * const pxList )
{
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );
/* portMAX_DELAY ( ) , xListEnd , ,
, listLIST_IS_INITIALISED() */
pxList->xListEnd.xItemValue = portMAX_DELAY;
/* , */
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );
pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );
pxList->uxNumberOfItems = ( UBaseType_t ) 0U;/* , , 0 */
}
void vListInitialiseItem( ListItem_t * const pxItem )
{
pxItem->pvContainer = NULL;
}
/* pxIndex ,
* listGET_OWNER_OF_NEXT_ENTRY() */
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{
ListItem_t * const pxIndex = pxList->pxIndex;
pxNewListItem->pxNext = pxIndex;
pxNewListItem->pxPrevious = pxIndex->pxPrevious;
pxIndex->pxPrevious->pxNext = pxNewListItem;
pxIndex->pxPrevious = pxNewListItem;
/* Remember which list the item is in. */
pxNewListItem->pvContainer = ( void * ) pxList;
( pxList->uxNumberOfItems )++;
}
/* */
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
{
ListItem_t *pxIterator;
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
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. */
}
}
pxNewListItem->pxNext = pxIterator->pxNext;
pxNewListItem->pxNext->pxPrevious = pxNewListItem;
pxNewListItem->pxPrevious = pxIterator;
pxIterator->pxNext = pxNewListItem;
pxNewListItem->pvContainer = ( void * ) pxList;
( pxList->uxNumberOfItems )++;
}
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer;
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
/* Make sure the index is left pointing to a valid item. */
if( pxList->pxIndex == pxItemToRemove )
{
pxList->pxIndex = pxItemToRemove->pxPrevious;
}
pxItemToRemove->pvContainer = NULL;
( pxList->uxNumberOfItems )--;
return pxList->uxNumberOfItems;
}
List_t関連アプリケーションtask.cでは、TCBタスク制御ブロックを管理するために、以下の大域変数を定義している.
#define configMAX_PRIORITIES 5 /* , , 32, */
static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/* FreeRTOS ( RTOS , ucosii, osek/autosar RTOS, os ), 。 , 。 */
static List_t xDelayedTaskList1;
static List_t xDelayedTaskList2;
static List_t * volatile pxDelayedTaskList;
static List_t * volatile pxOverflowDelayedTaskList;
static List_t xPendingReadyList;
vTaskDelay関数を呼び出して、現在のタスクを待ち時間にしてもいいです.この関数は、prvAddCurentTasky ToDelayedListを呼び出して、現在のジョブをレディキューから待ち行列に移動します.よく見ると、上で定義されているグローバル変数の中に、2つの遅延チェーンがあります.初期化時、pxDelayedTaskyListはxDelayedTaskyList 1、pxOverflow Delayed TaskyListを指します.なぜ2つのListが遅延タスクを組織する必要がありますか?この問題を持って下のコードを見てください.prvAddCurrentTaskToDelayedList( xTicksToDelay...)
{
...
uxListRemove( &( pxCurrentTCB->xStateListItem ) ); /* tcb */
...
/* xConstTickCount tick , xTimeToWake tick 。
* , tick , , , 。
* : tick 16 , 65535 。
* , pxDelayedTaskList pxOverflowDelayedTaskList 。
* pxDelayedTaskList tcb, tick 。
* pxOverflowDelayedTaskList tcb, tick 。
* tick , , , 。
* pxDelayedTaskList 。 */
xTimeToWake = xConstTickCount + xTicksToWait;
/* tcb ListItem_t xStateListItem , 。 ,xItemValue tick , tick , */
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
if( xTimeToWake < xConstTickCount )
{
/* Wake time has overflowed. Place this item in the overflow list. */
vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
}
else
{
/* The wake time has not overflowed, so the current block list is used. */
vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
/* If the task entering the blocked state was placed at the head of the list of blocked tasks then xNextTaskUnblockTime needs to be updated too. */
if( xTimeToWake < xNextTaskUnblockTime )
{
xNextTaskUnblockTime = xTimeToWake;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
...
}