ThreadX——IPC應用之事件標誌

1、應用簡介

在RTOS的應用開發中,事件標誌主要是用來進行任務之間的事件通知。例若有A和B兩個任務,A任務負責接收消息,B任務負責對消息響應。當A任務接收到消息後設置響應標誌,B任務監測到響應標誌被設置就執行消息響應。事件標誌沒被設置的時候任務是不會佔用CPU的,不用像裸機程序那樣不斷輪詢事件的發生,使得CPU的利用率更高,這也是使用RTOS的優點之一。api

2、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);

3、實例說明

該實例建立一個事件標誌組和三個任務。標誌組中包含了兩個事件標誌,任務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

相關文章
相關標籤/搜索