簡 介
Azure RTOS ThreadX 是 Microsoft 提供的高級工業級實時操作系統 (RTOS)。它是專門為深度嵌入式實時 IoT 應用程序設計的。Azure RTOS ThreadX 提供高級計劃、通信、同步、計時器、內存管理和中斷管理功能。此外,Azure RTOS ThreadX 具有許多高級功能,包括 picokernel? 體系結構、preemption-threshold? 計劃、event-chaining?、執行分析、性能指標和系統事件跟蹤。Azure RTOS ThreadX 非常易于使用,適用于要求極其苛刻的嵌入式應用程序。Azure RTOS ThreadX 在各種產品(包括消費者設備、醫療電子設備和工業控制設備)上的部署次數已達數十億次。
具體的介紹和用戶指南可以參考:
https://docs.microsoft.com/zh-cn/azure/rtos/threadx/
在前文描述移植基本內核的基礎上,本文描述了如何基于MM32F3270系列MCU結合Azure RTOS ThreadX應用事件標志組的使用,引導用戶理解Azure RTOS ThreadX事件標志組的功能。
表 1 適用系列型號
1、移植應用的準備
1.1 硬件開發板的準備
該移植過程中應用的開發板為MM32的EVB-F3270,板載MM32F3273G9P。
EVB-F3270 (MM32F3273G9P)的簡要參數:
● Arm Cortex-M3 內核
● 板載 MM32F3273G9P(LQFP144)
● 4 x Key、4 x LED
● I2S Speaker
● TF-Card
● Ethernet PHY
1.2 軟件的準備
庫函數和例程(Lib Samples)
該移植過程中應用的 Firmware 分別為 MM32F3270 庫函數和例程,下載地址:
https://www.mindmotion.com.cn/products/mm32mcu/mm32f/mm32f_mainstream/mm32f3270/
Azure RTOS ThreadX(源碼)
ThreadX 的源代碼已經開放,我們可以從 ThreadX 公共源代碼存儲庫獲取 Azure RTOS ThreadX,網址為:https://github.com/azure-rtos/threadx/
具體的商用使用條件參考Azure的許可證說明:
https://www.microsoft.com/en-us/legal/intellectualproperty/tech-licensing/programs?msclkid=f7ab4ff3afa011ec90a79366a52034fa activetab=pivot1:primaryr11
Microsoft publishes the Azure RTOS source code to GitHub. No license is required to install and use the software for internal development, testing, and evaluation purposes. A license is required to distribute or sell components and devices unless using Azure RTOS licensed hardware.
Azure RTOS 何時需要許可證?
Microsoft 將 Azure RTOS 源代碼發布到 GitHub。安裝和使用該軟件進行內部開發、測試和評估無需許可證。分發或銷售組件和設備需要許可證,除非使用 Azure RTOS 許可的硬件。
ThreadX 安裝
可以通過將 GitHub 存儲庫克隆到本地計算機來安裝 ThreadX。下面是用于在 PC 上創建 ThreadX 存儲庫的克隆的典型語法。
shell復制
git clone https://github.com/azure-rtos/threadx
或者,也可以使用 GitHub 主頁上的“下載”按鈕來下載存儲庫的副本。
下載后的倉庫代碼目錄列表如下:
Azure RTOS ThreadX(源碼)支持的開發環境
ThreadX 內核提供好了各種主流硬件平臺和軟件平臺的移植文件,以Cortex_M3為例,可以支持以下六種開發環境:
本次移植過程使用Azure RTOS原有的sample_threadx.c Samples為例子,稍作修改,演示了事件標志組的功能與應用。
2、Threadx 事件標志組的應用
該章節介紹了事件標志組應用實現的過程和注意事項,該演示程序可在MM32F3273G9P的EVB-F3270上運行。
此示例在文件 main_event_flags_demo.c 中定義,旨在說明如何在嵌入式多線程環境中使用事件標志組,實現任務之間的數據信號傳遞與中斷或任務同步的相互關系。
2.1 Azure Threadx event簡介
事件標志是Threadx線程同步的一個強大工具。事件標志可以被任何線程設置或清除,也可以被任何線程檢查。線程可以在等待設置某些事件標志組時掛起。
每個事件標志用1 bit表示,事件標志以32個為一組排列,組成一個事件標志組。之后的所有操作都是以組為單位。
線程可以同時對一個組中的所有32個事件標志進行操作。
要設置或清除事件標志組,可以使用tx_event_flags_set服務。
使用tx_event_flags_get服務可以“獲取”事件標志組。
獲取事件標志時,線程可以等待一個事件標志(一段時間或永久等待),直到該事件標志被另一個線程或中斷設置為1(set狀態)。
對于嵌入式應用來說,就有點像對一個個的寄存器位進行“ ”和“|”操作。
使用事件標志組可以有效的解決中斷服務程序和任務之間的同步問題。
2.2 Azure Threadx event的結構體
Event的結構體
typedef struct TX_EVENT_FLAGS_GROUP_STRUCT { /* Define the event flags group ID used for error checking. */ ULONG tx_event_flags_group_id; /* Define the event flags group's name. */ CHAR *tx_event_flags_group_name; /* Define the actual current event flags in this group. A zero in a particular bit indicates the event flag is not set. */ ULONG tx_event_flags_group_current; /* Define the reset search flag that is set when an ISR sets flags during the search of the suspended threads list. */ UINT tx_event_flags_group_reset_search; /* Define the event flags group suspension list head along with a count of how many threads are suspended. */ struct TX_THREAD_STRUCT *tx_event_flags_group_suspension_list; UINT tx_event_flags_group_suspended_count; /* Define the created list next and previous pointers. */ struct TX_EVENT_FLAGS_GROUP_STRUCT *tx_event_flags_group_created_next, *tx_event_flags_group_created_previous; /* Define the delayed clearing event flags. */ ULONG tx_event_flags_group_delayed_clear; #ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO /* Define the number of event flag sets. */ ULONG tx_event_flags_group_performance_set_count; /* Define the number of event flag gets. */ ULONG tx_event_flags_group__performance_get_count; /* Define the number of event flag suspensions. */ ULONG tx_event_flags_group___performance_suspension_count; /* Define the number of event flag timeouts. */ ULONG tx_event_flags_group____performance_timeout_count; #endif #ifndef TX_DISABLE_NOTIFY_CALLBACKS /* Define the application callback routine used to notify the application when an event flag is set. */ VOID (*tx_event_flags_group_set_notify)(struct TX_EVENT_FLAGS_GROUP_STRUCT *group_ptr); #endif /* Define the port extension in the event flags group control block. This is typically defined to whitespace in tx_port.h. */ TX_EVENT_FLAGS_GROUP_EXTENSION } TX_EVENT_FLAGS_GROUP;
Event flags包含成員的含義:
2.3 Azure Threadx event的主要函數與功能
事件標志組的主要函數
2.4 事件標志組的應用演示
2.4.1 工程目錄的建立
打開目標工程文件夾“MM32F3270Project”:
移除原有樣例.c 文件sample_threadx.c:
參考sample_threadx.c建立main_event_flags_demo.c文件,并添加hardware目錄中的led.c到工程項目中。
2.4.2 創建事件標志組tx_event_flags_create
聲明需要使用的事件標志組變量。
調用tx_event_flags_create, 建立一個事件標志組。
創建一個待使用的事件標志組
#include "tx_api.h" #define DEMO_STACK_SIZE 1024 /* Define the ThreadX object control blocks... */ TX_THREAD thread_0; TX_THREAD thread_5; TX_EVENT_FLAGS_GROUP event_flags_0; /* Define what the initial system looks like. */ void tx_application_define(void *first_unused_memory) { /* Create the main thread. */ tx_thread_create( thread_0, "thread 0", thread_0_entry, 0, thread_0_stack, DEMO_STACK_SIZE, 1, 1, TX_NO_TIME_SLICE, TX_AUTO_START); /* Create thread 5. This thread simply pends on an event flag which will be set by thread_0. */ tx_thread_create( thread_5, "thread 5", thread_5_entry, 5, thread_5_stack, DEMO_STACK_SIZE, 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START); /* Create the event flags group used by threads 0 and 5. */ tx_event_flags_create( event_flags_0, "event flags 0"); }
函數原型:
tx_event_flags_create函數原型
UINT _tx_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr)
參數:
● group_ptr:指向事件標志組控制塊的指針。
● name_ptr:指向事件標志組名稱的指針。
返回值:
● TX_SUCCESS:(0X00) 成功創建事件組。
● TX_GROUP_ERROR:(0x06) 事件組指針無效。指針為 NULL 或事件組已創建。
● NX_CALLER_ERROR:(0x13) 此服務的調用方無效。
應用中該實現函數:
tx_event_flags_create( event_flags_0, "event flags 0");
A. 第1個參數是事件標志組引用的指針,引用聲明的事件標注“event_flags_0”指向的地址。
B. 第2個參數是事件標志組的名字,字符串值為" event flags 0"。
2.4.3 創建一個任務用于發送事件標志組
在此建立一個定時發送一個事件標志組的簡單任務,發送完成,發送任務計數值加一:
創建一個發送事件標志組的任務
/* Define the test threads. */ void thread_0_entry(ULONG thread_input) { UINT status; /* This thread simply sits in while-forever-sleep loop. */ while(1) { /* Increment the thread counter. */ thread_0_counter++; /* Sleep for 10 ticks. */ tx_thread_sleep(10); /* Set event flag 0 to wakeup thread 5. */ status = tx_event_flags_set( event_flags_0, 0x1, TX_OR); /* Check status. */ if (status != TX_SUCCESS) break; } }
函數原型:
_tx_event_flags_set函數原型
UINT _tx_event_flags_set(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG flags_to_set, UINT set_option)
參數:
● group_ptr:指向以前創建的事件標志組控制塊的指針。
● flags_to_set:根據所選的 set-option,指定要設置或清除的事件標志。
● set_option:指定將所指定的事件標志與該組的當前事件標志進行“AND”或“OR”運算。以下是有效的選擇:
- TX_AND (0x02)
- TX_OR (0x00)
如果選擇 TX_AND,則會指定將所指定的事件標志與該組的當前事件標志進行“AND”運算。此選項通常用于清除組中的事件標志。否則,如果指定了 TX_OR,則對所指定的事件標志與該組的當前事件標志進行“OR”運算。
返回值:
● TX_SUCCESS:(0X00) 成功設置事件標志。
● TX_GROUP_ERROR:(0x06) 指向事件標志組的指針無效。
● TX_OPTION_ERROR:(0x08) 指定的 set-option 無效。
應用中該實現函數:
status = tx_event_flags_set( event_flags_0, 0x1, TX_OR);
A. 第1個參數是事件標志組引用的指針,引用聲明的事件標注“event_flags_0”指向的地址。
B. 第2個參數是事件標志組的名字,字符串值為" event flags 0"。
返回值
C. 第3個參數是TX_OR,則對所指定的事件標志與該組的當前事件標志進行“OR”運算。
2.4.4 創建一個任務接收事件標志組
在此建立一個任務,實現接收收事件標志組,接收事件設置值成功,接收任務計數值加一:
創建一個接收事件標志組任務
void thread_5_entry(ULONG thread_input) { UINT status; ULONG actual_flags; /* This thread simply waits for an event in a forever loop. */ while(1) { /* Increment the thread counter. */ thread_5_counter++; /* Wait for event flag 0. */ status = tx_event_flags_get( event_flags_0, 0x1, TX_OR_CLEAR, actual_flags, TX_WAIT_FOREVER); /* Check status. */ if ((status != TX_SUCCESS) || (actual_flags != 0x1)) break; } }
函數原型:
_tx_event_flags_set函數原型
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:指向以前創建的事件標志組的指針。
● requested_flags:32 位無符號變量,表示請求的事件標志。
● get_option:指定是否需要所有或任何請求的事件標志。以下是有效的選擇:
- TX_AND (0x02)
- TX_AND_CLEAR (0x03)
- TX_OR (0x00)
- TX_OR_CLEAR (0x01)
如果選擇 TX_AND 或 TX_AND_CLEAR,則會指定所有事件標志在組中都必須存在。如果選擇 TX_OR 或 TX_OR_CLEAR,則會指定任何事件標志都符合要求。如果指定 TX_AND_CLEAR 或 TX_OR_CLEAR,則會清除滿足請求的事件標志(設置為零)。
● actual_flags_ptr:指向放置檢索到的事件標志的位置這一目標的指針。注意,實際獲得的標志可能包含沒有請求的標志。
● wait_option:定義未設置所選事件標志時服務的行為方式。
等待選項的定義如下:
- TX_NO_WAIT (0x00000000) - 如果選擇 TX_NO_WAIT,則無論此服務是否成功,都會導致立即從此服務返回。如果從非線程(例如初始化、計時器或 ISR)調用服務,則這是唯一有效的選項。
- TX_WAIT_FOREVER 超時值 (0xFFFFFFFF) - 選擇 TX_WAIT_FOREVER 會導致發出調用的線程無限期掛起,直到事件標志可用為止。
- 超時值(0x00000001 至 0xFFFFFFFE)- 如果選擇一個數值(1 到 0xFFFFFFFE),則會指定在等待事件標志時發出調用的線程保持掛起的最大計時器時鐘周期數。
返回值:
● TX_SUCCESS:(0X00) 成功獲取事件標志。
● TX_DELETED:(0x01) 線程掛起時刪除了事件標志組。
● TX_NO_EVENTS:(0X07) 服務無法在指定的等待時間內獲取指定的事件。
● TX_WAIT_ABORTED:(0x1A) 掛起狀態由其他線程、計時器或 ISR 中止。
● TX_GROUP_ERROR:(0x06) 事件標志組指針無效。
● TX_PTR_ERROR:(0x03) 指向實際事件標志的指針無效。
● TX_WAIT_ERROR:(0x04) 從非線程調用時指定了除 TX_NO_WAIT 以外的等待選項。
● TX_OPTION_ERROR:(0x08) 指定的 get-option 無效。
應用中該實現函數:
status = tx_event_flags_get( event_flags_0, 0x1, TX_OR_CLEAR, actual_flags, TX_WAIT_FOREVER);
A. 第1個參數是事件標志組引用的指針,引用聲明的事件標注“event_flags_0”指向的地址。
B. 第2個參數是根據所選的 get-option,指定要設置或清除的事件標志等于0x01。
C. 第3個參數是TX_OR_CLEAR,則會判斷指定任何事件標志都符合要求,符合后并清除。
3、Threadx 的事件標志組應用實現與調試
3.1 代碼實現
下載調試默認會運行到main()函數,如下為全部實現的代碼。
Demo演示代碼
/* This is a small demo of the high-performance ThreadX kernel. It includes examples of six threads of different priorities, using a message an event flags group. */ #include "tx_api.h" #define DEMO_STACK_SIZE 1024 /* Define the ThreadX object control blocks... */ TX_THREAD thread_0; TX_THREAD thread_5; TX_EVENT_FLAGS_GROUP event_flags_0; /* Define the counters used in the demo application... */ ULONG thread_0_counter; ULONG thread_5_counter; /* Define the thread stacks. */ UCHAR thread_0_stack[DEMO_STACK_SIZE]; UCHAR thread_5_stack[DEMO_STACK_SIZE]; /* Define thread prototypes. */ void thread_0_entry(ULONG thread_input); void thread_5_entry(ULONG thread_input); /* Define main entry point. */ int main() { /* Enter the ThreadX kernel. */ tx_kernel_enter(); } /* Define what the initial system looks like. */ void tx_application_define(void *first_unused_memory) { /* Create the main thread. */ tx_thread_create( thread_0, "thread 0", thread_0_entry, 0, thread_0_stack, DEMO_STACK_SIZE, 1, 1, TX_NO_TIME_SLICE, TX_AUTO_START); /* Create thread 5. This thread simply pends on an event flag which will be set by thread_0. */ tx_thread_create( thread_5, "thread 5", thread_5_entry, 5, thread_5_stack, DEMO_STACK_SIZE, 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START); /* Create the event flags group used by threads 0 and 5. */ tx_event_flags_create( event_flags_0, "event flags 0"); } /* Define the test threads. */ void thread_0_entry(ULONG thread_input) { UINT status; /* This thread simply sits in while-forever-sleep loop. */ while(1) { /* Increment the thread counter. */ thread_0_counter++; /* Sleep for 10 ticks. */ tx_thread_sleep(10); /* Set event flag 0 to wakeup thread 5. */ status = tx_event_flags_set( event_flags_0, 0x1, TX_OR); /* Check status. */ if (status != TX_SUCCESS) break; } } void thread_5_entry(ULONG thread_input) { UINT status; ULONG actual_flags; /* This thread simply waits for an event in a forever loop. */ while(1) { /* Increment the thread counter. */ thread_5_counter++; /* Wait for event flag 0. */ status = tx_event_flags_get( event_flags_0, 0x1, TX_OR_CLEAR, actual_flags, TX_WAIT_FOREVER); /* Check status. */ if ((status != TX_SUCCESS) || (actual_flags != 0x1)) break; } }
3.2 下載與調試
進入調試模式,可以看到接收事件標志組成功。
該demo示例,建立了2個線程,程序執行一個發送事件標志,另外一個線程接收事件標志,實現執行Task Counter與發送 接收的Message Counter的累加。
全速運行后,可以看到相關的數值在變化:
4、小結
這個演示程序中,使用了tx_thread_sleep()函數做了延時,剛好使得發送事件標志組與接收事件標志組一一配對,計數值累加后都是相等的,說明同步成功。
Azure RTOS ThreadX 的使用事件標志組可以方便實現任務對任務或任務對中斷的同步,結合MM32F3270的強大性能,可以實現Azure RTOS的各種特色功能。
來源:靈動MM32MCU
免責聲明:本文為轉載文章,轉載此文目的在于傳遞更多信息,版權歸原作者所有。本文所用視頻、圖片、文字如涉及作品版權問題,請聯系小編進行處理
審核編輯 黃宇
-
RTOS
+關注
關注
22文章
811瀏覽量
119593 -
Azure
+關注
關注
1文章
123瀏覽量
12778
發布評論請先 登錄
相關推薦
評論