性无码一区二区三区在线观看,少妇被爽到高潮在线观看,午夜精品一区二区三区,无码中文字幕人妻在线一区二区三区,无码精品国产一区二区三区免费

小麥大叔
認(rèn)證:普通會員
所在專題目錄 查看專題
基于CubeIDE快速整合FreeRTOS創(chuàng)建第一個任務(wù)
【FreeRTOS學(xué)習(xí)02】源碼結(jié)構(gòu)/數(shù)據(jù)類型/命名規(guī)則總結(jié)
【FreeRTOS學(xué)習(xí)03】Task Management 任務(wù)管理基本概念介紹
【FreeRTOS學(xué)習(xí)04】Queue Management 消息隊(duì)列使用詳解
【FreeRTOS學(xué)習(xí)05】深度解剖FreeRTOSConfig.h實(shí)現(xiàn)對系統(tǒng)的自定義剪裁
【FreeRTOS學(xué)習(xí)06】深度解剖中斷與任務(wù)之間同步的具體使用場景
作者動態(tài) 更多
一款輕量級的開源GUI項(xiàng)目——SimpleGUI,可以完美適配單色屏
02-22 09:47
看到這100多個軟硬件開源項(xiàng)目,真是爽爆了
2024-11-30 14:12
推薦一個高效,可靠,安全的串口通訊開源方案
2024-11-27 11:17
推薦一款開源hack硬件平臺工具
2024-11-26 13:58
新手學(xué)STM32的話,先學(xué)標(biāo)準(zhǔn)庫還是HAL庫?
2024-10-18 15:09

【FreeRTOS學(xué)習(xí)03】Task Management 任務(wù)管理基本概念介紹

在FreeRTOS中,線程的術(shù)語又可以被稱之為任務(wù),或許這樣更加合適,本文將介紹任務(wù)的創(chuàng)建/刪除,任務(wù)參數(shù)的使用,以及任務(wù)優(yōu)先級;

1 軟實(shí)時和硬實(shí)時

硬實(shí)時系統(tǒng)的任務(wù)運(yùn)行正確性與響應(yīng)時限是緊密相關(guān)的,一旦超過時限將導(dǎo)致嚴(yán)重的后果,比如導(dǎo)彈控制系統(tǒng)、高鐵自動駕駛系統(tǒng)等,都是需要嚴(yán)格的響應(yīng)時限的。 軟實(shí)時系統(tǒng)中,雖然也存在時限指標(biāo),但是如果輸出響應(yīng)超過時限,一般不會造成嚴(yán)重后果,比如Windows桌面任務(wù),DVD播放機(jī)的視頻播放。 大多數(shù)嵌入式系統(tǒng)不僅能滿足硬實(shí)時要求,也能滿足軟實(shí)時要求。 軟實(shí)時

  • Windows;Linux系統(tǒng)通常為軟實(shí)時,當(dāng)然有補(bǔ)丁可以將內(nèi)核做成硬實(shí)時的系統(tǒng),不過商用沒有這么做的。

硬實(shí)時

  • VxWorks,uCOS,FreeRTOS,WinCE,RT-thread等實(shí)時系統(tǒng);

2 任務(wù)概述

2.1 基本寫法

FreeRTOS多任務(wù)的實(shí)時系統(tǒng),其最基本的運(yùn)行單元為任務(wù),其表示形式為由C語言函數(shù)實(shí)現(xiàn)的,該函數(shù)原型要求必須返回 void,并且?guī)б粋€ void 類型指針的參數(shù);具體如下所示;

void ATaskFunc(void *args);

每個任務(wù)都是在自己權(quán)限范圍內(nèi)的一個小程序。其具有程序入口,通常會運(yùn)行在一個死循環(huán)中,也不會退出,具體如下;

