首頁 > 軟體

FreeRTOS實時作業系統的任務應用函數詳解

2022-04-07 19:00:40

任務應用函數是一組輔助類函數,一般用於偵錯資訊輸出、獲取任務控制程式碼、獲取任務狀態、操作任務標籤值等等。

1.獲取任務系統狀態

1.1函數描述

         UBaseType_t uxTaskGetSystemState(
                       TaskStatus_t * constpxTaskStatusArray,
                       const UBaseType_tuxArraySize,
                       unsigned long * constpulTotalRunTime );

該函數向TaskStatus_t結構體填充相關資訊,系統中每一個任務的資訊都可以填充到TaskStatus_t結構體陣列中,陣列大小由uxArraySize指定。結構體TaskStatus_t定義如下:

typedef struct xTASK_STATUS
{
   /* 任務控制程式碼*/
   TaskHandle_t xHandle;
   /* 指標,指向任務名*/
   const signed char *pcTaskName;
   /*任務ID,是一個獨一無二的數位*/
   UBaseType_t xTaskNumber;
   /*填充結構體時,任務當前的狀態(執行、就緒、掛起等等)*/
   eTaskState eCurrentState;
   /*填充結構體時,任務執行(或繼承)的優先順序。*/
   UBaseType_t uxCurrentPriority;
   /* 當任務因繼承而改變優先順序時,該變數儲存任務最初的優先順序。僅當configUSE_MUTEXES定義為1有效。*/
   UBaseType_t uxBasePriority;
   /* 分配給任務的總執行時間。僅當宏configGENERATE_RUN_TIME_STATS為1時有效。*/
   unsigned long ulRunTimeCounter;
   /* 從任務建立起,堆疊剩餘的最小數量,這個值越接近0,堆疊溢位的可能越大。 */
   unsigned short usStackHighWaterMark;
}TaskStatus_t;

注意,這個函數僅用來偵錯用,呼叫此函數會掛起所有任務,直到函數最後才恢復掛起的任務,因此任務可能被掛起很長時間。在檔案FreeRTOSConfig.h中,宏configUSE_TRACE_FACILITY必須設定為1,此函數才有效。

1.2引數描述

pxTaskStatusArray:指向TaskStatus_t型別的結構體陣列。這個陣列至少要包含1個元素。RTOS控制的任務數量可以使用API函數uxTaskGetNumberOfTasks()獲取。

uxArraySize:引數pxTaskStatusArray指向的陣列大小,也就是該陣列的索引數目。

pulTotalRunTime:如果在檔案FreeRTOSConfig.h中設定宏configGENERATE_RUN_TIME_STATS為1,則該函數將總執行時間寫入*pulTotalRunTime中。pulTotalRunTime可以設定為NULL,表示忽略總執行時間。

1.3返回值

被填充的TaskStatus_t結構體數量。這個值應該等於通過呼叫API函數uxTaskGetNumberOfTasks()返回的值,但如果傳遞給uxArraySize引數的值太小,則返回0。

1.4用法舉例

/*本例演示如是使用uxTaskGetSystemState()函數來獲取執行時間資訊,並將其轉化為程式設計師更易識別的字元格式,這些轉化後的字元儲存到pcWriteBuffer中。*/
void vTaskGetRunTimeStats(signed char *pcWriteBuffer )
{
   TaskStatus_t*pxTaskStatusArray;
   volatileUBaseType_t uxArraySize, x;
   unsignedlong ulTotalRunTime, ulStatsAsPercentage;
    /* 防禦性程式碼,確保字串有合理的結束*/
  *pcWriteBuffer = 0x00;
    /* 獲取任務總數目*/
  uxArraySize = uxTaskGetNumberOfTasks ();
    /*為每個任務的TaskStatus_t結構體分配記憶體,也可以靜態的分配一個足夠大的陣列 */
  pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ));
    if(pxTaskStatusArray != NULL )
   {
      /*獲取每個任務的狀態資訊 */
     uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize,&ulTotalRunTime );
       /* 百分比計算 */
     ulTotalRunTime /= 100UL;
      /* 避免除零錯誤 */
      if(ulTotalRunTime > 0 )
      {
         /* 將獲得的每一個任務狀態資訊部分的轉化為程式設計師容易識別的字串格式*/
        for( x = 0; x < uxArraySize; x++ )
         {
           /* 計算任務執行時間與總執行時間的百分比。*/
           ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter /ulTotalRunTime;
           if( ulStatsAsPercentage > 0UL )
           {
              sprintf( pcWriteBuffer, "%stt%lutt%lu%%rn",
                                pxTaskStatusArray[ x ].pcTaskName,
                                pxTaskStatusArray[ x ].ulRunTimeCounter,
                                ulStatsAsPercentage );
           }
           else
           {
              /* 任務執行時間不足總執行時間的1%*/
              sprintf( pcWriteBuffer, "%stt%lutt<1%%rn",
                                pxTaskStatusArray[ x ].pcTaskName,
                                 pxTaskStatusArray[x ].ulRunTimeCounter );
           }
           pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
         }
      }
      /* 釋放之前申請的記憶體*/
     vPortFree( pxTaskStatusArray );
   }
}

