FreeRTOS列表和列表項


FreeRTOS中的列表和列表項類似於數據結構中的鏈表和節點;

相關的文件是list.c和list.h兩個文件;

List_t列表結構體

具體定義如下:

/*
 * Definition of the type of queue used by the scheduler.
 */
typedef struct xLIST
{
	listFIRST_LIST_INTEGRITY_CHECK_VALUE
	volatile UBaseType_t uxNumberOfItems;
	ListItem_t * configLIST_VOLATILE pxIndex;
	MiniListItem_t xListEnd;
	listSECOND_LIST_INTEGRITY_CHECK_VALUE
} List_t;

在上述結構體中:

  • listFIRST_LIST_INTEGRITY_CHECK_VALUElistSECOND_LIST_INTEGRITY_CHECK_VALUE兩個成員,是用來檢查列表完整性的,如果使用需要將宏configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES設置為1,之后會將這兩個成員分別用xListIntegrityValue1xListIntegrityValue2替換,並且在初始化函數vListInitialise()中給這兩個成員變量設置一個特殊的值,一般默認不使用
  • uxNumberOfItems是一個unsigned long類型的變量,用於記錄列表中列表項的個數;
  • pxIndex用來記錄當前列表項索引值,用於遍歷列表;
  • xListEnd列表中最后一個列表項,用來表示列表結尾,該變量的類型是一個Mini列表項類型;

xLIST_ITEM列表項結構體

struct xLIST_ITEM
{
	listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE			
	configLIST_VOLATILE TickType_t xItemValue;			
	struct xLIST_ITEM * configLIST_VOLATILE pxNext;		
	struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
	void * pvOwner;										
	struct xLIST * configLIST_VOLATILE pxContainer;		
	listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE			
};
typedef struct xLIST_ITEM ListItem_t;	

在上述結構體中:

  • 第一個成員和最后一個成員,用來檢查列表項完整性的,與列表結構體中的作用類似;
  • xItemValue為列表項值;
  • pxNext指向下一個列表項和pxPrevious配合實現類似雙向鏈表的功能;
  • pvOwner記錄該列表項的擁有者,通常是任務塊;
  • pxContainer記錄此列表項歸哪個列表;

xMINI_LIST_ITEM迷你列表項結構體

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;

迷你列表項和列表項結構體區別就是少了幾個成員變量,之所以如此定義是因為有些情況下不需要列表項中的部分變量;

列表的初始化

列表是通過vListInitialise()函數初始化的,源碼定義如下:

void vListInitialise( List_t * const pxList )
{
	pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );
	pxList->xListEnd.xItemValue = portMAX_DELAY;
	pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );
	pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );
	pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
	listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
	listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}

對於listSET_LIST_INTEGRITY_CHECK_1_VALUElistSET_LIST_INTEGRITY_CHECK_2_VALUE兩項默認不使用,所以整個列表初始化之后的示意圖如下:

  • 由於目前還沒有列表項所以uxNumberOfItems變量初始化為0;

  • pxIndex指向列表結構體xLIST中內嵌的xListEnd迷你列表項;

  • 列表項xListEnd中成員變量xItemValue初始化為portMAX_DELAY,portMAX_DELAY是一個宏,定義在portmacro.h文件中,根據使用的MCU不同,對應的值也不同,定義如下:

    #if( configUSE_16_BIT_TICKS == 1 )
    	#define portMAX_DELAY ( TickType_t ) 0xffff
    #else
    	#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
    #endif
    
  • pxNext和pxPrevious都指向自身,也就是xListEnd;

列表項的初始化

void vListInitialiseItem( ListItem_t * const pxItem )
{
	/* Make sure the list item is not recorded as being on a list. */
	pxItem->pxContainer = 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 );
}

主要是將成員變量pxContainer指向NULL;

列表插入操作

列表插入函數有兩個,分別是vListInsertEnd()和vListInsert()函數;

vListInsertEnd()函數是往列表的末尾添加列表項的,列表中的xListEnd成員變量表示末尾,那么該函數插入一個列表項是不是就是插入到xListEnd的前面或者后面?這個不一定;

所謂的末尾要根據列表的成員變量pxIndex來確定的

pxIndex成員變量是用來遍歷列表的,它所指向的列表項就是要遍歷的開始列表項,也就是列表的頭部,由於是個環形列表,所以新的列表項就應該插入到pxIndex所指向的列表項的前面,這才是真正意義上的尾部;

vListInsert()函數是向列表中插入一個列表項,插入的位置由列表項成員變量xItemValue決定

如果xItemValue的值是portMAX_DELAY,那么就直接將列表項插入到xListEnd的前面;

如果xItemValue的值不等於portMAX_DELAY,那么這個要插入的位置根據xItemValue的值按照升序的方式在列表中一個個找,直到最終確定位置插入列表項;

列表項的刪除

列表項的刪除是由函數uxListRemove()實現的,整個過程的操作如下:

  • 從傳入的要刪除的列表項中讀取成員變量pxContainer得到該列表項處於哪個列表中;
  • 斷開該列表項的前后“連接”,即刪除;
  • 如果列表的pxIndex正好指向要刪除的列表項,那么在刪除列表項以后重新給pxIndex找個新的指向,這個新的指向就是被刪除列表項的前一個列表項;
  • 將被刪除的列表項的成員變量pxContainer指向NULL;
  • 返回新列表當前的列表項數目;

列表的遍歷

FreeRTOS提供了一個函數來完成列表的遍歷,就是listGET_OWNER_OF_NEXT_ENTRY(),這個函數本質上是一個宏,沒調用一次這個函數列表的pxIndex變量就會指向下一個列表項,並且通過pxTCB傳出這個列表項的pvOwner變量值;

此函數用於從多個同優先級的就緒任務中查找下一個要運行的任務


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM