第18章 FreeRTOS 事件標誌組


目錄

18.1 事件標誌組

18.1.1 爲什麼要 使用事件標誌

18.1.2 F reeRTOS 任務 間 事件標誌組的實現 

18.1.3 F reeRTOS 中斷 方式事件標誌 組 的實現

18.2 事件標誌組 API 函數

18.2.1 函數 xEventGroupCreate

18.2.2 函數 xEventGroupCreateStatic

18.2.3 函 數 vEventGroupDelete

18.2.4 函 數 xEventGroupSetBits

18.2.5 函數 xEventGroupSetBitsFromISR

18.2.6 函數 xEventGroupWaitBits

18.2.7 函數 xEventGroupClearBits

18.2.8 函數 xEventGroupClearBitsFromISR

18.2.9 函數 xEventGroupGetBits

18.2.10 函數 xEventGroupGetBitsFromISR

18.2.11 函數 xEventGroupSync



前面的章節我們已經講解了任務管理和時間管理,從本章節開始講解任務間的通信和同步機制。首先講解任務間的通信和同步機制之一,事件標誌組。

18.1 事件標誌組

18.1.1 爲什麼要 使用事件標誌

事件標誌組是實現多任務同步的有效機制之一。也許有不理解的初學者會問採用事件標誌組多麻煩,搞個全局變量不是更簡單?其實不然,在裸機編程時,使用全局變量的確比較方便,但是在加上RTOS後就是另一種情況了。使用全局變量相比事件標誌組主要有如下三個問題:

  1.  使用事件標誌組可以讓RTOS內核有效地管理任務,而全局變量是無法做到的,任務的超時等機制需要用戶自己去實現。
  2.  使用了全局變量就要防止多任務的訪問衝突,而使用事件標誌組則處理好了這個問題,用戶無需擔心。
  3.  使用事件標誌組可以有效地解決中斷服務程序和任務之間的同步問題。

18.1.2 F reeRTOS 任務 間 事件標誌組的實現 

任務間事件標誌組的實現是指各個任務之間使用事件標誌組實現任務的通信或者同步機制。 下面我們來說說FreeRTOS中事件標誌的實現,根據用戶在FreeRTOSConfig.h文件中的配置:

  •  #define configUSE_16_BIT_TICKS 1 配置宏定義configUSE_16_BIT_TICKS爲1時,每創建一個事件標誌組,用戶可以使用的事件標誌是8個。
  •  #define configUSE_16_BIT_TICKS 0

配置宏定義configUSE_16_BIT_TICKS爲0時,每創建一個事件標誌組,用戶可以使用的事件標誌是24個。 上面說的8個和24個事件標誌應該怎麼理解呢?其實就是定義了一個16位變量,僅使用了低8bit或者定義了一個32位變量,僅使用了低24bit。每一個bit用0和1兩種狀態來代表事件標誌。反映到FreeRTOS上就是將事件標誌存儲到了EventBits_t類型的變量中,這個變量又是怎麼回事呢?定義如下:

/*
* The type that holds event bits always matches TickType_t therefore the
* number of bits it holds is set by configUSE_16_BIT_TICKS (16 bits if set to
* 32 bits if set to 0.
* defgroup EventBits_t EventBits_t
* ingroup EventGroup
typedef TickType_t EventBits_t;

進一步跟蹤TickType_t的數據類型,定義如下:

#if( configUSE_16_BIT_TICKS == 1 )
    typedef uint16_t TickType_t;
    #define portMAX_DELAY ( TickType_t ) 0xffff
#else
    typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
    /* 32 bit tick type on a 32 bit architecture, so reads of the tick count do
    not need to be guarded with a critical section. */
    #define portTICK_TYPE_IS_ATOMIC 1
#endif

由上面定義可以看出,TickType_t數據類型可以是16位數或者32位數,這樣就跟上面剛剛說的configUSE_16_BIT_TICKS 宏定義呼應上了。教程配套的例子都是配置宏定義configUSE_16_BIT_TICKS 爲0,即用戶每創建一個事件標誌組,有24個標誌可以設置。如下圖所示,這裏僅使用bit0,bit1和bit2。

