在RTOS的應用開發中,事件標誌主要是用來進行任務之間的事件通知。例若有A和B兩個任務,A任務負責接收消息,B任務負責對消息響應。當A任務接收到消息後設置響應標誌
,B任務監測到響應標誌
被設置就執行消息響應。事件標誌沒被設置的時候任務是不會佔用CPU的,不用像裸機程序那樣不斷輪詢事件的發生,使得CPU的利用率更高,這也是使用RTOS的優點之一。api
下面列出使用事件標誌組時經常使用的幾個函數app
- 描述:
- 該函數會建立一個包含32個事件標誌的事件組(其實就是一個32bit的變量),組中的32個事件標誌都被初始化爲零,每一個事件標誌由一個Bit表示(bit位置1則代表該位表明的事件標誌被設置)。
- 參數
- group_ptr :指向事件標誌組控件塊的指針
- name_ptr :指向事件標誌組名稱的指針
- 返回值
- TX_SUCCESS (0x00) :成功建立事件組
- TX_GROUP_ERROR (0x06) :無效的事件組指針,指針爲NULL或事件組已建立
- TX_CALLER_ERROR (0x13):該服務的調用者無效
UINT tx_event_flags_create( TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr);
- 描述
- 此服務會刪除指定的事件標誌組,全部等待該組事件的掛起線程將被恢復,並給出TX_DELETED返回狀態。
- 在刪除事件標誌組以前,應用程序必須確保完成(或禁用)此事件標誌組的通知回調。此外,應用程序必須禁止使用已刪除的事件標誌組。
- 參數
- group_ptr :指向先前建立的事件標誌組的指針
- 返回值
- TX_SUCCESS (0x00):成功刪除事件標誌組
- TX_GROUP_ERROR (0x06):無效的事件標誌組指針
- TX_CALLER_ERROR (0x13):該服務的調用者無效
UINT tx_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr);
- 描述
- 此服務從指定的事件標誌組檢索事件標誌。每一個事件標誌組包含32個事件標誌。每一個標誌由一個位表示。此服務能夠檢索由輸入參數選擇的各類事件標誌組合。
- 參數
- group_ptr:指向先前建立的事件標誌組的指針
- requested_flags:表示請求的事件標誌
- get_option:請求事件標誌的選項(TX_AND (0x02):指定的事件標誌必須所有有效;TX_OR (0x00):指定的事件部分部分有效便可;TX_AND_CLEAR (0x03):指定的事件標誌必須都被設置且清除相應的事件標誌;TX_OR_CLEAR (0x01):指定的事件標誌部分被設置就知足條件且清除相應的事件標誌)
- actual_flags_ptr:指向放置檢索到的事件標誌的指針。請注意,得到的實際標誌可能包含未被請求的標誌。
- wait_option:所選事件標誌未被設置時服務的行爲(TX_NO_WAIT (0x00000000) :不等待當即返回;TX_WAIT_FOREVER(0xFFFFFFFF):一直掛起等待直到事件標誌被設置;(0x00000001 到 0xFFFFFFFE):等待的心跳節拍數,例如設置心跳是1KHZ那單位就是ms)
- 返回值
- TX_SUCCESS(0x00)成功得到事件標誌。
- TX_DELETED(0x01)線程掛起時,事件標誌組已刪除。
- TX_NO_EVENTS(0x07)服務沒法在指定的等待時間內獲取指定的事件。
- TX_WAIT_ABORTED(0x1A)被另外一個線程、計時器或中斷服務打斷。
- TX_GROUP_ERROR(0x06)無效的事件標誌組指針。
- TX_PTR_ERROR(0x03)實際事件標誌的無效指針。
- TX_WAIT_ERROR(0x04)在非線程調用中指定了TX_NO_WAIT之外的等待選項。
- TX_OPTION_ERROR(0x08)指定了無效的獲取選項。
UINT tx_event_flags_get( TX_EVENT_FLAGS_GROUP *group_ptr, ULONG requested_flags, UINT get_option, ULONG *actual_flags_ptr, ULONG wait_option);
- 描述
- 此服務根據指定的選項設置或清除事件標誌組中的事件標誌。 全部請求被設置事件標誌的線程將從掛起狀態恢復運行態。
- 參數
- group_ptr:指向先前建立的事件標誌組控制塊的指針
- flags_to_set:根據選擇的設置選項指定要設置或清除的事件標誌
- set_option:將指定的事件標誌與該組的當前事件標誌進行「與」或「或」運算(TX_AND(0x02)、TX_OR(0x00));選擇TX_AND將指定的事件標誌與該組中的當前事件標誌進行「與」運算。 此選項一般用於清除組中的事件標誌。選擇TX_OR,則將指定的事件標誌與組中的當前事件進行「或」運算。
- 返回值
- TX_SUCCESS(0x00)事件標誌成功設置。
- TX_GROUP_ERROR(0x06)指向事件標誌組指針無效。
- TX_OPTION_ERROR(0x08)指定了無效的設置選項。
UINT tx_event_flags_set( TX_EVENT_FLAGS_GROUP *group_ptr, ULONG flags_to_set, UINT set_option);
該實例建立一個事件標誌組和三個任務。標誌組中包含了兩個事件標誌,任務1檢測按鍵1的運行,任務2檢測按鍵2的運行,任務3執行對應的按鍵響應,任務之間的通知採用事件標誌的方式。函數
#include "main.h" #include "usart.h" #include "gpio.h" #include "tx_api.h" #define DEMO_STACK_SIZE (2 * 1024) #define DEMO_BYTE_POOL_SIZE (32 * 1024) /*事件標誌*/ #define TX_EVENT_FLAG_KEY1 (1 << 0) #define TX_EVENT_FLAG_KEY2 (1 << 1) TX_THREAD thread_0; TX_THREAD thread_1; TX_THREAD thread_2; TX_BYTE_POOL byte_pool_0; UCHAR memory_area[DEMO_BYTE_POOL_SIZE]; /*事件標誌組*/ TX_EVENT_FLAGS_GROUP tx_event_flags; void thread_0_entry(ULONG thread_input); void thread_1_entry(ULONG thread_input); void thread_2_entry(ULONG thread_input); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); tx_kernel_enter(); while (1) { } } void tx_application_define(void *first_unused_memory) { CHAR *pointer = TX_NULL; /* Create a byte memory pool from which to allocate the thread stacks. */ tx_byte_pool_create(&byte_pool_0, "byte pool 0", memory_area, DEMO_BYTE_POOL_SIZE); /* 建立事件標誌組 */ tx_event_flags_create(&tx_event_flags, "my_event_group_name"); /* Allocate the stack for thread 0. */ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); /* Create the main thread. */ tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, pointer, DEMO_STACK_SIZE, 1, 1, TX_NO_TIME_SLICE, TX_AUTO_START); /* Allocate the stack for thread 1. */ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); /* Create threads 1 */ tx_thread_create(&thread_1, "thread 1", thread_1_entry, 0, pointer, DEMO_STACK_SIZE, 2, 2, TX_NO_TIME_SLICE, TX_AUTO_START); /* Allocate the stack for thread 2. */ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); /* Create threads 1 */ tx_thread_create(&thread_2, "thread 2", thread_2_entry, 0, pointer, DEMO_STACK_SIZE, 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START); } void thread_0_entry(ULONG thread_input) { uint8_t key_cnt = 0; while(1) { if (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) != GPIO_PIN_RESET) { key_cnt++; } else { if (key_cnt > 2) { /* 按鍵1觸發,設置事件標誌 */ tx_event_flags_set(&tx_event_flags, TX_EVENT_FLAG_KEY1, TX_OR); } key_cnt = 0; } tx_thread_sleep(20); } } void thread_1_entry(ULONG thread_input) { uint8_t key_cnt = 0; while(1) { if (HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) != GPIO_PIN_RESET) { key_cnt++; } else { if (key_cnt > 2) { /* 按鍵2觸發,設置事件標誌 */ tx_event_flags_set(&tx_event_flags, TX_EVENT_FLAG_KEY2, TX_OR); } key_cnt = 0; } tx_thread_sleep(20); } } void thread_2_entry(ULONG thread_input) { UINT status; ULONG actual_events; while(1) { /* 等待事件標誌:任意按鍵觸發都有效 */ status = tx_event_flags_get(&tx_event_flags, TX_EVENT_FLAG_KEY1 | TX_EVENT_FLAG_KEY2, TX_OR_CLEAR, &actual_events, TX_WAIT_FOREVER); if (TX_SUCCESS == status) { if (TX_EVENT_FLAG_KEY1 == (actual_events & TX_EVENT_FLAG_KEY1)) { HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin); printf("key1 is pressed, actual_events:0x%x\r\n", (int)actual_events); } if (TX_EVENT_FLAG_KEY2 == (actual_events & TX_EVENT_FLAG_KEY2)) { HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin); printf("key2 is pressed, actual_events:0x%x\r\n", (int)actual_events); } } } }
效果以下:ui