freeRTOS链表


前言

freeRTOS链表结构体和链表操作。源文件和头文件分别为list.c和list.h,list.c中主要为链表的创建,增删等操作,list.h为链表等相关的结构体,宏函数。

1、 list.h

1.1、未实现的宏

    /* Define the macros to do nothing. */
    #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE
    #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
    #define listFIRST_LIST_INTEGRITY_CHECK_VALUE
    #define listSECOND_LIST_INTEGRITY_CHECK_VALUE
    #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
    #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
    #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList )
    #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )
    #define listTEST_LIST_ITEM_INTEGRITY( pxItem )
    #define listTEST_LIST_INTEGRITY( pxList )

这些宏并没有实现,可以提供给用户进行自定义实现功能。

1.2、 列表项

struct xLIST_ITEM
{
    listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE           //由1.1可以看到此成员没有实现
    configLIST_VOLATILE TickType_t xItemValue;          //被列出的值。在大多数情况下,用于按升序对列表进行排序。
    struct xLIST_ITEM * configLIST_VOLATILE pxNext;     //指向列表的下一个列表项的指针
    struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; //指向列表的上一个列表项的指针
    void * pvOwner;                                     //指向了包含该链表项的对象(通常是TCB),因此,FreeRTOS的链表与所有者互联,即所有者与链表项相互关联。
    struct xLIST * configLIST_VOLATILE pxContainer;     //指向放置此列表项的列表的指针(如果有的话)。
    listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE          //由1.1可以看到此成员没有实现
};
typedef struct xLIST_ITEM ListItem_t;                   /* For some reason lint wants this as two separate definitions. */

1.3、mini列表项

    struct xMINI_LIST_ITEM
    {
        listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE 
        configLIST_VOLATILE TickType_t xItemValue;
        struct xLIST_ITEM * configLIST_VOLATILE pxNext;
        struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
    };
    typedef struct xMINI_LIST_ITEM MiniListItem_t;

mini列表项大体上跟列表项差不多,但是结构体成员少了pvOwner,pxContainer。

1.4、列表

/*
 * Definition of the type of queue used by the scheduler.
 */
typedef struct xLIST
{
    listFIRST_LIST_INTEGRITY_CHECK_VALUE			//由1.1可以看到此成员没有实现
    volatile UBaseType_t uxNumberOfItems;			//列表项的数量
    ListItem_t * configLIST_VOLATILE pxIndex; 		//用来遍历列表,指向调用listGET_OWNER_OF_NEXT_ENTRY()返回的最后一项。
    MiniListItem_t xListEnd;               		    //包含最大可能项值的列表项,这意味着它总是在列表的末尾,因此用作标记。
    listSECOND_LIST_INTEGRITY_CHECK_VALUE    		//由1.1可以看到此成员没有实现
} List_t;

mini列表项在列表的结构体中出现了,它的作用看注释或许不太明白?没关系接着往下看。

1.5、 已经实现的宏函数

1.5.1、 set列表项拥有者

#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner )    ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )

1.5.2、 get列表项拥有者

#define listGET_LIST_ITEM_OWNER( pxListItem )             ( ( pxListItem )->pvOwner )

1.5.3、 set列表项value

#define listSET_LIST_ITEM_VALUE( pxListItem, xValue )     ( ( pxListItem )->xItemValue = ( xValue ) )

1.5.4、 检索(retrieve)列表项value

访问宏以检索列表项的值。这个值可以表示任何东西——例如任务的优先级,或者任务应该被解除阻塞的时间。

#define listGET_LIST_ITEM_VALUE( pxListItem )             ( ( pxListItem )->xItemValue )

1.5.5、 检索(retrieve)列表头部列表项value

#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList )        ( ( ( pxList )->xListEnd ).pxNext->xItemValue )

1.5.5、 get列表头部列表项

#define listGET_HEAD_ENTRY( pxList )                      ( ( ( pxList )->xListEnd ).pxNext )

1.5.6、 get当前列表项的下一个列表项

#define listGET_NEXT( pxListItem )                        ( ( pxListItem )->pxNext )

1.5.7、 get列表尾部列表项地址

#define listGET_END_MARKER( pxList )                      ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )

1.5.8、 判断列表是否为空

#define listLIST_IS_EMPTY( pxList )                       ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE )

1.5.9、 列表长度数值

#define listCURRENT_LIST_LENGTH( pxList )                 ( ( pxList )->uxNumberOfItems )