注意:後面的講解中,默認全是創建一個事件標誌,支持24個事件標誌設置。 下面我們通過如下的框圖來說明一下FreeRTOS事件標誌的實現,讓大家有一個形象的認識。

運行條件:

  •  創建2個任務:Task1和Task2

運行過程描述如下:

  •  任務Task1運行過程中調用函數xEventGroupWaitBits,等待事件標誌位被設置,任務Task1由運行態進入到阻塞態。
  •  任務Task2設置Task1等待的事件標誌,任務Task1由阻塞態進入到就緒態,在調度器的作用下由就緒態又進入到運行態。

上面就是一個簡單的FreeRTOS任務間事件標誌通信過程。

18.1.3 F reeRTOS 中斷 方式事件標誌 組 的實現

FreeRTOS中斷方式事件標誌組的實現是指中斷函數和FreeRTOS任務之間使用事件標誌。下面我們通過如下的框圖來說明一下FreeRTOS事件標誌的實現,讓大家有一個形象的認識。

運行條件:  創建一個任務和一個串口接收中斷

運行過程描述如下:

  1.  任務Task1運行過程中調用函數xEventGroupWaitBits,等待事件標誌位被設置,任務Task1由運行態進入到阻塞態。
  2.  Task1阻塞的情況下,串口接收到數據進入到了串口中斷服務程序,在串口中斷服務程序中設置Task1等待的事件標誌,任務Task1由阻塞態進入到就緒態,在調度器的作用下由就緒態又進入到運行態。

上面就是一個簡單的FreeRTOS中斷方式事件標誌通信過程。實際應用中,中斷方式的消息機制要注意以下四個問題:

  1.  中斷函數的執行時間越短越好,防止其它低於這個中斷優先級的異常不能得到及時響應。
  2.  實際應用中,建議不要在中斷中實現消息處理,用戶可以在中斷服務程序裏面發送消息通知任務,在任務中實現消息處理,這樣可以有效地保證中斷服務程序的實時響應。同時此任務也需要設置爲高優先級,以便退出中斷函數後任務可以得到及時執行。
  3.  中斷服務程序中一定要調用專用於中斷的事件標誌設置函數,即以FromISR結尾的函數。
  4.  在操作系統中實現中斷服務程序與裸機編程的區別。

 如果FreeRTOS工程的中斷函數中沒有調用FreeRTOS的事件標誌組API函數,與裸機編程是一樣的。

 如果FreeRTOS工程的中斷函數中調用了FreeRTOS的事件標誌組的API函數,退出的時候要檢測是否有高優先級任務就緒,如果有就緒的,需要在退出中斷後進行任務切換,這點跟裸機編程稍有區別,詳見18.4小節實驗例程說明(中斷方式):

 另外強烈推薦用戶將Cortex-M3內核的STM32F103和Cortex-M4內核的STM32F407,F429的NVIC優先級分組設置爲4,即:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);這樣中斷優先級的管理將非常方便。

 用戶要在FreeRTOS多任務開啓前就設置好優先級分組,一旦設置好切記不可再修改。

18.2 事件標誌組 API 函數

使用如下11個函數可以實現FreeRTOS的事件標誌組:

  •  xEventGroupCreate()
  •  xEventGroupCreateStatic()
  •  vEventGroupDelete()
  •  xEventGroupWaitBits()
  •  xEventGroupSetBits()
  •  xEventGroupSetBitsFromISR()
  •  xEventGroupClearBits()
  •  xEventGroupClearBitsFromISR()
  •  xEventGroupGetBits()
  •  xEventGroupGetBitsFromISR()
  •  xEventGroupSync()

 

18.2.1 函數 xEventGroupCreate

EventGroupHandle_t xEventGroupCreate(void);

創建一個新的RTOS 事件組,並返回一個句柄,通過它可以引用新創建的事件組。

要使此RTOS API函數可用:

  1. 必須在FreeRTOSConfig.h 中將configSUPPORT_DYNAMIC_ALLOCATION設置爲1,或者未定義(在這種情況下,它將默認爲1)。
  2. RTOS源文件FreeRTOS / source / event_groups.c必須包含在構建中。

