FreeRTOS学習ノート-01 Listとその応用

17872 ワード

(FreeRTOS v 9.0.0に対して)
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    1665535     。
     *                    ,     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();
        }
    }
    ...

}