FreeRTOS学习记录 03--列表篇

0 前言

@ Author         :Dargon
@ Record Date    :2021/07/12
@ Reference Book : `FreeRTOS源码详解与应用开发`,`ARM Cortex-M3与Cortex-M4权威指南`,`B站正点原子FreeRTOS讲解视频`
@ Purpose        :学习正点原子的miniFly,该飞控基于FreeRTOS系统开发的,所以学习一下记录下关于RTOS系统的一些基本操作,大概了解系统的工作原理,如何创建,运行,切换任务等等基本操作流程。在此进行学习的记录。

1 列表基础知识

1.1 列表List_t

  • List_t 结构体定义
    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;
        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. uxNumberOfItems表示列表中列表项的个数
    2. pxIndex 用来遍历列表,一个列表项ListItem_t类型的指针
    3. xListEnd 用作一个标记,位于列表的末尾

1.2 列表项ListItem_t

  • ListItem_t 结构体定义
    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 descending 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. */
        void * configLIST_VOLATILE pvContainer;				/*< Pointer to the list in which this list item is placed (if any). */
        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;					/* For some reason lint wants this as two separate definitions. */
    
    1. xItemValue表示该列表项的值
    2. pxNext 指向前一个列表项
    3. pxPrevious 指向后一个列表项
    4. pvOwner 指向所属于哪个任务块,对应于TBC_t 中的 xStateListItem->pvOwner
    5. pvContainer 指向当前所属于的列表

1.3 Mini列表项MiniListItem_t

  • MiniListItem_t 结构体定义
    由于只用作列表的最后一项,只是做个标记而已,减少内存的浪费,简化的省略一些成员变量。
    struct xMINI_LIST_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;
        struct xLIST_ITEM * configLIST_VOLATILE pxNext;
        struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
    };
    typedef struct xMINI_LIST_ITEM MiniListItem_t;
    
    1. xItemValue表示该列表项的值
    2. pxNext 指向前一个列表项
    3. pxPrevious 指向后一个列表项

2 API函数的实现

2.1 列表初始化 vListInitialise()

  • vListInitialise() 初始化源码分析
    void vListInitialise( List_t * const pxList )
    {
          
          
        /* The list structure contains a list item which is used to mark the
        end of the list.  To initialise the list the list end is inserted
        as the only list entry. */
        pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );			/*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */
    
        /* The list end value is the highest possible value in the list to
        ensure it remains at the end of the list. */
        pxList->xListEnd.xItemValue = portMAX_DELAY;
    
        /* The list end next and previous pointers point to itself so we know
        when the list is empty. */
        pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );	/*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */
        pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );/*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */
    
        pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
    
        /* Write known values into the list if
        configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
        listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
        listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
    }
    
    1. 将index 指向xListEnd
    2. 初始化 pxList->xListEnd.xItemValue = portMAX_DELAY;为最大值,确保在列表的末端
    3. 初始化 pxList->xListEnd.pxNextpxList->xListEnd.pxPrevious
    4. 初始化 pxList->uxNumberOfItems = ( UBaseType_t ) 0U; 列表项个数为0

2.2 列表项初始化 vListInitialiseItem()

  • vListInitialiseItem()
    void vListInitialiseItem( ListItem_t * const pxItem )
    {
          
          
        /* Make sure the list item is not recorded as being on a list. */
        pxItem->pvContainer = NULL;
    
        /* Write known values into the list item if
        configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
        listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
        listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
    }
    
    1. pxItem->pvContainer = NULL; 仅仅初始化次列表项的列表属性为 null

2.3 列表插入 vListInsert()

  • vListInsert()
    1. 获取要插入的列表项的值
    2. 遍历列表,找到位置
    3. 更新next 和 previous
    4. 更新该插入列表值的pxNewListItem->pvContainer
    5. 列表 ( pxList->uxNumberOfItems )++;需要更新

2.4 列表末尾插入 vListInsertEnd()

  • vListInsertEnd()
    	pxNewListItem->pxNext = pxIndex;
        pxNewListItem->pxPrevious = pxIndex->pxPrevious;
    
        /* Only used during decision coverage testing. */
        mtCOVERAGE_TEST_DELAY();
    
        pxIndex->pxPrevious->pxNext = pxNewListItem;
        pxIndex->pxPrevious = pxNewListItem;
    
        /* Remember which list the item is in. */
        pxNewListItem->pvContainer = ( void * ) pxList;
    
        ( pxList->uxNumberOfItems )++;
    
    1. 直接更新列表项的next 和previous即可

2.5 列表删除 uxListRemove()

  • 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 = ( List_t * ) pxItemToRemove->pvContainer;
    
        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->pvContainer = NULL;
        ( pxList->uxNumberOfItems )--;
    
        return pxList->uxNumberOfItems;
    }
    
    1. 根据pxItemToRemove->pvContainer,获得所在的列表
    2. 进行更新next 和 previous
    3. 若是当前的index 指向的是被删除的,则进行更新到指向被删除的前一个列表项
    4. 更新列表项的个数( pxList->uxNumberOfItems )–;

猜你喜欢

转载自blog.csdn.net/Dallas01/article/details/118720734
今日推荐