每個事件組都需要[非常]少量的RAM,用於保留事件組的狀態。如果使用xEventGroupCreate()創建事件組,則將從FreeRTOS堆中自動分配所需的RAM 。如果使用xEventGroupCreateStatic()創建事件組,則RAM由應用程序編寫器提供,它需要一個附加參數,但允許在編譯時靜態分配RAM。有關更多信息,請參見靜態與動態分配頁面。

事件組存儲在EventBits_t類型的變量中。如果將configUSE_16_BIT_TICKS設置爲1,則在事件組內實現的位數(或標誌)爲8;如果將configUSE_16_BIT_TICKS設置爲0,則爲24。對configUSE_16_BIT_TICKS的依賴性是由於在內部實現中用於線程本地存儲的數據類型RTOS任務。

參數:

沒有    

返回值:

如果創建了事件組,則返回事件組的句柄。如果FreeRTOS堆不足以 創建事件組,則返回NULL。

用法示例:

    /* Declare a variable to hold the created event group. */
    EventGroupHandle_t xCreatedEventGroup;

    /* Attempt to create the event group. */
    xCreatedEventGroup = xEventGroupCreate();

    /* Was the event group created successfully? */
    if( xCreatedEventGroup == NULL )
    {
        /* The event group was not created because there was insufficient
        FreeRTOS heap available. */
    }
    else
    {
        /* The event group was created. */
    }

 

 18.2.2 函數 xEventGroupCreateStatic


EventGroupHandle_t xEventGroupCreateStatic(
                              StaticEventGroup_t * pxEventGroupBuffer);

創建一個新的RTOS 事件組,並返回一個句柄,通過它可以引用新創建的事件組。 必須在FreeRTOSConfig.h 中將configSUPPORT_STATIC_ALLOCATION設置爲1,並且必須將RTOS源文件FreeRTOS / source / event_groups.c包含在構建中,以便xEventGroupCreateStatic()函數可用。

每個事件組都需要[非常]少量的RAM,用於保留事件組的狀態。如果使用xEventGroupCreate()創建事件組,則將 從FreeRTOS堆中自動分配所需的RAM 。如果使用xEventGroupCreateStatic()創建事件組,則RAM由應用程序編寫器提供,它需要一個附加參數,但允許在編譯時靜態分配RAM。有關更多信息,請參見靜態與動態分配頁面。

事件組存儲在EventBits_t類型的變量中。如果將configUSE_16_BIT_TICKS設置爲1,則在事件組內實現的位數(或標誌)爲8;如果將configUSE_16_BIT_TICKS設置爲0,則爲24。對configUSE_16_BIT_TICKS的依賴性是由於在內部實現中用於線程本地存儲的數據類型RTOS任務。

參數:

pxEventGroupBuffer   必須指向StaticEventGroup_t類型的變量,事件組數據結構將存儲在該變量中。

返回值:

如果事件組創建成功,則返回事件組的句柄。如果pxEventGroupBuffer爲NULL,則返回NULL。

用法示例: 

     /* Declare a variable to hold the handle of the created event group. */
    EventGroupHandle_t xEventGroupHandle;

    /* Declare a variable to hold the data associated with the created
    event group. */
    StaticEventGroup_t xCreatedEventGroup;

    /* Attempt to create the event group. */
    xEventGroupHandle = xEventGroupCreateStatic( &xCreatedEventGroup );

    /* pxEventGroupBuffer was not null so expect the event group to have
    been created? */
    configASSERT( xEventGroupHandle );

 

18.2.3 函 數 vEventGroupDelete


void vEventGroupDelete(EventGroupHandle_t xEventGroup);

刪除以前使用xEventGroupCreate()調用創建的事件組。

在要刪除的事件組上被阻止的任務將被取消阻止,並報告事件組值爲0。

RTOS源文件FreeRTOS / source / event_groups.c必須包含在構建中,以便vEventGroupDelete()函數可用。

不能從中斷中調用此函數。

參數:

xEventGroup   事件組被刪除。

返回值:

沒有。

 