2.獲取當前任務控制程式碼

2.1函數描述

TaskHandle_t xTaskGetCurrentTaskHandle(void );

在檔案FreeRTOSConfig.h中,宏INCLUDE_xTaskGetCurrentTaskHandle必須設定為1,此函數才有效。

2.2返回值

返回當前任務(呼叫該函數的任務)的控制程式碼。

3.獲取空閒任務控制程式碼

3.1函數描述

TaskHandle_t xTaskGetIdleTaskHandle(void );

在檔案FreeRTOSConfig.h中,宏INCLUDE_xTaskGetIdleTaskHandle必須設定為1,此函數才有效。

3.2返回值

返回空閒任務控制程式碼。空閒任務在RTOS排程器啟動時自動建立。

4.獲取任務堆疊最大使用深度

4.1函數描述

UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );

任務的堆疊空間會隨著任務執行以及中斷處理而增長或縮小。該函數可以返回任務啟動後的最小剩餘堆疊空間。換句話說,可以間接估算出一個任務最多需要多少堆疊空間。在檔案FreeRTOSConfig.h中,宏INCLUDE_uxTaskGetStackHighWaterMark 必須設定成1,此函數才有效。

4.2引數描述

xTask:任務控制程式碼。NULL表示檢視當前任務的堆疊使用情況。

4.3返回值

返回最小剩餘堆疊空間,以字為單位。比如一個32為架構處理器,返回值為1表示有4位元組堆疊空間沒有使用過。如果返回值為0,則任務很可能已經發生了堆疊溢位。

4.4用法舉例

     void vTask1( void * pvParameters )
     {
         UBaseType_tuxHighWaterMark;
         /* 入口處檢測一次 */
         uxHighWaterMark =uxTaskGetStackHighWaterMark( NULL );
 
         for( ;; )
         {
             /* 正常呼叫函數 */
             vTaskDelay( 1000 );
             /* 測量堆疊使用情況 */
             uxHighWaterMark =uxTaskGetStackHighWaterMark( NULL );
         }
    }

5.獲取任務狀態

5.1函數描述

eTaskState eTaskGetState( TaskHandle_txTask );

返回一個列舉型別的任務狀態值。在檔案FreeRTOSConfig.h中,宏INCLUDE_eTaskGetState必須設定為1,此函數才有效。

5.2引數描述

xTask:任務控制程式碼

5.3返回值

下表列出返回值和對應的任務狀態。

6.獲取任務描述內容

6.1函數描述

char * pcTaskGetTaskName( TaskHandle_txTaskToQuery );

獲取任務的描述內容,在檔案FreeRTOSConfig.h中,宏INCLUDE_pcTaskGetTaskName必須設定成1,此函數才有效。

6.2引數描述

xTaskToQuery:任務的控制程式碼。NULL表示獲取當前任務的描述內容指標。

6.3返回值

一個指標,指向任務描述字串。

7.獲取系統節拍次數

7.1函數描述

volatile TickType_t xTaskGetTickCount(void );

這個函數不能在ISR中呼叫。在ISR中用xTaskGetTickCountFromISR(),原型為volatileTickType_t xTaskGetTickCountFromISR( void )。

7.2返回值

返回從vTaskStartScheduler函數呼叫後的系統時鐘節拍次數。