void ATaskFunc(void *args){ while(1){  //TODO  }}

FreeRTOS 任務(wù)不允許以任何方式從實(shí)現(xiàn)函數(shù)中返回——它們絕不能有一條return語句,也不能執(zhí)行到函數(shù)末尾,如果不再需要,則在任務(wù)中調(diào)用刪除任務(wù)的API,具體如下所示;

void ATaskFunc(void *args){ vTaskDelete( NULL );}

2.2 TCB

TCB為任務(wù)控制塊,或者是線程控制塊,另外操作系統(tǒng)中還有PCB為進(jìn)程控制塊,主要封裝了一個任務(wù)在系統(tǒng)調(diào)度中所需要的所有資源,FreeRTOSTCB的成員,具體如下所示;

任務(wù)狀態(tài)如下所示;

typedef struct xTASK_STATUS
{
	/* The handle of the task to which the rest of the information in the structure relates. */
	TaskHandle_t xHandle;			
	/* A pointer to the task's name.*/ 
	const char *pcTaskName;			
	/* A number unique to the task. */	
	UBaseType_t xTaskNumber;		
	/* The state in which the task existed when the structure was populated. */
	eTaskState eCurrentState;		
	/* The priority at which the task was running (may be inherited) when the structure was populated. */
	UBaseType_t uxCurrentPriority;	
	UBaseType_t uxBasePriority;		
	uint32_t ulRunTimeCounter;		
	StackType_t *pxStackBase;		
	uint16_t usStackHighWaterMark;	
} TaskStatus_t;

每一個任務(wù)都會擁有一個自己的TCB,具體如下圖所示;

typedef struct tskTaskControlBlock
{
	volatile StackType_t	*pxTopOfStack;	/*< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */

	#if ( portUSING_MPU_WRAPPERS == 1 )
		xMPU_SETTINGS	xMPUSettings;		/*< The MPU settings are defined as part of the port layer.  THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
	#endif

	ListItem_t			xStateListItem;	/*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
	ListItem_t			xEventListItem;		/*< Used to reference a task from an event list. */
	UBaseType_t			uxPriority;			/*< The priority of the task.  0 is the lowest priority. */
	StackType_t			*pxStack;			/*< Points to the start of the stack. */
	char				pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created.  Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */

	#if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
		StackType_t		*pxEndOfStack;		/*< Points to the highest valid address for the stack. */
	#endif

	#if ( portCRITICAL_NESTING_IN_TCB == 1 )
		UBaseType_t		uxCriticalNesting;	/*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
	#endif

	#if ( configUSE_TRACE_FACILITY == 1 )
		UBaseType_t		uxTCBNumber;		/*< Stores a number that increments each time a TCB is created.  It allows debuggers to determine when a task has been deleted and then recreated. */
		UBaseType_t		uxTaskNumber;		/*< Stores a number specifically for use by third party trace code. */
	#endif

	#if ( configUSE_MUTEXES == 1 )
		UBaseType_t		uxBasePriority;		/*< The priority last assigned to the task - used by the priority inheritance mechanism. */
		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;	/*< Stores the amount of time the task has spent in the Running state. */
	#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

	/* See the comments above the definition of
	tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
	#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */
		uint8_t	ucStaticallyAllocated; 		/*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
	#endif

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

} tskTCB;

3 任務(wù)狀態(tài)

任務(wù)頂層存在兩種狀態(tài),運(yùn)行態(tài)非運(yùn)行態(tài); 但是非運(yùn)行的任務(wù)狀態(tài)又可以分為:堵塞狀態(tài) / Blocked,掛起狀態(tài) / Suspend,就緒狀態(tài) / Ready,下面簡單做一下介紹;

  • 運(yùn)行狀態(tài) / Running 運(yùn)行態(tài)的任務(wù)完全占用CPU的使用權(quán),如果當(dāng)前CPU只有一個內(nèi)核,那么在某個時刻只能運(yùn)行一個任務(wù),就是所謂的單核單線程;

  • 堵塞狀態(tài) / Blocked; 用戶可以主動調(diào)用vTaskDelay(T)將任務(wù)進(jìn)入堵塞狀態(tài),直到任務(wù)堵塞時間已經(jīng)達(dá)到T;或者該任務(wù)在等待隊(duì)列,信號量,事件組,通知或信號量事件時,也將處于堵塞狀態(tài);處于堵塞狀態(tài)的任務(wù)不再占用CPU,同樣也不能直接進(jìn)入運(yùn)行狀態(tài),而是先進(jìn)入就緒狀態(tài);

  • 掛起狀態(tài) / Suspend; 任何狀態(tài)的下的任務(wù)都可以通過調(diào)用vTaskSuspend函數(shù)進(jìn)入掛起狀態(tài),并且無法直接進(jìn)入運(yùn)行態(tài),只能通過調(diào)用xTaskResume函數(shù)進(jìn)入就緒狀態(tài);

  • 就緒狀態(tài) / Ready; 被搶占的任務(wù)將處于就緒狀態(tài),掛起的任務(wù)被回復(fù)的會處于就緒狀態(tài),堵塞的任務(wù)收到相應(yīng)事件也會處于就緒狀態(tài),如果當(dāng)前沒有更高優(yōu)先級的任務(wù)處于運(yùn)行,則當(dāng)前就緒狀態(tài)的任務(wù)進(jìn)入運(yùn)行狀態(tài);

其主要的狀態(tài)轉(zhuǎn)換關(guān)系如下圖所示;

FreeRTOS使用一個枚舉封裝了任務(wù)的狀態(tài),具體如下所示;

typedef enum
{
	eRunning = 0,/* A task is querying the state of itself, so must be running. */
	eReady,		/* The task being queried is in a read or pending ready list. */
	eBlocked,	/* The task being queried is in the Blocked state. */
	eSuspended,	/* The task being queried is in the Suspended state*/
	eDeleted,	/* The task being queried has been deleted, but its TCB has not yet been freed. */
	eInvalid	/* Used as an 'invalid state' value. */
} eTaskState;

4 任務(wù)優(yōu)先級

FreeRTOS的最低優(yōu)先級是0,分配給了空閑任務(wù),空閑任務(wù)的優(yōu)先級使用宏定義tskIDLE_PRIORITY進(jìn)行表示,最大的優(yōu)先級為需要用戶進(jìn)行配置;在FreeRTOS.h中可以看到預(yù)編譯指令,具體如下:

#ifndef configMAX_PRIORITIES
	#error Missing definition:  configMAX_PRIORITIES must be defined in FreeRTOSConfig.h.  \
	See the Configuration section of the FreeRTOS API documentation for details.
#endif
 
#if configMAX_PRIORITIES < 1
	#error configMAX_PRIORITIES must be defined to be greater than or equal to 1.
#endif

configMAX_PRIORITIES需要用戶在FreeRTOSConfig.h進(jìn)行定義,則任務(wù)最大的優(yōu)先級為configMAX_PRIORITIES - 1。

5 相關(guān)函數(shù)

任務(wù)管理的函數(shù)聲明和一些基本類型都封裝在源碼tasks.h中;

5.1 創(chuàng)建任務(wù)

使用xTaskCreate創(chuàng)建一個任務(wù),具體如下所示;

// Task to be created.
 void vTaskCode( void * pvParameters )
 {
	 for( ;; )
	 {
		 // Task code goes here.
	 }
 }
 // Function that creates a task.
 void vOtherFunction( void )
 {
 static uint8_t ucParameterToPass;
 TaskHandle_t xHandle = NULL;

	 // Create the task, storing the handle.  Note that the passed parameter ucParameterToPass
	 // must exist for the lifetime of the task, so in this case is declared static.  If it was just an
	 // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
	 // the new task attempts to access it.
	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
     configASSERT( xHandle );

	 // Use the handle to delete the task.
     if( xHandle != NULL )
     {
	     vTaskDelete( xHandle );
     }
 }

5.2 函數(shù)刪除

使用函數(shù)vTaskDelete對函數(shù)進(jìn)行刪除;

 void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION;

 void vOtherFunction( void )
 {
 TaskHandle_t xHandle;

	 // Create the task, storing the handle.
	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );

	 // Use the handle to delete the task.
	 vTaskDelete( xHandle );
 }

5.3 堵塞任務(wù)

使用vTaskDelay函數(shù)可以將任務(wù)堵塞一定時間;

 void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION;
 void vTaskFunction( void * pvParameters )
 {
 // Block for 500ms.
 const TickType_t xDelay = 500 / portTICK_PERIOD_MS;

	 for( ;; )
	 {
		 // Simply toggle the LED every 500ms, blocking between each toggle.
		 vToggleLED();
		 vTaskDelay( xDelay );
	 }
 }

5.4 掛起和恢復(fù)

使用函數(shù)vTaskSuspend可以將函數(shù)掛起,通過vTaskResume(xHandle)函數(shù)可以將掛起的函數(shù)恢復(fù)到就緒狀態(tài);

 void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION;

 void vAFunction( void )
 {
 	 TaskHandle_t xHandle;

	 // Create a task, storing the handle.
	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );

	 // ...

	 // Use the handle to suspend the created task.
	 vTaskSuspend( xHandle );

	 // ...

	 // The created task will not run during this period, unless
	 // another task calls vTaskResume( xHandle ).

	 //...


	 // Suspend ourselves.
	 vTaskSuspend( NULL );

	 // We cannot get here unless another task calls vTaskResume
	 // with our handle as the parameter.
 }

6 總結(jié)

先了解任務(wù)之前的狀態(tài),先學(xué)會使用FreeRTOS的常用接口,后續(xù)對于其調(diào)度算法和內(nèi)存管理的算法可以分析和學(xué)習(xí)一下。


文中難免有錯誤和紕漏之處,請大佬們不吝賜教 創(chuàng)作不易,如果本文幫到了您; 請幫忙點(diǎn)個贊

聲明:本內(nèi)容為作者獨(dú)立觀點(diǎn),不代表電子星球立場。未經(jīng)允許不得轉(zhuǎn)載。授權(quán)事宜與稿件投訴,請聯(lián)系:editor@netbroad.com
覺得內(nèi)容不錯的朋友,別忘了一鍵三連哦!
贊 4
收藏 3
關(guān)注 144
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