18.2.4 函 數 xEventGroupSetBits

函數原型: EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToSet ); 
函數描述: 函數xEventGroupSetBits用於設置指定的事件標誌位爲1。

 第1個參數是事件標誌組句柄。

 第2個參數表示24個可設置的事件標誌位,EventBits_t是定義的32位變量(詳解18.1.2小節說明),低24位用於事件標誌設置。變量uxBitsToSet的低24位的某個位設置爲1,那麼被設置的事件標誌組的相應位就設置爲1。變量uxBitsToSet設置爲0的位對事件標誌相應位沒有影響。比如設置變量uxBitsToSet = 0x0003就表示將事件標誌的位0和位1設置爲1,其餘位沒有變化。

 返回當前的事件標誌組數值。

使用這個函數要注意以下問題:

1. 使用前一定要保證事件標誌組已經通過函數xEventGroupCreate創建了。

2. 此函數是用於任務代碼中調用的,故不可以在中斷服務程序中調用此函數,中斷服務程序中使用的是 xEventGroupSetBitsFromISR

3. 用戶通過參數uxBitsToSet設置的標誌位並不一定會保留到此函數的返回值中,下面舉兩種情況:

a. 調用此函數的過程中,其它高優先級的任務就緒了,並且也修改了事件標誌,此函數返回的事件標誌位會發生變化。

b. 調用此函數的任務是一個低優先級任務,通過此函數設置了事件標誌後,讓一個等待此事件標誌的高優先級任務就緒了,會立即切換到高優先級任務去執行,相應的事件標誌位會被函數xEventGroupWaitBits清除掉,等從高優先級任務返回到低優先級任務後,函數xEventGroupSetBits的返回值已經被修改。 使用舉例:

#define BIT_0	( 1 << 0 )
#define BIT_4	( 1 << 4 )

void aFunction( EventGroupHandle_t xEventGroup )
{
  EventBits_t uxBits;

  /* 在xEventGroup中設置位0和位4。*/
  uxBits = xEventGroupSetBits(
                              xEventGroup,    /* 正在更新的事件組。 */
                              BIT_0 | BIT_4 );/* 正在設置的位。 */

  if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
  {
      /* 當函數返回時,位0和位4都保持設置。 */
  }
  else if( ( uxBits & BIT_0 ) != 0 )
  {
      /* 當函數返回時,位0保持設置,但位4被清除。
         可能是由於等待位4的任務已從阻止狀態中刪除,位4被自動清除。 */
  }
  else if( ( uxBits & BIT_4 ) != 0 )
  {
      /* 當函數返回時,位4保持設置,但位0被清除。
         可能是位0被自動清除,因爲等待位0的任務已從阻止狀態中刪除。 */
  }
  else
  {
      /* 第0位和第4位均未設置。可能是某個任務正在等待設置這兩個位,
         當任務離開阻塞狀態時,這些位被清除。 */
  }
}

 

18.2.5 函數 xEventGroupSetBitsFromISR

 

 BaseType_t xEventGroupSetBitsFromISR(
                          EventGroupHandle_t xEventGroup,
                          const EventBits_t uxBitsToSet,
                          BaseType_t * pxHigherPriorityTaskWoken);

在RTOS 事件組內設置位(標誌)。可以從中斷服務程序(ISR)調用的xEventGroupSetBits()版本。

在事件組中設置位將自動解除阻止等待這些位的任務。

在事件組中設置位不是確定性操作,因爲可能有未知數量的任務正在等待設置一個或多個位。FreeRTOS不允許在中斷或關鍵部分執行不確定的操作。因此,xEventGroupSetBitFromISR()向RTOS守護程序任務發送一條消息,以在守護程序任務的上下文中執行設置操作-在此任務中,使用調度程序鎖代替關鍵節。

注意:如上段所述,來自ISR的設置位會將設置操作延遲到RTOS daemon任務(也稱爲計時器服務任務)。與其他任何RTOS任務一樣,RTOS daemon 任務是根據其優先級安排的。因此,如果必須立即完成設置操作(在執行由應用程序創建的任務之前),則RTOS daemon 任務的優先級必須高於使用事件組的任何應用程序任務的優先級。RTOS daemon 任務的優先級由 FreeRTOSConfig.h中的configTIMER_TASK_PRIORITY定義設置 。