8.獲取排程器狀態

8.1函數描述

BaseType_t xTaskGetSchedulerState( void);

獲取排程器當前狀態。在檔案FreeRTOSConfig.h中,宏INCLUDE_xTaskGetSchedulerState或configUSE_TIMERS必須定義為1,此函數才有效。

8.2返回值

&&&返回值是以下常數之一(定義在task.h):taskSCHEDULER_NOT_STARTED(未啟動)、taskSCHEDULER_RUNNING(正常執行)、taskSCHEDULER_SUSPENDED(掛起)。

9.獲取任務總數

9.1函數描述

UBaseType_t uxTaskGetNumberOfTasks(void );

&&&獲取RTOS核心當前管理的任務總數。包含所有就緒、阻塞和掛起狀態的任務。對於一個刪除的任務,如果它的堆疊空間還沒有被空閒任務釋放掉,則這個被刪除的任務也含在計數值中。

9.2返回值

&&&返回RTOS核心當前管理的任務總數。

10.獲取所有任務詳情

10.1函數描述

void vTaskList( char *pcWriteBuffer );

&&&將每個任務的狀態、堆疊使用情況等以字元的形式儲存到引數pcWriteBuffer指向的區域。vTaskList()函數呼叫usTaskGetSystemState()函數,然後將得到的資訊格式化為程式設計師易讀的字元形式。輸出的內容例子如下圖所示,圖中State一欄中,B表示阻塞、R表示就緒、D表示刪除(等待清除記憶體)、S表示掛起或阻塞。

&&&注意,呼叫這個函數會掛起所有任務,這一過程可能持續較長時間,因此本函數僅在偵錯時使用。在檔案FreeRTOSConfig.h中,宏configUSE_TRACE_FACILITY和configUSE_STATS_FORMATTING_FUNCTIONS必須定義為1,此函數才有效。

10.2引數描述

pcWriteBuffer:任務的資訊會寫入這個緩衝區,為ASCII表單形式。這個緩衝區要足夠大,以容納生成的報告,每個任務大約需要40個位元組。

11.獲取任務執行時間

11.1函數描述

void vTaskGetRunTimeStats( char*pcWriteBuffer );

這個函數用於統計每個任務的執行時間。要使用這個函數必須滿足一些條件,那就是必須有一個用於時間統計的定時器或計數器,這個定時器或計數器的精度要至少大於10倍的系統節拍週期。這個定時器或計數器的設定以及獲取定時時間是由兩個宏定義實現的,這兩個宏一般在檔案FreeRTOSConfig.h中定義。設定定時器或計數器的宏為portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(),獲取定時時間的宏為portGET_RUN_TIME_COUNTER_VALUE。實現了這兩個宏定義後,還必須在檔案FreeRTOSConfig.h中將宏configGENERATE_RUN_TIME_STATS和configUSE_STATS_FORMATTING_FUNCTIONS設定為1,此API函數才有效。

&&&這個API函數呼叫usTaskGetSystemState()函數獲取每個任務的狀態資訊,並把其中的執行時間格式化為程式設計師易讀的字元形式,並將這些資訊儲存到引數pcWriteBuffer指向的區域。

&&&注意,呼叫這個函數會掛起所有任務,這一過程可能持續較長時間,因此本函數僅在偵錯時使用。

11.2引數描述

pcWriteBuffer:任務的執行時間資訊會寫入這個緩衝區,為ASCII表單形式。這個緩衝區要足夠大,以容納生成的報告,每個任務大約需要40個位元組。

11.3用法舉例

&&&以lpc17xx系列為控制為例,我們使用定時器0來作為統計基準時鐘。

11.3.1使能函數宏

&&&在檔案FreeRTOSConfig.h中,設定宏configGENERATE_RUN_TIME_STATS和configUSE_STATS_FORMATTING_FUNCTIONS為1,

11.3.2定時初始化定時器程式碼

