<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          FreeRTOS系列第11篇---FreeRTOS任務(wù)應(yīng)用函數(shù)

          共 2843字,需瀏覽 6分鐘

           ·

          2020-09-13 10:43


          關(guān)注、星標(biāo)公眾號,直達(dá)精彩內(nèi)容

          ID:技術(shù)讓夢想更偉大

          整理:李肖遙


          前一篇:FreeRTOS系列第10篇---FreeRTOS任務(wù)控制

          任務(wù)應(yīng)用函數(shù)是一組輔助類函數(shù),一般用于調(diào)試信息輸出、獲取任務(wù)句柄、獲取任務(wù)狀態(tài)、操作任務(wù)標(biāo)簽值等等。

          1.獲取任務(wù)系統(tǒng)狀態(tài)

          1.1函數(shù)描述

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

          該函數(shù)向TaskStatus_t結(jié)構(gòu)體填充相關(guān)信息,系統(tǒng)中每一個任務(wù)的信息都可以填充到TaskStatus_t結(jié)構(gòu)體數(shù)組中,數(shù)組大小由uxArraySize指定。結(jié)構(gòu)體TaskStatus_t定義如下:

          typedef?struct?xTASK_STATUS
          {
          ???/*?任務(wù)句柄*/
          ???TaskHandle_t?xHandle;
          ?
          ???/*?指針,指向任務(wù)名*/
          ???const?signed?char?*pcTaskName;
          ?
          ???/*任務(wù)ID,是一個獨一無二的數(shù)字*/
          ???UBaseType_t?xTaskNumber;
          ?
          ???/*填充結(jié)構(gòu)體時,任務(wù)當(dāng)前的狀態(tài)(運行、就緒、掛起等等)*/
          ???eTaskState?eCurrentState;
          ?
          ???/*填充結(jié)構(gòu)體時,任務(wù)運行(或繼承)的優(yōu)先級。*/
          ???UBaseType_t?uxCurrentPriority;
          ?
          ???/*?當(dāng)任務(wù)因繼承而改變優(yōu)先級時,該變量保存任務(wù)最初的優(yōu)先級。僅當(dāng)configUSE_MUTEXES定義為1有效。*/
          ???UBaseType_t?uxBasePriority;
          ?
          ???/*?分配給任務(wù)的總運行時間。僅當(dāng)宏configGENERATE_RUN_TIME_STATS為1時有效。*/
          ???unsigned?long?ulRunTimeCounter;
          ?
          ???/*?從任務(wù)創(chuàng)建起,堆棧剩余的最小數(shù)量,這個值越接近0,堆棧溢出的可能越大。?*/
          ???unsigned?short?usStackHighWaterMark;
          }TaskStatus_t;

          「注意」,這個函數(shù)僅用來調(diào)試用,調(diào)用此函數(shù)會掛起所有任務(wù),直到函數(shù)最后才恢復(fù)掛起的任務(wù),因此任務(wù)可能被掛起很長時間。在文件FreeRTOSConfig.h中,宏configUSE_TRACE_FACILITY必須設(shè)置為1,此函數(shù)才有效。

          1.2參數(shù)描述

          • 「pxTaskStatusArray」:指向TaskStatus_t類型的結(jié)構(gòu)體數(shù)組。這個數(shù)組至少要包含1個元素。RTOS控制的任務(wù)數(shù)量可以使用API函數(shù)uxTaskGetNumberOfTasks()獲取。
          • 「uxArraySize」:參數(shù)pxTaskStatusArray指向的數(shù)組大小,也就是該數(shù)組的索引數(shù)目。
          • 「pulTotalRunTime」:如果在文件FreeRTOSConfig.h中設(shè)置宏configGENERATE_RUN_TIME_STATS為1,則該函數(shù)將總運行時間寫入*pulTotalRunTime中。pulTotalRunTime可以設(shè)置為NULL,表示忽略總運行時間。

          1.3返回值

          被填充的TaskStatus_t結(jié)構(gòu)體數(shù)量。這個值應(yīng)該等于通過調(diào)用API函數(shù)uxTaskGetNumberOfTasks()返回的值,但如果傳遞給uxArraySize參數(shù)的值太小,則返回0。

          1.4用法舉例

          /*本例演示如是使用uxTaskGetSystemState()函數(shù)來獲取運行時間信息,并將其轉(zhuǎn)化為程序員更易識別的字符格式,這些轉(zhuǎn)化后的字符保存到pcWriteBuffer中。*/
          void?vTaskGetRunTimeStats(signed?char?*pcWriteBuffer?)
          {
          ???TaskStatus_t*pxTaskStatusArray;
          ???volatileUBaseType_t?uxArraySize,?x;
          ???unsignedlong?ulTotalRunTime,?ulStatsAsPercentage;
          ?
          ???/*?防御性代碼,確保字符串有合理的結(jié)束*/
          ??*pcWriteBuffer?=?0x00;
          ?
          ???/*?獲取任務(wù)總數(shù)目*/
          ??uxArraySize?=?uxTaskGetNumberOfTasks?();
          ?
          ???/*為每個任務(wù)的TaskStatus_t結(jié)構(gòu)體分配內(nèi)存,也可以靜態(tài)的分配一個足夠大的數(shù)組?*/
          ??pxTaskStatusArray?=?pvPortMalloc(?uxArraySize?*?sizeof(?TaskStatus_t?));
          ?
          ???if(pxTaskStatusArray?!=?NULL?)
          ???{
          ??????/*獲取每個任務(wù)的狀態(tài)信息?*/
          ?????uxArraySize?=?uxTaskGetSystemState(?pxTaskStatusArray,?uxArraySize,&ulTotalRunTime?);
          ?
          ??????/*?百分比計算?*/
          ?????ulTotalRunTime?/=?100UL;
          ?
          ??????/*?避免除零錯誤?*/
          ??????if(ulTotalRunTime?>?0?)
          ??????{
          ?????????/*?將獲得的每一個任務(wù)狀態(tài)信息部分的轉(zhuǎn)化為程序員容易識別的字符串格式*/
          ????????for(?x?=?0;?x??????????{
          ???????????/*?計算任務(wù)運行時間與總運行時間的百分比。*/
          ???????????ulStatsAsPercentage?=?pxTaskStatusArray[?x?].ulRunTimeCounter?/ulTotalRunTime;
          ?
          ???????????if(?ulStatsAsPercentage?>?0UL?)
          ???????????{
          ??????????????sprintf(?pcWriteBuffer,?"%s\t\t%lu\t\t%lu%%\r\n",
          ????????????????????????????????pxTaskStatusArray[?x?].pcTaskName,
          ????????????????????????????????pxTaskStatusArray[?x?].ulRunTimeCounter,
          ????????????????????????????????ulStatsAsPercentage?);
          ???????????}
          ???????????else
          ???????????{
          ??????????????/*?任務(wù)運行時間不足總運行時間的1%*/
          ??????????????sprintf(?pcWriteBuffer,?"%s\t\t%lu\t\t<1%%\r\n",
          ????????????????????????????????pxTaskStatusArray[?x?].pcTaskName,
          ?????????????????????????????????pxTaskStatusArray[x?].ulRunTimeCounter?);
          ???????????}
          ?
          ???????????pcWriteBuffer?+=?strlen(?(?char?*?)?pcWriteBuffer?);
          ?????????}
          ??????}
          ?
          ??????/*?釋放之前申請的內(nèi)存*/
          ?????vPortFree(?pxTaskStatusArray?);
          ???}
          }

          2.獲取當(dāng)前任務(wù)句柄

          2.1函數(shù)描述

          TaskHandle_t?xTaskGetCurrentTaskHandle(void?);

          在文件FreeRTOSConfig.h中,宏INCLUDE_xTaskGetCurrentTaskHandle必須設(shè)置為1,此函數(shù)才有效。

          2.2返回值

          返回當(dāng)前任務(wù)(調(diào)用該函數(shù)的任務(wù))的句柄。

          3.獲取空閑任務(wù)句柄

          3.1函數(shù)描述

          TaskHandle_t?xTaskGetIdleTaskHandle(void?);

          在文件FreeRTOSConfig.h中,宏INCLUDE_xTaskGetIdleTaskHandle必須設(shè)置為1,此函數(shù)才有效。

          3.2返回值

          返回空閑任務(wù)句柄。空閑任務(wù)在RTOS調(diào)度器啟動時自動創(chuàng)建。

          4.獲取任務(wù)堆棧最大使用深度

          4.1函數(shù)描述

          UBaseType_t?uxTaskGetStackHighWaterMark(?TaskHandle_t?xTask?);

          任務(wù)的堆棧空間會隨著任務(wù)執(zhí)行以及中斷處理而增長或縮小。該函數(shù)可以返回任務(wù)啟動后的最小剩余堆棧空間。

          換句話說,可以間接估算出一個任務(wù)最多需要多少堆棧空間。在文件FreeRTOSConfig.h中,宏INCLUDE_uxTaskGetStackHighWaterMark必須設(shè)置成1,此函數(shù)才有效。

          4.2參數(shù)描述

          • 「xTask」:任務(wù)句柄。NULL表示查看當(dāng)前任務(wù)的堆棧使用情況。

          4.3返回值

          返回最小剩余堆棧空間,以字為單位。

          比如一個32為架構(gòu)處理器,返回值為1表示有4字節(jié)堆棧空間沒有使用過。

          如果返回值為0,則任務(wù)很可能已經(jīng)發(fā)生了堆棧溢出。

          4.4用法舉例

          void?vTask1(?void?*?pvParameters?)
          {
          ???UBaseType_tuxHighWaterMark;

          ???/*?入口處檢測一次?*/
          ???uxHighWaterMark?=uxTaskGetStackHighWaterMark(?NULL?);

          ???for(?;;?)
          ???{
          ???????/*?正常調(diào)用函數(shù)?*/
          ???????vTaskDelay(?1000?);

          ???????/*?測量堆棧使用情況?*/
          ???????uxHighWaterMark?=uxTaskGetStackHighWaterMark(?NULL?);
          ???}
          }

          5.獲取任務(wù)狀態(tài)

          5.1函數(shù)描述

          eTaskState?eTaskGetState(?TaskHandle_txTask?);

          返回一個枚舉類型的任務(wù)狀態(tài)值。在文件FreeRTOSConfig.h中,宏INCLUDE_eTaskGetState必須設(shè)置為1,此函數(shù)才有效。

          5.2參數(shù)描述

          • 「xTask」:任務(wù)句柄

          5.3返回值

          下表列出返回值和對應(yīng)的任務(wù)狀態(tài)。

          6.獲取任務(wù)描述內(nèi)容

          6.1函數(shù)描述

          char?*?pcTaskGetTaskName(?TaskHandle_txTaskToQuery?);

          獲取任務(wù)的描述內(nèi)容,在文件FreeRTOSConfig.h中,宏INCLUDE_pcTaskGetTaskName必須設(shè)置成1,此函數(shù)才有效。

          6.2參數(shù)描述

          • 「xTaskToQuery」:任務(wù)的句柄。NULL表示獲取當(dāng)前任務(wù)的描述內(nèi)容指針。

          6.3返回值

          一個指針,指向任務(wù)描述字符串。

          7.獲取系統(tǒng)節(jié)拍次數(shù)

          7.1函數(shù)描述

          volatile?TickType_t?xTaskGetTickCount(void?);

          這個函數(shù)不能在ISR中調(diào)用。在ISR中用xTaskGetTickCountFromISR(),原型為volatileTickType_t xTaskGetTickCountFromISR( void )

          7.2返回值

          返回從vTaskStartScheduler函數(shù)調(diào)用后的系統(tǒng)時鐘節(jié)拍次數(shù)。

          8.獲取調(diào)度器狀態(tài)

          8.1函數(shù)描述

          BaseType_t?xTaskGetSchedulerState(?void);

          獲取調(diào)度器當(dāng)前狀態(tài)。在文件FreeRTOSConfig.h中,宏INCLUDE_xTaskGetSchedulerStateconfigUSE_TIMERS必須定義為1,此函數(shù)才有效。

          8.2返回值

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

          9.獲取任務(wù)總數(shù)

          9.1函數(shù)描述

          UBaseType_t?uxTaskGetNumberOfTasks(void?);

          獲取RTOS內(nèi)核當(dāng)前管理的任務(wù)總數(shù)。包含所有就緒、阻塞和掛起狀態(tài)的任務(wù)。

          對于一個刪除的任務(wù),如果它的堆棧空間還沒有被空閑任務(wù)釋放掉,則這個被刪除的任務(wù)也含在計數(shù)值中。

          9.2返回值

          返回RTOS內(nèi)核當(dāng)前管理的任務(wù)總數(shù)。

          10.獲取所有任務(wù)詳情

          10.1函數(shù)描述

          void?vTaskList(?char?*pcWriteBuffer?);

          將每個任務(wù)的狀態(tài)、堆棧使用情況等以字符的形式保存到參數(shù)pcWriteBuffer指向的區(qū)域。

          vTaskList()函數(shù)調(diào)用usTaskGetSystemState()函數(shù),然后將得到的信息格式化為程序員易讀的字符形式。

          輸出的內(nèi)容例子如下圖所示,圖中State一欄中,B表示阻塞、R表示就緒、D表示刪除(等待清除內(nèi)存)、S表示掛起或阻塞。

          「注意」,調(diào)用這個函數(shù)會掛起所有任務(wù),這一過程可能持續(xù)較長時間,因此本函數(shù)僅在調(diào)試時使用。在文件FreeRTOSConfig.h中,宏configUSE_TRACE_FACILITYconfigUSE_STATS_FORMATTING_FUNCTIONS必須定義為1,此函數(shù)才有效。

          10.2參數(shù)描述

          • 「pcWriteBuffer」:任務(wù)的信息會寫入這個緩沖區(qū),為ASCII表單形式。這個緩沖區(qū)要足夠大,以容納生成的報告,每個任務(wù)大約需要40個字節(jié)。

          11.獲取任務(wù)運行時間

          11.1函數(shù)描述

          void?vTaskGetRunTimeStats(?char*pcWriteBuffer?);

          這個函數(shù)用于統(tǒng)計每個任務(wù)的運行時間。要使用這個函數(shù)必須滿足一些條件,那就是必須有一個用于時間統(tǒng)計的定時器或計數(shù)器,這個定時器或計數(shù)器的精度要至少大于10倍的系統(tǒng)節(jié)拍周期。

          這個定時器或計數(shù)器的配置以及獲取定時時間是由兩個宏定義實現(xiàn)的,這兩個宏一般在文件FreeRTOSConfig.h中定義。

          配置定時器或計數(shù)器的宏為portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(),獲取定時時間的宏為portGET_RUN_TIME_COUNTER_VALUE

          實現(xiàn)了這兩個宏定義后,還必須在文件FreeRTOSConfig.h中將宏configGENERATE_RUN_TIME_STATSconfigUSE_STATS_FORMATTING_FUNCTIONS設(shè)置為1,此API函數(shù)才有效。

          這個API函數(shù)調(diào)用usTaskGetSystemState()函數(shù)獲取每個任務(wù)的狀態(tài)信息,并把其中的運行時間格式化為程序員易讀的字符形式,并將這些信息保存到參數(shù)pcWriteBuffer指向的區(qū)域。

          「注意」,調(diào)用這個函數(shù)會掛起所有任務(wù),這一過程可能持續(xù)較長時間,因此本函數(shù)僅在調(diào)試時使用。

          11.2參數(shù)描述

          • 「pcWriteBuffer」:任務(wù)的運行時間信息會寫入這個緩沖區(qū),為ASCII表單形式。這個緩沖區(qū)要足夠大,以容納生成的報告,每個任務(wù)大約需要40個字節(jié)。

          11.3用法舉例

          「lpc17xx系列」為控制為例,我們使用定時器0來作為統(tǒng)計基準(zhǔn)時鐘。

          11.3.1使能函數(shù)宏

          在文件FreeRTOSConfig.h中,設(shè)置宏configGENERATE_RUN_TIME_STATSconfigUSE_STATS_FORMATTING_FUNCTIONS為1,

          11.3.2定時初始化定時器代碼

          void?vConfigureTimerForRunTimeStats(?void?)
          {
          ????/*?使能定時器0的外設(shè)電源,配置外設(shè)時鐘?*/
          ????PCONP?|=?0x02UL;
          ????PCLKSEL0?=?(PCLKSEL0&?(~(0x3<<2)))?|?(0x01?<?
          ????/*?復(fù)位定時器?0?*/
          ????T0TCR?=?0x02;
          ?
          ????/*?作為計數(shù)器?*/
          ????T0CTCR?=?0x00;
          ?
          ????/*?預(yù)分頻,設(shè)置合適的分辨率即可?*/
          ????T0PR?=??(?configCPU_CLOCK_HZ?/?10000UL?)?-?1UL;
          ?
          ????/*?啟動計數(shù)器?*/
          ????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.設(shè)置任務(wù)標(biāo)簽值

          12.1函數(shù)描述

          voidvTaskSetApplicationTaskTag(?TaskHandle_t?xTask,
          ????????????????TaskHookFunction_tpxTagValue?);

          可以給每個任務(wù)分配一個標(biāo)簽值。這個值一般用于應(yīng)用程序,RTOS內(nèi)核不會使用。

          在文件FreeRTOSConfig.h中,宏configUSE_APPLICATION_TASK_TAG必須設(shè)置為1,此函數(shù)才有效。

          12.2參數(shù)描述

          • 「xTask」:任務(wù)句柄。NULL表示當(dāng)前任務(wù)。
          • 「pxTagValue」:要分配給任務(wù)的標(biāo)簽值。這是一個TaskHookFunction_t類型的函數(shù)指針,但也可以給任務(wù)標(biāo)簽分配任意的值。

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

          12.3用法舉例

          /*?在這個例子中,給任務(wù)設(shè)置一個整形標(biāo)簽值。例子中使用了RTOS跟蹤鉤子宏。*/
          void?vATask(?void?*pvParameters?)
          {
          ??/*?為自己的標(biāo)簽分配一個整形值?*/
          ?vTaskSetApplicationTaskTag(?NULL,?(?void?*?)?1?);
          ?
          ??for(?;;?)
          ??{
          ????/*?任務(wù)主體代碼?*/
          ??}
          }
          /*****************************************************************************/
          ?
          /*在這個任務(wù)中,給任務(wù)設(shè)置一個函數(shù)標(biāo)簽值。首先定義一個回調(diào)函數(shù),這個函數(shù)必須聲明為TaskHookFunction_t類型。?*/
          static?BaseType_t?prvExampleTaskHook(?void?*?pvParameter?)
          {
          ??/*?這里為用戶定義代碼?–可能是記錄數(shù)據(jù)、更新任務(wù)狀態(tài)值等。*/
          ?
          ??return?0;
          }
          ?
          /*?將回調(diào)函數(shù)設(shè)置為任務(wù)的標(biāo)簽值。?*/
          void?vAnotherTask(?void?*pvParameters?)
          {
          ??/*?注冊回調(diào)函數(shù)*/
          ?vTaskSetApplicationTaskTag(?NULL,?prvExampleTaskHook?);
          ?
          ??for(?;;?)
          ??{
          ?????/*?任務(wù)主體代碼?*/
          ??}
          }
          ?
          /*?每當(dāng)任務(wù)切換時,會調(diào)用xTaskCallApplicationTaskHook 函數(shù)(見14.)。?*/
          #define?traceTASK_SWITCHED_OUT()?xTaskCallApplicationTaskHook(pxCurrentTCB,0?)

          13.獲取任務(wù)標(biāo)簽值

          13.1函數(shù)描述

          TaskHookFunction_txTaskGetApplicationTaskTag(?TaskHandle_t?xTask?);

          返回分配給任務(wù)的標(biāo)簽值。程序員定義標(biāo)簽值,RTOS內(nèi)核通常不會訪問標(biāo)簽值。

          函數(shù)僅對高級用戶使用。在文件FreeRTOSConfig.h中,宏configUSE_APPLICATION_TASK_TAG必須設(shè)置為1,此函數(shù)才有效。

          13.2參數(shù)描述

          • 「xTask」:任務(wù)句柄。NULL表示當(dāng)前任務(wù)。

          13.3返回值

          返回指定任務(wù)的標(biāo)簽值。

          14.執(zhí)行任務(wù)的應(yīng)用鉤子函數(shù)

          14.1函數(shù)描述

          BaseType_txTaskCallApplicationTaskHook(
          ?????????????????????????TaskHandle_txTask,
          ?????????????????????????void*pvParameter?);

          可以為每個任務(wù)分配一個標(biāo)簽值,當(dāng)這個值是一個TaskHookFunction_t類型函數(shù)指針時,相當(dāng)于應(yīng)用程序向任務(wù)注冊了一個回調(diào)函數(shù),而API函數(shù)xTaskCallApplicationTaskHook用來調(diào)用這個回調(diào)函數(shù)。

          一般這個函數(shù)配合RTOS跟蹤鉤子宏使用,見12.設(shè)置任務(wù)標(biāo)簽值一節(jié)的用法舉例。

          14.2參數(shù)描述

          • 「xTask」:任務(wù)句柄。NULL表示當(dāng)前任務(wù)。
          • 「pvParameter」:作為參數(shù)傳遞給應(yīng)用鉤子函數(shù)

          15.設(shè)置線程本地存儲指針

          15.1函數(shù)描述

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

          此函數(shù)僅用于高級用戶。

          線程本地存儲允許應(yīng)用程序在任務(wù)的控制塊中存儲一些值,每個任務(wù)都有自己獨立的儲存空間。

          比如,許多庫函數(shù)都包含一個叫做errno的全局變量。某些庫函數(shù)使用errno返回庫函數(shù)錯誤信息,應(yīng)用程序檢查這個全局變量來確定發(fā)生了那些錯誤。

          在單線程程序中,將errno定義成全局變量是可以的,但是在多線程應(yīng)用中,每個線程(任務(wù))必須具有自己獨有的errno值,否則,一個任務(wù)可能會讀取到另一個任務(wù)的errno值。

          FreeRTOS提供了一個靈活的機(jī)制,使得應(yīng)用程序可以使用線程本地存儲指針來讀寫線程本地存儲。

          在文件FreeRTOSConfig.h中,宏configNUM_THREAD_LOCAL_STORAGE_POINTERS指定每個任務(wù)線程本地存儲指針數(shù)組的大小。

          API函數(shù)vTaskSetThreadLocalStoragePointer()用于向指針數(shù)組中寫入值,API函數(shù)pvTaskGetThreadLocalStoragePointer()用于從指針數(shù)組中讀取值。

          15.2參數(shù)描述

          • 「xTaskToSet」:任務(wù)句柄。NULL表示當(dāng)前任務(wù)。
          • 「xIndex」:寫入到線程本地存儲數(shù)組的索引號,線程本篤存儲數(shù)組的大小由宏configNUM_THREAD_LOCAL_STORAGE_POINTERS設(shè)定,該宏在文件FreeRTOSConfig.h中。
          • 「pvValue」:寫入到指定索引地址的數(shù)據(jù)值

          15.3用法舉例

          參見16.獲取線程本地存儲指針一節(jié)。

          16.讀取線程本地存儲指針

          16.1函數(shù)描述

          void*pvTaskGetThreadLocalStoragePointer(
          ???????????????????????TaskHandle_txTaskToQuery,
          ???????????????????????BaseType_txIndex?);

          此函數(shù)僅用于高級用戶。從線程本地存儲指針數(shù)組中讀取值。更詳細(xì)描述見15.設(shè)置線程本地存儲指針一節(jié)。

          16.2參數(shù)描寫

          • 「xTaskToQuery」:任務(wù)句柄。NULL表示當(dāng)前任務(wù)。
          • 「xIndex」:寫入到線程本地存儲數(shù)組的索引號,線程本篤存儲數(shù)組的大小由宏configNUM_THREAD_LOCAL_STORAGE_POINTERS設(shè)定,該宏在文件FreeRTOSConfig.h中。

          16.3返回值

          返回一個指針,這個指針存儲在線程本地存儲指針數(shù)組中,數(shù)組索引由參數(shù)xIndex指定。

          16.4用法舉例

          16.4.1存儲一個整形數(shù)

          uint32_tulVariable;
          ?
          /*?向當(dāng)前任務(wù)的線程本地存儲數(shù)組下標(biāo)為1的位置寫入一個指向32位常量值的指針。*/
          vTaskSetThreadLocalStoragePointer(NULL,?1,?(?void?*?)?0x12345678?);
          ?
          /*向當(dāng)前任務(wù)的線程本地存儲數(shù)組下標(biāo)為0的位置寫入一個指向32整形值的指針*/
          ulVariable=?ERROR_CODE;
          vTaskSetThreadLocalStoragePointer(NULL,?0,?(?void?*?)?ulVariable?);
          ?
          /*從當(dāng)前任務(wù)的線程本地存儲數(shù)組下標(biāo)為5的位置讀取出一個指針并賦值給32位整形變量。*/
          ulVariable=?(?uint32_t?)?pvTaskGetThreadLocalStoragePointer(?NULL,?5?);

          16.4.2存儲結(jié)構(gòu)提

          typedefstruct
          {
          ????uint32_t?ulValue1;
          ????uint32_t?ulValue2;
          }xExampleStruct;
          ?
          xExampleStruct*pxStruct;
          ?
          /*為結(jié)構(gòu)體分配內(nèi)存*/
          pxStruct=?pvPortMalloc(?sizeof(?xExampleStruct?)?);
          ?
          /*為結(jié)構(gòu)體成員賦值*/
          pxStruct->ulValue1=?0;
          pxStruct->ulValue2=?1;
          ?
          /*向當(dāng)前任務(wù)的線程本地存儲數(shù)組下標(biāo)為0的位置寫入一個指向結(jié)構(gòu)體變量的指針*/
          vTaskSetThreadLocalStoragePointer(NULL,?0,?(?void?*?)?pxStruct?);
          ?
          /*從當(dāng)前任務(wù)的線程本地存儲數(shù)組下標(biāo)為0的位置讀取出一個結(jié)構(gòu)體指針*/
          pxStruct=?(?xExampleStruct?*?)?pvTaskGetThreadLocalStoragePointer(?NULL,?0?);

          17.設(shè)置超時狀態(tài)

          17.1函數(shù)描述

          void?vTaskSetTimeOutState(?TimeOut_t?*const?pxTimeOut?);

          此函數(shù)僅用于高級用戶,通常與API函數(shù)xTaskCheckForTimeOut()共同使用。

          任務(wù)因為等待某事件而進(jìn)入阻塞狀態(tài),通常情況下任務(wù)會設(shè)置一個等待超時周期。如果在等待事件超時,任務(wù)會退出阻塞狀態(tài)。

          想象一個這樣的應(yīng)用,某任務(wù)等待一個事件而進(jìn)入阻塞狀態(tài),但是事件遲遲不發(fā)生,超時后任務(wù)退出阻塞狀態(tài)繼續(xù)執(zhí)行任務(wù)。

          假如任務(wù)等待的事件仍然沒有發(fā)生,則任務(wù)又會阻塞在該事件下。

          只要任務(wù)等待的事件一直不發(fā)生,這個任務(wù)進(jìn)入阻塞然后超時退出阻塞,再進(jìn)入阻塞的循環(huán)就會一直存在。

          是不是可以設(shè)定一個總超時時間,只要總阻塞時間大于這個總超時時間,則可以結(jié)束這個任務(wù)或進(jìn)行相應(yīng)記錄?

          freeRTOS提供了兩個API函數(shù)來完成這個功能,這就是vTaskSetTimeOutState()xTaskCheckForTimeOut()

          vTaskSetTimeOutState()函數(shù)用于設(shè)置初始條件,之后調(diào)用xTaskCheckForTimeOut()函數(shù)檢查任務(wù)總阻塞時間是否超過總超時時間,如果沒有超過,則調(diào)整剩余的超時時間計數(shù)器。

          17.2參數(shù)描述

          • 「pxTimeOut」:指向一個結(jié)構(gòu)體的指針,該結(jié)構(gòu)體用來保存確定超時是否發(fā)生的必要信息。vTaskSetTimeOutState()函數(shù)會設(shè)置結(jié)構(gòu)體的成員。

          17.3用法舉例

          參見18.超時檢測。

          18.超時檢測

          18.1函數(shù)描述

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

          此函數(shù)僅用于高級用戶,通常與API函數(shù)vTaskSetTimeOutState共同使用。

          詳細(xì)描述見17.設(shè)置超時狀態(tài)。

          18.2參數(shù)描述

          • 「pxTimeOut」:指向一個結(jié)構(gòu)體的指針。該結(jié)構(gòu)體保存確定超時是否發(fā)生的必要信息。使用API函數(shù)vTaskSetTimeOutState初始化該結(jié)構(gòu)體。
          • 「pxTicksToWait」TickType_t指針,指向的變量保存總超時時間。

          18.3返回值

          • 「pdTRUE」:總超時發(fā)生
          • 「pdFALSE」:總超時未發(fā)生

          18.4用法舉例

          /*?函數(shù)用于從RX緩沖區(qū)中接收uxWantedBytes字節(jié)數(shù)據(jù),RX緩沖區(qū)由UART中斷填充。如果RX緩沖區(qū)沒有足夠的數(shù)據(jù),則任務(wù)進(jìn)入阻塞狀態(tài),直到RX緩沖區(qū)有足夠數(shù)據(jù)或者發(fā)生超時。如果超時后仍然沒有足夠的數(shù)據(jù),則任務(wù)會再次進(jìn)入阻塞狀態(tài),xTaskCheckForTimeOut()函數(shù)用于重新計算總超時時間以確保總阻塞狀態(tài)時間不超過MAX_TIME_TO_WAIT。如果總阻塞狀態(tài)時間大于了總超時時間,則不管RX緩沖區(qū)是否有充足數(shù)據(jù),都將這些數(shù)據(jù)讀出來。
          ?*/
          size_txUART_Receive(?uint8_t?*pucBuffer,?size_t?uxWantedBytes?)
          {
          ????size_t?uxReceived?=?0;
          ????TickType_t?xTicksToWait?=?MAX_TIME_TO_WAIT;
          ????TimeOut_t?xTimeOut;
          ?
          ???/*?初始化結(jié)構(gòu)體變量xTimeOut。*/
          ???vTaskSetTimeOutState(?&xTimeOut?);
          ?
          ???/*?無限循環(huán),直到緩沖區(qū)包含足夠的數(shù)據(jù)或者阻塞超時發(fā)生。*/
          ???while(?UART_bytes_in_rx_buffer(pxUARTInstance?)????{
          ??????/* RX緩沖區(qū)沒有足夠多的數(shù)據(jù),表示任務(wù)已經(jīng)進(jìn)入過一次阻塞狀態(tài)。調(diào)用API函數(shù)xTaskCheckForTimeOut檢查總阻塞時間是否超過總超時時間,如果沒有,則調(diào)整剩余的總超時時間。*/
          ??????if(?xTaskCheckForTimeOut(?&xTimeOut,&xTicksToWait?)?!=?pdFALSE?)
          ??????{
          ?????????/*?如果總阻塞時間大于總超時時間,則退出這個循環(huán)?*/
          ?????????break;
          ??????}
          ?
          ??????/*?在等待了xTicksToWait個系統(tǒng)節(jié)拍周期后,向接收中斷發(fā)出通知,需要更多數(shù)據(jù)。
          */


          ??????ulTaskNotifyTake(?pdTRUE,?xTicksToWait?);
          ???}
          ?
          ????/*從RX緩沖區(qū)讀取uxWantedBytes個字節(jié)并放到pucBuffer緩沖區(qū)。*/
          ????uxReceived?=?UART_read_from_receive_buffer(pxUARTInstance,??pucBuffer,??uxWantedBytes?);
          ?
          ????return?uxReceived;
          }
          推薦閱讀:

          嵌入式編程專輯

          Linux 學(xué)習(xí)專輯

          C/C++編程專輯

          關(guān)注微信公眾號『技術(shù)讓夢想更偉大』,后臺回復(fù)“m”查看更多內(nèi)容,回復(fù)“加群”加入技術(shù)交流群。

          長按前往圖中包含的公眾號關(guān)注

          瀏覽 86
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  a 在线天堂| 国产一卡二卡在线 | 日韩小电影在线观看 | 亚洲视频免费完整版在线播放 | 台湾午夜视频 |