必須將FreeRTOSConfig.h中的INCLUDE_xEventGroupSetBitFromISR,configUSE_TIMERS和INCLUDE_xTimerPendFunctionCall都設置爲1,才能使xEventGroupSetBitsFromISR()函數可用。

RTOS源文件FreeRTOS / source / event_groups.c必須包含在構建中,以便xEventGroupSetBitsFromISR()函數可用。

參數:

xEventGroup   將在其中設置位的事件組。必須事先通過調用xEventGroupCreate()創建事件組 。
uxBitsToSet   指示要設置的一個或多個位的按位值。例如,將uxBitsToSet設置爲0x08僅設置第3位。將uxBitsToSet設置爲0x09設置第3位和第0位。
pxHigherPriorityTaskWoken   如上所述,調用此函數將導致消息發送到RTOS daemon 任務。如果 daemon 任務的優先級高於當前正在運行的任務(中斷被中斷的任務)的優先級,則xEventGroupSetBitsFromISR()會將* pxHigherPriorityTaskWoken設置爲pdTRUE,指示應在中斷退出之前請求上下文切換。因此,必須將* pxHigherPriorityTaskWoken初始化爲pdFALSE。請參見下面的示例代碼。

返回值:

如果消息已發送到RTOS daemon 任務,則返回pdPASS,否則返回pdFAIL。如果計時器服務隊列已滿,則將返回pdFAIL 。

用法示例:

#define BIT_0    ( 1 << 0 )
#define BIT_4    ( 1 << 4 )

/*假定已通過調用 xEventGroupCreate() */
EventGroupHandle_t xEventGroup;

void anInterruptHandler( void )
{
  BaseType_t xHigherPriorityTaskWoken, xResult;

  /* xHigherPriorityTaskWoken必須初始化爲pdFALSE. */
  xHigherPriorityTaskWoken = pdFALSE;

  /* Set bit 0 and bit 4 in xEventGroup. */
  xResult = xEventGroupSetBitsFromISR(
                              xEventGroup,   /* The event group being updated. */
                              BIT_0 | BIT_4, /* The bits being set. */
                              &xHigherPriorityTaskWoken );

  /* Was the message posted successfully? */
  if( xResult != pdFAIL )
  {
      /* 如果xHigherPriorityTaskWoken現在設置爲pdTRUE,則應請求上下文切換。
         使用的宏是端口特定的,可以是portYIELD_FROM_ISR()或portendd_SWITCHING_ISR()
         -請參閱所用端口的文檔頁. */
      portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
  }
}

 

18.2.6 函數 xEventGroupWaitBits

EventBits_t xEventGroupWaitBits(
                       const EventGroupHandle_t xEventGroup,
                       const EventBits_t uxBitsToWaitFor,
                       const BaseType_t xClearOnExit,
                       const BaseType_t xWaitForAllBits,
                       TickType_t xTicksToWait);

讀取RTOS 事件組中的位,可以選擇進入Blocked狀態(帶有超時),以等待位或位組的置位。

不能從中斷中調用此函數。

RTOS源文件FreeRTOS / source / event_groups.c必須包含在構建中,以便xEventGroupWaitBits()函數可用。

參數:

xEventGroup   在其中測試位的事件組。必須事先通過調用xEventGroupCreate()創建事件組 。
uxBitsToWaitFor   指示事件組內要測試的一個或多個位的按位值。例如,要等待位0和/或位2,請將uxBitsToWaitFor設置爲0x05。要等待位0和/或位1和/或位2,請將uxBitsToWaitFor設置爲0x07。等等。

uxBitsToWaitFor 不得設置爲0。

xClearOnExit   如果xClearOnExit設置爲pdTRUE,則如果xEventGroupWaitBits()由於超時以外的任何其他原因返回,則xEventGroupWaitBits()返回之前,將在事件組中清除作爲uxBitsToWaitFor參數傳遞的值中設置的任何位。超時值由xTicksToWait參數設置。