1.5.10、 获取列表下一项所有者

#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 ) ) \
        //mini列表项没有列表项所有者的成员
        {                                                                                      \
            ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;                       \
        }                                                                                      \
        ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner;                                         \
    }

1.5.11、 从列表中删除一个项目

#define listREMOVE_ITEM( pxItemToRemove ) \
    {                                     \
        /* The list item knows which list it is in.  Obtain the list from the list \
         * item. */                                                              \
        List_t * const pxList = ( pxItemToRemove )->pxContainer;                 \
                                                                                 \
        ( 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 )->pxContainer = NULL;                                  \
        ( pxList->uxNumberOfItems )--;                                           \
    }

1.5.12、 移除列表项

不返回值的uxListRemove()的版本。作为轻微的通过内联优化xTaskIncrementTick()。从列表中删除一个项目。列表项有一个指向它所在列表的指针,因此只需要将列表项传递到函数中。@param uxlistmove要删除的项。项目将从它的pxcontainer参数所指向的列表中删除自己。在列表项结束后,列表中剩余的项数被移除。

#define listREMOVE_ITEM( pxItemToRemove ) \
    {                                     \
        /* The list item knows which list it is in.  Obtain the list from the list \
         * item. */                                                              \
        List_t * const pxList = ( pxItemToRemove )->pxContainer;                 \
                                                                                 \
        ( 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 )->pxContainer = NULL;                                  \
        ( pxList->uxNumberOfItems )--;                                           \
    }

1.5.13、 列表尾插

#define listINSERT_END( pxList, pxNewListItem )           \
    {                                                     \
        ListItem_t * const pxIndex = ( pxList )->pxIndex; \
                                                          \
        /* Only effective when configASSERT() is also defined, these tests may catch \
         * the list data structures being overwritten in memory.  They will not catch \
         * data errors caused by incorrect configuration or use of FreeRTOS. */ \
        listTEST_LIST_INTEGRITY( ( pxList ) );                                  \
        listTEST_LIST_ITEM_INTEGRITY( ( pxNewListItem ) );                      \
                                                                                \
        /* Insert a new list item into ( pxList ), but rather than sort the list, \
         * makes the new list item the last item to be removed by a call to \
         * listGET_OWNER_OF_NEXT_ENTRY(). */                 \
        ( pxNewListItem )->pxNext = pxIndex;                 \
        ( pxNewListItem )->pxPrevious = pxIndex->pxPrevious; \
                                                             \
        pxIndex->pxPrevious->pxNext = ( pxNewListItem );     \
        pxIndex->pxPrevious = ( pxNewListItem );             \
                                                             \
        /* Remember which list the item is in. */            \
        ( pxNewListItem )->pxContainer = ( pxList );         \
                                                             \
        ( ( pxList )->uxNumberOfItems )++;                   \
    }

1.5.14、 获取列表第一条条目所有者

#define listGET_OWNER_OF_HEAD_ENTRY( pxList )            ( ( &( ( pxList )->xListEnd ) )->pxNext->pvOwner )

1.5.15、 检查列表项是否在列表中

#define listIS_CONTAINED_WITHIN( pxList, pxListItem )    ( ( ( pxListItem )->pxContainer == ( pxList ) ) ? ( pdTRUE ) : ( pdFALSE ) )

1.5.16、 获取列表项的pxContainer

#define listLIST_ITEM_CONTAINER( pxListItem )            ( ( pxListItem )->pxContainer )

1.5.17、 查看列表是否被初始化

#define listLIST_IS_INITIALISED( pxList )                ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY )

2、 list.c

2.1、vListInitialise

void vListInitialise( List_t * const pxList )
{
    
    pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); //用来遍历列表的指针指向mini列表,即为列表项尾部
    listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) );

    pxList->xListEnd.xItemValue = portMAX_DELAY;//mini列表项列表结束值为最大值

    
    pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );    //列表项末尾项的下一项指向自己
    pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );//上一项指向自己
    
    #if ( configUSE_MINI_LIST_ITEM == 0 )
    {
        pxList->xListEnd.pvOwner = NULL;
        pxList->xListEnd.pxContainer = NULL;
        listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) );
    }
    #endif

    pxList->uxNumberOfItems = ( UBaseType_t ) 0U;//最小值
    
    listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
    listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}

在这里插入图片描述

2.2、vListInitialiseItem

