一、應用簡介
在RTOS的應用開發中,事件標志主要是用來進行任務之間的事件通知,例如有A和B兩個任務,A任務負責接收訊息,B任務負責對訊息回應,當A任務接收到訊息后設定回應標志,B任務監測到回應標志被設定就執行訊息回應,事件標志沒被設定的時候任務是不會占用CPU的,不用像裸機程式那樣不斷輪詢事件的發生,使得CPU的利用率更高,這也是使用RTOS的優勢之一,
二、API說明
下面列出使用事件標志組時常用的幾個函式
1、創建事件標志組
- 描述:
- 該函式會創建一個包含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);
2、洗掉事件標志組
- 描述
- 此服務會洗掉指定的事件標志組,所有等待該組事件的掛起執行緒將被恢復,并給出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);
3、獲取事件標志
- 描述
- 此服務從指定的事件標志組檢索事件標志,每個事件標志組包含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);
4、設定事件標志
- 描述
- 此服務根據指定的選項設定或清除事件標志組中的事件標志, 所有請求被設定事件標志的執行緒將從掛起狀態恢復運行態,
- 引數
- 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);
}
}
}
}
效果如下:

轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/233759.html
標籤:其他