如果xClearOnExit設置爲pdFALSE,則當對xEventGroupWaitBits()的調用返回時,事件組中設置的位不會更改。

xWaitForAllBits   xWaitForAllBits用於創建邏輯AND測試(必須設置所有位)或邏輯OR測試(必須設置一個或多個位),如下所示:

如果將xWaitForAllBits設置爲pdTRUE,則當在事件組中設置了作爲uxBitsToWaitFor參數傳遞的值中設置的所有位或者指定的阻止時間到期時,xEventGroupWaitBits()將返回。

如果將xWaitForAllBits設置爲pdFALSE,則在事件組中設置了作爲uxBitsToWaitFor參數傳遞的值中設置的任何位或指定的阻止時間到期時,xEventGroupWaitBits()將返回。

xTicksToWait   等待設置uxBitsToWaitFor指定的位中的一個/全部(取決於xWaitForAllBits值)的最長時間(以“滴答”表示)。

返回值:

等待事件位被置位或塊時間到期時事件組的值。如果更高優先級的任務或中斷更改了調用任務離開阻塞狀態與退出xEventGroupWaitBits()函數之間的事件位的值,則事件組中事件位的當前值將不同於返回值。

測試返回值以瞭解設置了哪些位。如果xEventGroupWaitBits()由於超時而返回,則不會設置所有等待的位。如果由於設置了xEventGroupWaitBits()而返回了等待的位,則返回值是事件組值,因爲xClearOnExit參數設置爲pdTRUE,因此在自動清除任何位之前。

用法示例:


#define BIT_0	( 1 << 0 )
#define BIT_4	( 1 << 4 )

void aFunction(EventGroupHandle_t xEventGroup)
{
    EventBits_t uxBits;
    const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;

    /* Wait a maximum of 100ms for either bit 0 or bit 4 to be set within
    the event group.  Clear the bits before exiting. */
    uxBits = xEventGroupWaitBits(
                 xEventGroup,   /* The event group being tested. */
                 BIT_0 | BIT_4, /* The bits within the event group to wait for. */
                 pdTRUE,        /* BIT_0 & BIT_4 should be cleared before returning. */
                 pdFALSE,       /* Don't wait for both bits, either bit will do. */
                 xTicksToWait); /* Wait a maximum of 100ms for either bit to be set. */

    if ((uxBits & (BIT_0 | BIT_4)) == (BIT_0 | BIT_4))
    {
        /* xEventGroupWaitBits() returned because both bits were set. */
    }
    else if ((uxBits & BIT_0) != 0)
    {
        /* xEventGroupWaitBits() returned because just BIT_0 was set. */
    }
    else if ((uxBits & BIT_4) != 0)
    {
        /* xEventGroupWaitBits() returned because just BIT_4 was set. */
    }
    else
    {
        /* xEventGroupWaitBits() returned because xTicksToWait ticks passed
        without either BIT_0 or BIT_4 becoming set. */
    }
}

 

18.2.7 函數 xEventGroupClearBits

EventBits_t xEventGroupClearBits(
                                 EventGroupHandle_t xEventGroup,
                                 const EventBits_t uxBitsToClear);

清除RTOS 事件組中的位(標誌)。不能從中斷中調用此函數。有關可從中斷調用的版本,請參見xEventGroupClearBitsFromISR()。

RTOS源文件FreeRTOS / source / event_groups.c必須包含在構建中,以便xEventGroupClearBits()函數可用。

參數:

xEventGroup   要清除其中事件的事件組。必須事先通過調用xEventGroupCreate()創建事件組 。
uxBitsToClear   指示事件組中要清除的一個或多個位的按位值。例如,將uxBitsToClear設置爲0x08僅清除位3。將uxBitsToClear設置爲0x09以清除位3和位0。

返回值:

清除指定位之前 的事件組的值。

用法示例:

#define BIT_0	( 1 << 0 )
#define BIT_4	( 1 << 4 )