void vListInitialiseItem( ListItem_t * const pxItem )
{
    pxItem->pxContainer = NULL;//确保列表项没有被记录在列表中。

    listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
    listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
}

在这里插入图片描述

2.3、vListInsertEnd

void vListInsertEnd( List_t * const pxList,
                     ListItem_t * const pxNewListItem )
{
    ListItem_t * const pxIndex = pxList->pxIndex;//此时pxIndex指向的是mini列表项,即尾项

    listTEST_LIST_INTEGRITY( pxList );//未实现
    listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );//未实现

    /* Insert a new list item into pxList, but rather than sort the list,
     * makes the new list item the last item to be removed by a call to
     * listGET_OWNER_OF_NEXT_ENTRY(). */
    pxNewListItem->pxNext = pxIndex;//让新插入的列表项的下一个指针域指向mini列表项,即指向尾项
    pxNewListItem->pxPrevious = pxIndex->pxPrevious;//让新插入的列表项上一个指针域指向mini列表项的上一个指针域
    												//这两步实现新插入列表项的“左右手手拉手”

    /* Only used during decision coverage testing. */
    mtCOVERAGE_TEST_DELAY();

    pxIndex->pxPrevious->pxNext = pxNewListItem;//让插入前的mini列表项下一项指针域指向新插入的列表项
    pxIndex->pxPrevious = pxNewListItem;//让mini列表项上一个指针域指向新插入列表项

    /* Remember which list the item is in. */
    pxNewListItem->pxContainer = pxList;//将列表保存在列表项的pxContainer内

    ( pxList->uxNumberOfItems )++;
}

在这里插入图片描述

2.4、vListInsert

void vListInsert( List_t * const pxList,
                  ListItem_t * const pxNewListItem )
{
    ListItem_t * pxIterator;
    const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;

    listTEST_LIST_INTEGRITY( pxList );
    listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
    
    if( xValueOfInsertion == portMAX_DELAY )
    {
        pxIterator = pxList->xListEnd.pxPrevious;
    }
    else
    {
        /* *** NOTE ***********************************************************
        *  If you find your application is crashing here then likely causes are
        *  listed below.  In addition see https://www.FreeRTOS.org/FAQHelp.html for
        *  more tips, and ensure configASSERT() is defined!
        *  https://www.FreeRTOS.org/a00110.html#configASSERT
        *
        *   1) Stack overflow -
        *      see https://www.FreeRTOS.org/Stacks-and-stack-overflow-checking.html
        *   2) Incorrect interrupt priority assignment, especially on Cortex-M
        *      parts where numerically high priority values denote low actual
        *      interrupt priorities, which can seem counter intuitive.  See
        *      https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html and the definition
        *      of configMAX_SYSCALL_INTERRUPT_PRIORITY on
        *      https://www.FreeRTOS.org/a00110.html
        *   3) Calling an API function from within a critical section or when
        *      the scheduler is suspended, or calling an API function that does
        *      not end in "FromISR" from an interrupt.
        *   4) Using a queue or semaphore before it has been initialised or
        *      before the scheduler has been started (are interrupts firing
        *      before vTaskStartScheduler() has been called?).
        *   5) If the FreeRTOS port supports interrupt nesting then ensure that
        *      the priority of the tick interrupt is at or below
        *      configMAX_SYSCALL_INTERRUPT_PRIORITY.
        **********************************************************************/

        for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM.  This is checked and valid. *//*lint !e440 The iterator moves to a different value, not xValueOfInsertion. */
        {
            /* 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;

    /* Remember which list the item is in.  This allows fast removal of the
     * item later. */
    pxNewListItem->pxContainer = pxList;

    ( pxList->uxNumberOfItems )++;
}

2.5、uxListRemove

UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
/* The list item knows which list it is in.  Obtain the list from the list
 * item. */
    List_t * const pxList = pxItemToRemove->pxContainer;

    pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
    pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;

    /* Only used during decision coverage testing. */
    mtCOVERAGE_TEST_DELAY();

    /* Make sure the index is left pointing to a valid item. */
    if( pxList->pxIndex == pxItemToRemove )
    {
        pxList->pxIndex = pxItemToRemove->pxPrevious;
    }
    else
    {
        mtCOVERAGE_TEST_MARKER();
    }

    pxItemToRemove->pxContainer = NULL;
    ( pxList->uxNumberOfItems )--;

    return pxList->uxNumberOfItems;
}
  • 24
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值