void vConfigureTimerForRunTimeStats( void )
{
    /* 使能定時器0的外設電源,設定外設時鐘 */
    PCONP |= 0x02UL;
    PCLKSEL0 = (PCLKSEL0& (~(0x3<<2))) | (0x01 << 2);
    /* 復位定時器 0 */
    T0TCR = 0x02;
    /* 作為計數器 */
    T0CTCR = 0x00;
    /* 預分頻,設定合適的解析度即可 */
    T0PR =  ( configCPU_CLOCK_HZ / 10000UL ) - 1UL;
    /* 啟動計數器 */
    T0TCR = 0x01;
}

11.3.3定義設定定時器和獲取定時時間宏

&&&在檔案FreeRTOSConfig.h中,定義下列程式碼:

extern void vConfigureTimerForRunTimeStats( void );
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats()
#defineportGET_RUN_TIME_COUNTER_VALUE() T0TC

12.設定任務標籤值

12.1函數描述

       voidvTaskSetApplicationTaskTag( TaskHandle_t xTask,
                        TaskHookFunction_tpxTagValue );

&&&可以給每個任務分配一個標籤值。這個值一般用於應用程式,RTOS核心不會使用。在檔案FreeRTOSConfig.h中,宏configUSE_APPLICATION_TASK_TAG必須設定為1,此函數才有效。

12.2引數描述

xTask:任務控制程式碼。NULL表示當前任務。pxTagValue:要分配給任務的標籤值。這是一個TaskHookFunction_t型別的函數指標,但也可以給任務標籤分配任意的值。

注:TaskHookFunction_t原型定義:typedef BaseType_t (*TaskHookFunction_t)(void * )

12.3用法舉例

/* 在這個例子中,給任務設定一個整形標籤值。例子中使用了RTOS跟蹤勾點宏。*/
void vATask( void *pvParameters )
{
  /* 為自己的標籤分配一個整形值 */
 vTaskSetApplicationTaskTag( NULL, ( void * ) 1 );
  for( ;; )
  {
    /* 任務主體程式碼 */
  }
}
/*****************************************************************************/
/*在這個任務中,給任務設定一個函數標籤值。首先定義一個回撥函數,這個函數必須宣告為TaskHookFunction_t型別。 */
static BaseType_t prvExampleTaskHook( void * pvParameter )
{
  /* 這裡為使用者定義程式碼 –可能是記錄資料、更新任務狀態值等。*/
  return 0;
}
/* 將回撥函數設定為任務的標籤值。 */
void vAnotherTask( void *pvParameters )
{
  /* 註冊回撥函數*/
 vTaskSetApplicationTaskTag( NULL, prvExampleTaskHook );
  for( ;; )
  {
     /* 任務主體程式碼 */
  }
}
/* 每當工作切換時,會呼叫xTaskCallApplicationTaskHook 函數(見14.)。 */
#define traceTASK_SWITCHED_OUT() xTaskCallApplicationTaskHook(pxCurrentTCB,0 )

13.獲取任務標籤值

13.1函數描述

TaskHookFunction_txTaskGetApplicationTaskTag( TaskHandle_t xTask );

返回分配給任務的標籤值。程式設計師定義標籤值,RTOS核心通常不會存取標籤值。

函數僅對高階使用者使用。在檔案FreeRTOSConfig.h中,宏configUSE_APPLICATION_TASK_TAG必須設定為1,此函數才有效。

13.2引數描述

xTask:任務控制程式碼。NULL表示當前任務。

13.3返回值

返回指定任務的標籤值。

14.執行任務的應用勾點函數

14.1函數描述

         BaseType_txTaskCallApplicationTaskHook(
                                   TaskHandle_txTask,
                                   void*pvParameter );

可以為每個任務分配一個標籤值,當這個值是一個TaskHookFunction_t型別函數指標時,相當於應用程式向任務註冊了一個回撥函數,而API函數xTaskCallApplicationTaskHook用來呼叫這個回撥函數。

一般這個函數配合RTOS跟蹤勾點宏使用,見12.設定任務標籤值一節的用法舉例。

14.2引數描述

xTask:任務控制程式碼。NULL表示當前任務。pvParameter:作為引數傳遞給應用勾點函數

15.設定執行緒本地儲存指標

15.1函數描述

       void vTaskSetThreadLocalStoragePointer(TaskHandle_t xTaskToSet,
                                       BaseType_t xIndex,
                                        void*pvValue )

此函數僅用於高階使用者。