void aFunction( EventGroupHandle_t xEventGroup )
{
  EventBits_t uxBits;

  /* Clear bit 0 and bit 4 in xEventGroup. */
  uxBits = xEventGroupClearBits(
                                xEventGroup,  /* The event group being updated. */
                                BIT_0 | BIT_4 );/* The bits being cleared. */

  if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
  {
      /* Both bit 0 and bit 4 were set before xEventGroupClearBits()
      was called.  Both will now be clear (not set). */
  }
  else if( ( uxBits & BIT_0 ) != 0 )
  {
      /* Bit 0 was set before xEventGroupClearBits() was called.  It will
      now be clear. */
  }
  else if( ( uxBits & BIT_4 ) != 0 )
  {
      /* Bit 4 was set before xEventGroupClearBits() was called.  It will
      now be clear. */
  }
  else
  {
      /* Neither bit 0 nor bit 4 were set in the first place. */
  }
}

 

18.2.8 函數 xEventGroupClearBitsFromISR

BaseType_t xEventGroupClearBitsFromISR(
                                EventGroupHandle_t xEventGroup,
                                const EventBits_t uxBitsToClear);

可以從中斷中調用 的xEventGroupClearBits()版本。清除操作將推遲到RTOS守護程序任務,也稱爲計時器服務任務。守護程序任務的優先級由 FreeRTOSConfig.h中的 configTIMER_TASK_PRIORITY設置來設置。

RTOS源文件FreeRTOS / source / event_groups.c必須包含在構建中,以便xEventGroupClearBitsFromISR()函數可用。

參數:

xEventGroup   要清除其中事件的事件組。必須事先通過調用xEventGroupCreate()創建事件組 。
uxBitsToClear   指示事件組中要清除的一個或多個位的按位值。例如,將uxBitsToClear設置爲0x08僅清除位3。將uxBitsToClear設置爲0x09以清除位3和位0。

返回值:

pdPASS,如果操作已成功推遲到RTOS守護程序任務。否則爲pdFALSE。僅當計時器命令隊列已滿時才返回pdFALSE 。

用法示例:

#define BIT_0	( 1 << 0 )
#define BIT_4	( 1 << 4 )

/* This code assumes the event group referenced by the
xEventGroup variable has already been created using a call to
xEventGroupCreate(). */
void anInterruptHandler( void )
{
  BaseType_t xSuccess;

  /* Clear bit 0 and bit 4 in xEventGroup. */
  xSuccess = xEventGroupClearBitsFromISR(
                                xEventGroup, /* The event group being updated. */
                                BIT_0 | BIT_4 );/* The bits being cleared. */

  if( xSuccess == pdPASS )
  {
      /* The command was sent to the daemon task. */
  }
  else
  {
      /* The clear bits command was not sent to the daemon task. */
  }
}

 

18.2.9 函數 xEventGroupGetBits

EventBits_t xEventGroupGetBits(EventGroupHandle_t xEventGroup);

返回RTOS 事件組中事件位(事件標誌)的當前值。不能從中斷使用此功能。有關 可以在中斷中使用的版本,請參見xEventGroupGetBitsFromISR()。

RTOS源文件FreeRTOS / source / event_groups.c必須包含在構建中,以便xEventGroupGetBits()函數可用。

參數:

xEventGroup   正在查詢的事件組。必須事先通過調用xEventGroupCreate()創建事件組 。

返回值:

調用xEventGroupGetBits()時,事件組中事件位的值。

 

18.2.10 函數 xEventGroupGetBitsFromISR

EventBits_t xEventGroupGetBitsFromISR(
                               EventGroupHandle_t xEventGroup);

可以從中斷中調用 的xEventGroupGetBits()版本。

RTOS源文件FreeRTOS / source / event_groups.c必須包含在構建中,以便xEventGroupGetBitsFrom()函數可用。

參數:

xEventGroup   正在查詢的事件組。必須事先通過調用xEventGroupCreate()創建事件組 。

返回值:

調用xEventGroupGetBitsFromISR()時,事件組中事件位的值。

 

18.2.11 函數 xEventGroupSync

EventBits_t xEventGroupSync(EventGroupHandle_t xEventGroup,
                              const EventBits_t uxBitsToSet,
                              const EventBits_t uxBitsToWaitFor,
                              TickType_t xTicksToWait);

