天天看點

freertos 源碼學習一 ------ xTaskCreate()參數部分解析。

今天開始有決心來學習freertos 的源碼,因為我感覺非開始不行了。

        我從freertos 官網下載下傳了源代碼(10.1.1)。下載下傳源代碼很簡單,隻需要在搜尋網站上輸入“freertos”  在下面就出現首頁面。點選進去下載下傳就好了。這個就不多說了,這是我的第一篇學習freertos 的文章,是以提了一下上面的話。謝謝大家提出寶貴意見。

今天的主角:xTaskCreate()

BaseType_t xTaskCreate(	TaskFunction_t pxTaskCode,
		        const char * const pcName,		
		        const configSTACK_DEPTH_TYPE usStackDepth,
		        void * const pvParameters,
		        UBaseType_t uxPriority,
		        TaskHandle_t * const pxCreatedTask 
                    )
           

當我看到這個函數的時候,我第一個想法就是: 它的參數是什麼意思?有什麼作用?

是以我下面的就逐一去找這些參數的定義。

(1)TaskFunction_t   : typedef   void   (*TaskFunction_t)( void * );    很顯然是函數指針

(2)const  char  *  const  pcName  :  任務名字

(3)configSTACK_DEPTH_TYPE   :   #define  configSTACK_DEPTH_TYPE   uint16_t   是無符号的2位元組數值

(4)void  *  const  pvParameters  :從名字看是要傳入的參數

(5)UBaseType_t   uxPriority   :    typedef  unsigned   short   UBaseType_t;  是一個無符号的整形數

(6)TaskHandle_t  *  const   pxCreatedTask :這裡面有一個結構體指針。下面列出來

typedef struct tskTaskControlBlock 
{
	volatile StackType_t	*pxTopOfStack;	

	#if ( portUSING_MPU_WRAPPERS == 1 )
		xMPU_SETTINGS	xMPUSettings;		
	#endif

	ListItem_t	xStateListItem;	
	ListItem_t	xEventListItem;		
	UBaseType_t	uxPriority;			
	StackType_t	*pxStack;			/*< Points to the start of the stack. */
	char		pcTaskName[ configMAX_TASK_NAME_LEN ];

	#if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
		StackType_t	*pxEndOfStack;		
	#endif

	#if ( portCRITICAL_NESTING_IN_TCB == 1 )
		UBaseType_t	uxCriticalNesting;	
	#endif

	#if ( configUSE_TRACE_FACILITY == 1 )
		UBaseType_t	uxTCBNumber;		
		UBaseType_t	uxTaskNumber;		
	#endif

	#if ( configUSE_MUTEXES == 1 )
		UBaseType_t	uxBasePriority;		
		UBaseType_t	uxMutexesHeld;
	#endif

	#if ( configUSE_APPLICATION_TASK_TAG == 1 )
		TaskHookFunction_t pxTaskTag;
	#endif

	#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
		void  *pvThreadLocalStoragePointers[configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
	#endif

	#if( configGENERATE_RUN_TIME_STATS == 1 )
		uint32_t ulRunTimeCounter;	
	#endif

	#if ( configUSE_NEWLIB_REENTRANT == 1 )
		struct	_reent xNewLib_reent;
	#endif

	#if( configUSE_TASK_NOTIFICATIONS == 1 )
		volatile uint32_t ulNotifiedValue;
		volatile uint8_t ucNotifyState;
	#endif

	#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) 
		uint8_t	ucStaticallyAllocated; 		
	#endif

	#if( INCLUDE_xTaskAbortDelay == 1 )
		uint8_t ucDelayAborted;
	#endif

	#if( configUSE_POSIX_ERRNO == 1 )
		int iTaskErrno;
	#endif

} tskTCB;
           

上面的代碼,我删除了很多的注釋。不删除注釋的話,顯示的會很亂。看到這個結構體這麼大,我感覺肯定很重要。認真去看他的每一個成員。

(1)volatile StackType_t    *pxTopOfStack;   :pxTopOfStack  從名字看,是指向棧的最頂端。

         這個裡面還用了一個很重要的關鍵字:volatile  

(2)xMPU_SETTINGS    xMPUSettings;  xMPU_SETTINGS 是一個結構體,

typedef struct MPU_SETTINGS
{

	xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS ];

} xMPU_SETTINGS;


typedef struct MPU_REGION_REGISTERS
{

	uint32_t ulRegionBaseAddress;
	uint32_t ulRegionAttribute;

} xMPU_REGION_REGISTERS;

           

     從代碼看到xRegion  是一個帶有區域基位址和區域屬性的數組結構體。那麼我又想到了一個問題,這個區域是做什麼的啊? 這個問題就暫且保留吧,後面肯定會揭發它。

(3)ListItem_t            xStateListItem;   這個裡面我想着重研究明白,ListItem_t 這個結構體。

struct xLIST;
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;					
           

<1>就是一層跟着一層的出現未知的内容。listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE   這個宏又是幹什麼的呢?

宏listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE和listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE用于檢查清單項資料是否完整。

<2>configLIST_VOLATILE TickType_t xItemValue;      typedef   uint16_t    TickType_t;  這僅是一個值,但是我還不知道用來做什麼?

 xItemValue是清單項值,通常是一個被跟蹤的任務優先級或是一個排程事件的計數器值。

<3>struct xLIST_ITEM * configLIST_VOLATILE pxNext;  和   struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;  這個就很容易了解了,雙向連結清單的pre 和 next。

<4>void * pvOwner;  指向一個任務TCB。

<5>struct   xLIST  *   configLIST_VOLATILE   pxContainer;

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;

/*
 * 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;
           

從xLIST 結構體中看到xListEnd 中有MiniListItem 子集,而這個子集不難發現是把雙向連結清單的元素選擇出來了。也就是說連結清單索引時隻需要讀取這個元素就可以了。

(4)剩下的内容會在遇到的時候,再添加。

到這裡參數就分析完了。但這隻是剛開始,因為讀完這麼多參數功能,我們還需要靜下心來想一想這個函數的參數到底布下了一張什麼樣的網?? 有函數指針,有任務名字字元串指針,有整型數,有操作句柄--> 在句柄中有清單項,有雙向連結清單,在結構體中有宏檢查資料完整,。。。。。   我們靜下心來思考吧,每個人都有自己的體會。

繼續閱讀