執行緒本地儲存允許應用程式在任務的控制塊中儲存一些值,每個任務都有自己獨立的儲存空間。

比如,許多庫函數都包含一個叫做errno的全域性變數。某些庫函數使用errno返回庫函數錯誤資訊,應用程式檢查這個全域性變數來確定發生了那些錯誤。在單執行緒程式中,將errno定義成全域性變數是可以的,但是在多執行緒應用中,每個執行緒(任務)必須具有自己獨有的errno值,否則,一個任務可能會讀取到另一個任務的errno值。

FreeRTOS提供了一個靈活的機制,使得應用程式可以使用執行緒本地儲存指標來讀寫執行緒本地儲存。在檔案FreeRTOSConfig.h中,宏configNUM_THREAD_LOCAL_STORAGE_POINTERS指定每個任務執行緒本地儲存指標陣列的大小。API函數vTaskSetThreadLocalStoragePointer()用於向指標陣列中寫入值,API函數pvTaskGetThreadLocalStoragePointer()用於從指標陣列中讀取值。

15.2引數描述

xTaskToSet:任務控制程式碼。NULL表示當前任務。

xIndex:寫入到執行緒本地儲存陣列的索引號,執行緒本篤儲存陣列的大小由宏configNUM_THREAD_LOCAL_STORAGE_POINTERS設定,該宏在檔案FreeRTOSConfig.h中。

pvValue:寫入到指定索引地址的資料值

15.3用法舉例

&&參見16.獲取執行緒本地儲存指標一節。

16.讀取執行緒本地儲存指標

16.1函數描述

         void*pvTaskGetThreadLocalStoragePointer(
                                 TaskHandle_txTaskToQuery,
                                 BaseType_txIndex );

此函數僅用於高階使用者。從執行緒本地儲存指標陣列中讀取值。更詳細描述見15.設定執行緒本地儲存指標一節。

16.2引數描寫

xTaskToQuery:任務控制程式碼。NULL表示當前任務。

xIndex:寫入到執行緒本地儲存陣列的索引號,執行緒本篤儲存陣列的大小由宏configNUM_THREAD_LOCAL_STORAGE_POINTERS設定,該宏在檔案FreeRTOSConfig.h中。

16.3返回值

返回一個指標,這個指標儲存線上程本地儲存指標陣列中,陣列索引由引數xIndex指定。

16.4用法舉例

16.4.1儲存一個整形數

uint32_tulVariable;
/* 向當前任務的執行緒本地儲存陣列下標為1的位置寫入一個指向32位元常數值的指標。*/
vTaskSetThreadLocalStoragePointer(NULL, 1, ( void * ) 0x12345678 );
/*向當前任務的執行緒本地儲存陣列下標為0的位置寫入一個指向32整形值的指標*/
ulVariable= ERROR_CODE;
vTaskSetThreadLocalStoragePointer(NULL, 0, ( void * ) ulVariable );
/*從當前任務的執行緒本地儲存陣列下標為5的位置讀取出一個指標並賦值給32位元整形變數。*/
ulVariable= ( uint32_t ) pvTaskGetThreadLocalStoragePointer( NULL, 5 );

16.4.2儲存結構提

typedefstruct
{
    uint32_t ulValue1;
    uint32_t ulValue2;
}xExampleStruct;
xExampleStruct*pxStruct;
/*為結構體分配記憶體*/
pxStruct= pvPortMalloc( sizeof( xExampleStruct ) );
/*為結構體成員賦值*/
pxStruct->ulValue1= 0;
pxStruct->ulValue2= 1;
/*向當前任務的執行緒本地儲存陣列下標為0的位置寫入一個指向結構體變數的指標*/
vTaskSetThreadLocalStoragePointer(NULL, 0, ( void * ) pxStruct );
/*從當前任務的執行緒本地儲存陣列下標為0的位置讀取出一個結構體指標*/
pxStruct= ( xExampleStruct * ) pvTaskGetThreadLocalStoragePointer( NULL, 0 );

17.設定超時狀態

17.1函數描述

void vTaskSetTimeOutState( TimeOut_t *const pxTimeOut );

此函數僅用於高階使用者,通常與API函數xTaskCheckForTimeOut()共同使用。