以原子方式設置RTOS 事件組中的位(標誌),然後等待在同一事件組中設置位的組合。此功能通常用於同步多個任務(通常稱爲任務集合點),其中每個任務必須等待其他任務到達同步點才能繼續。

不能從中斷使用此功能。

如果設置了uxBitsToWait參數指定的位,或者在該時間內設置了該功能,則該函數將在其塊時間到期之前返回。在這種情況下,uxBitsToWait指定的所有位將在函數返回之前自動清除。

RTOS源文件FreeRTOS / source / event_groups.c必須包含在構建中,以便xEventGroupSync()函數可用。

參數:

xEventGroup   設置和測試位的事件組。必須事先通過調用xEventGroupCreate()創建事件組 。
uxBitsToSet   在確定(並可能等待)是否已設置uxBitsToWait參數指定的所有位之前,事件組中要設置的位。例如,將uxBitsToSet設置爲0x04可將事件組中的位2設置爲1。
uxBitsToWaitFor   指示事件組內要測試的一個或多個位的按位值。例如,將uxBitsToWaitFor設置爲0x05以等待位0和位2。將uxBitsToWaitFor設置爲0x07以等待位0和位1和位2等。
xTicksToWait   等待設置uxBitsToWaitFor參數值指定的所有位的最長時間(以“滴答”表示)。

返回值:

在等待位被置位或塊時間到期時事件組的值。測試返回值以瞭解設置了哪些位。

如果xEventGroupSync()由於超時而返回,則不會設置所有等待的位。

如果由於設置了xEventGroupSync()而已等待的所有位而返回,則返回的值是事件組值,然後自動清除任何位。

用法示例:

/* Bits used by the three tasks. */
#define TASK_0_BIT        ( 1 << 0 )
#define TASK_1_BIT        ( 1 << 1 )
#define TASK_2_BIT        ( 1 << 2 )

#define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )

/* Use an event group to synchronise three tasks.  It is assumed this event
group has already been created elsewhere. */
EventGroupHandle_t xEventBits;

void vTask0( void *pvParameters )
{
  EventBits_t uxReturn;
  TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;

    for( ;; )
    {
        /* Perform task functionality here. */
        . . .

        /* Set bit 0 in the event group to note this task has reached the
        sync point.  The other two tasks will set the other two bits defined
        by ALL_SYNC_BITS.  All three tasks have reached the synchronisation
        point when all the ALL_SYNC_BITS are set.  Wait a maximum of 100ms
        for this to happen. */
        uxReturn = xEventGroupSync( xEventBits,
                                    TASK_0_BIT,
                                    ALL_SYNC_BITS,
                                    xTicksToWait );

        if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS )
        {
            /* All three tasks reached the synchronisation point before the call
            to xEventGroupSync() timed out. */
        }
    }
}

void vTask1( void *pvParameters )
{
    for( ;; )
    {
        /* Perform task functionality here. */
        . . .

        /* Set bit 1 in the event group to note this task has reached the
        synchronisation point.  The other two tasks will set the other two
        bits defined by ALL_SYNC_BITS.  All three tasks have reached the
        synchronisation point when all the ALL_SYNC_BITS are set.  Wait
        indefinitely for this to happen. */
        xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );

        /* xEventGroupSync() was called with an indefinite block time, so
        this task will only reach here if the syncrhonisation was made by all
        three tasks, so there is no need to test the return value. */
    }
}

void vTask2( void *pvParameters )
{
    for( ;; )
    {
        /* Perform task functionality here. */
        . . .

        /* Set bit 2 in the event group to note this task has reached the
        synchronisation point.  The other two tasks will set the other two
        bits defined by ALL_SYNC_BITS.  All three tasks have reached the
        synchronisation point when all the ALL_SYNC_BITS are set.  Wait
        indefinitely for this to happen. */
        xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );

        /* xEventGroupSync() was called with an indefinite block time, so
        this task will only reach here if the syncrhonisation was made by all
        three tasks, so there is no need to test the return value. */
    }
}

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章