任務因為等待某事件而進入阻塞狀態,通常情況下任務會設定一個等待超時週期。如果在等待事件超時,任務會退出阻塞狀態。想象一個這樣的應用,某任務等待一個事件而進入阻塞狀態,但是事件遲遲不發生,超時後任務退出阻塞狀態繼續執行任務。假如任務等待的事件仍然沒有發生,則任務又會阻塞在該事件下。只要任務等待的事件一直不發生,這個任務進入阻塞然後超時退出阻塞,再進入阻塞的迴圈就會一直存在。是不是可以設定一個總超時時間,只要總阻塞時間大於這個總超時時間,則可以結束這個任務或進行相應記錄?freeRTOS提供了兩個API函數來完成這個功能,這就是vTaskSetTimeOutState()和xTaskCheckForTimeOut()。

vTaskSetTimeOutState()函數用於設定初始條件,之後呼叫xTaskCheckForTimeOut()函數檢查任務總阻塞時間是否超過總超時時間,如果沒有超過,則調整剩餘的超時時間計數器。

17.2引數描述

pxTimeOut:指向一個結構體的指標,該結構體用來儲存確定超時是否發生的必要資訊。vTaskSetTimeOutState()函數會設定結構體的成員。

17.3用法舉例

參見18.超時檢測。

18.超時檢測

18.1函數描述

         BaseType_t xTaskCheckForTimeOut(TimeOut_t * const pxTimeOut,
                                 TickType_t* const pxTicksToWait );

此函數僅用於高階使用者,通常與API函數vTaskSetTimeOutState共同使用。

詳細描述見17.設定超時狀態。

18.2引數描述

pxTimeOut:指向一個結構體的指標。該結構體儲存確定超時是否發生的必要資訊。使用API函數vTaskSetTimeOutState初始化該結構體。

pxTicksToWait:TickType_t指標,指向的變數儲存總超時時間。

18.3返回值

pdTRUE:總超時發生pdFALSE:總超時未發生

18.4用法舉例

/* 函數用於從RX緩衝區中接收uxWantedBytes位元組資料,RX緩衝區由UART中斷填充。如果RX緩衝區沒有足夠的資料,則任務進入阻塞狀態,直到RX緩衝區有足夠資料或者發生超時。如果超時後仍然沒有足夠的資料,則任務會再次進入阻塞狀態,xTaskCheckForTimeOut()函數用於重新計算總超時時間以確保總阻塞狀態時間不超過MAX_TIME_TO_WAIT。如果總阻塞狀態時間大於了總超時時間,則不管RX緩衝區是否有充足資料,都將這些資料讀出來。
 */
size_txUART_Receive( uint8_t *pucBuffer, size_t uxWantedBytes )
{
    size_t uxReceived = 0;
    TickType_t xTicksToWait = MAX_TIME_TO_WAIT;
    TimeOut_t xTimeOut;
    /* 初始化結構體變數xTimeOut。*/
   vTaskSetTimeOutState( &xTimeOut );
   /* 無限迴圈,直到緩衝區包含足夠的資料或者阻塞超時發生。*/
   while( UART_bytes_in_rx_buffer(pxUARTInstance ) < uxWantedBytes )
   {
      /* RX緩衝區沒有足夠多的資料,表示任務已經進入過一次阻塞狀態。呼叫API函數xTaskCheckForTimeOut檢查總阻塞時間是否超過總超時時間,如果沒有,則調整剩餘的總超時時間。*/
      if( xTaskCheckForTimeOut( &xTimeOut,&xTicksToWait ) != pdFALSE )
      {
         /* 如果總阻塞時間大於總超時時間,則退出這個迴圈 */
         break;
      }
       /* 在等待了xTicksToWait個系統節拍週期後,向接收中斷髮出通知,需要更多資料。
*/
      ulTaskNotifyTake( pdTRUE, xTicksToWait );
   }
     /*從RX緩衝區讀取uxWantedBytes個位元組並放到pucBuffer緩衝區。*/
    uxReceived = UART_read_from_receive_buffer(pxUARTInstance,  pucBuffer,  uxWantedBytes );
     return uxReceived;
}

以上就是FreeRTOS實時作業系統的任務應用函數詳解的詳細內容,更多關於FreeRTOS任務應用函數的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com