簡 介
Azure RTOS ThreadX 是 Microsoft 提供的高級工業(yè)級實時操作系統(tǒng) (RTOS)。它是專門為深度嵌入式實時 IoT 應(yīng)用程序設(shè)計的。Azure RTOS ThreadX 提供高級計劃、通信、同步、計時器、內(nèi)存管理和中斷管理功能。此外,Azure RTOS ThreadX 具有許多高級功能,包括 picokernel 體系結(jié)構(gòu)、preemption-threshold 計劃、event-chaining、執(zhí)行分析、性能指標(biāo)和系統(tǒng)事件跟蹤。Azure RTOS ThreadX 非常易于使用,適用于要求極其苛刻的嵌入式應(yīng)用程序。Azure RTOS ThreadX 在各種產(chǎn)品(包括消費者設(shè)備、醫(yī)療電子設(shè)備和工業(yè)控制設(shè)備)上的部署次數(shù)已達(dá)數(shù)十億次。
具體的介紹和用戶指南可以參考:
https://docs.microsoft.com/zh-cn/azure/rtos/threadx/
在前文描述移植基本內(nèi)核的基礎(chǔ)上,該應(yīng)用手冊描述了如何基于MM32F3270系列MCU結(jié)合Azure RTOS ThreadX應(yīng)用Counting Semaphores的使用,引導(dǎo)用戶理解Azure RTOS ThreadX信號量功能。
表 1 適用系列型號
系列 | 芯片型號 | 開發(fā)板 |
MM32F3270 | MM32F3273G9P | EVB-F3270 |
1移植應(yīng)用的準(zhǔn)備
1.1 硬件開發(fā)板的準(zhǔn)備
該移植過程中應(yīng)用的開發(fā)板為MM32的EVB-F3270,板載MM32F3273G9P。
EVB-F3270 (MM32F3273G9P) 的簡要參數(shù):
Arm Cortex-M3 內(nèi)核
板載 MM32F3273G9P(LQFP144)
4 x Key、4 x LED
I2S Speaker
TF-Card
Ethernet PHY
1.2 軟件的準(zhǔn)備
庫函數(shù)和例程(Lib Samples)
該移植過程中應(yīng)用的 Firmware 分別為 MM32F3270 庫函數(shù)和例程,下載地址:
https://www.mindmotion.com.cn/products/mm32mcu/mm32f/mm32f_mainstream/mm32f3270/
? ?
Azure RTOS ThreadX(源碼)
ThreadX 的源代碼已經(jīng)開放,我們可以從 ThreadX 公共源代碼存儲庫獲取 Azure RTOS ThreadX,網(wǎng)址為:
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 源代碼發(fā)布到 GitHub。安裝和使用該軟件進行內(nèi)部開發(fā)、測試和評估無需許可證。分發(fā)或銷售組件和設(shè)備需要許可證,除非使用 Azure RTOS 許可的硬件。
ThreadX 安裝
可以通過將 GitHub 存儲庫克隆到本地計算機來安裝 ThreadX。下面是用于在 PC 上創(chuàng)建 ThreadX 存儲庫的克隆的典型語法。
shell復(fù)制
git clone https://github.com/azure-rtos/threadx
或者,也可以使用 GitHub 主頁上的“下載”按鈕來下載存儲庫的副本。
下載后的倉庫代碼目錄列表如下:
? ?
Azure RTOS ThreadX(源碼)支持的開發(fā)環(huán)境
ThreadX 內(nèi)核提供好了各種主流硬件平臺和軟件平臺的移植文件,以Cortex_M3為例,可以支持以下六種開發(fā)環(huán)境:
本次移植過程使用Azure RTOS原有的sample_threadx.c文件為例,稍作修改,演示信號量的功能與應(yīng)用。
2Threadx 信號量的應(yīng)用
該章節(jié)介紹信號量的相關(guān)知識,演示程序可在MM32F3273G9P的EVB-F3270上運行。
此示例在文件 main_semaphore_demo.c 中實現(xiàn),旨在說明如何在嵌入式多線程環(huán)境中使用信號量,實現(xiàn)任務(wù)之間的同步和資源共享機制。
2.1 信號量
2.1.1 統(tǒng)計信號量
ThreadX 提供 32 位計數(shù)信號燈,其值范圍在 0 到 4,294,967,295 之間。計數(shù)信號燈有兩個操作:tx_semaphore_get 和 tx_semaphore_put 。執(zhí)行獲取操作會將信號燈數(shù)量減一,如果信號燈為 0,獲取操作不會成功。獲取操作的逆操作是放置操作,該操作會將信號燈數(shù)量加一。
每個計數(shù)信號燈都是一個公用資源,ThreadX 對如何使用計數(shù)信號燈沒有任何限制。
計數(shù)信號燈通常用于互相排斥,也可將計數(shù)信號燈用作事件通知的方法。
2.1.2 互相排斥
互相排斥用于控制線程對某些應(yīng)用程序區(qū)域(也稱為關(guān)鍵部分或應(yīng)用程序資源)的訪問 。將信號燈用于互相排斥時,信號燈的“當(dāng)前計數(shù)”表示允許訪問的線程總數(shù)。在大多數(shù)情況下,用于互相排斥的計數(shù)信號燈的初始值為 1,這意味著每次只有一個線程可以訪問關(guān)聯(lián)的資源。只有 0 或 1 值的計數(shù)信號燈通常稱為二進制信號燈。
如果使用二進制信號燈,用戶必須阻止同一個線程對其已擁有的信號燈執(zhí)行獲取操作。第二個獲取操作將失敗,并且可能導(dǎo)致調(diào)用線程無限期掛起和資源永久不可用。
2.1.3 事件通知
還可以采用生成者-使用者的方式,將計數(shù)信號燈用作事件通知。使用者嘗試獲取計數(shù)信號燈,而生成者則在有可用的信息時增加信號燈。此類信號燈的初始值通常為 0,此值不會在生成者為使用者準(zhǔn)備好信息之前增加。用于事件通知的信號燈也可能從使用 tx_semaphore_ceiling_put 服務(wù)調(diào)用中獲益。此服務(wù)確保信號燈計數(shù)值永遠(yuǎn)不會超過調(diào)用中提供的值。
2.1.4 創(chuàng)建計數(shù)信號燈
計數(shù)信號燈由應(yīng)用程序線程在初始化期間或運行時創(chuàng)建。信號燈的初始計數(shù)在創(chuàng)建過程中指定。應(yīng)用程序中計數(shù)信號燈的數(shù)量沒有限制。
2.1.5 線程掛起
嘗試對當(dāng)前計數(shù)為 0 的信號燈執(zhí)行獲取操作時,應(yīng)用程序線程可能會掛起。
執(zhí)行放置操作后,才會執(zhí)行掛起線程的獲取操作并恢復(fù)該線程。如果同一計數(shù)信號燈上掛起多個線程,這些線程將按照掛起的順序 (FIFO) 恢復(fù)。
不過,如果應(yīng)用程序在取消線程掛起的信號燈放置調(diào)用之前調(diào)用 tx_semaphore_prioritize,還可以恢復(fù)優(yōu)先級。信號燈設(shè)置優(yōu)先級服務(wù)將優(yōu)先級最高的線程放于掛起列表的前面,同時讓所有其他掛起的線程采用相同的 FIFO 順序。
2.1.6 信號燈放置通知
某些應(yīng)用程序可能會發(fā)現(xiàn),在放置信號燈時收到通知十分有利。ThreadX 通過 tx_semaphore_put_notify 服務(wù)提供此功能。此服務(wù)將提供的應(yīng)用程序通知函數(shù)注冊到指定的信號燈。只要放置了信號燈,ThreadX 就會調(diào)用此應(yīng)用程序通知函數(shù)。應(yīng)用程序通知函數(shù)內(nèi)的確切處理由應(yīng)用程序決定;但這通常包括恢復(fù)相應(yīng)的線程以處理新信號燈放置事件。
2.1.7 運行時信號燈性能信息
ThreadX 提供可選的運行時信號燈性能信息。如果 ThreadX 庫和應(yīng)用程序是在定義 TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO 的情況下生成的,ThreadX 會累積以下信息。
整個系統(tǒng)的總數(shù):
信號燈放置數(shù)
信號燈獲取數(shù)
信號燈獲取掛起數(shù)
信號燈獲取超時數(shù)
每個信號燈的總數(shù):
信號燈放置數(shù)
信號燈獲取數(shù)
信號燈獲取掛起數(shù)
信號燈獲取超時數(shù)
此信息在運行時通過tx_semaphore_performance_info_get和 tx_semaphore_performance_system_info_get 服務(wù)提供。信號燈性能信息在確定應(yīng)用程序是否正常運行時非常有用。此信息對于優(yōu)化應(yīng)用程序也很有用。例如,“信號燈獲取超時數(shù)”相對較高可能表明其他線程占用資源的時間太長。
2.2 Azure Threadx 信號量的相關(guān)函數(shù)
tx_semaphore_create 創(chuàng)建計數(shù)信號燈
UINTtx_semaphore_create( TX_SEMAPHORE*semaphore_ptr, CHAR*name_ptr, ULONGinitial_count);
函數(shù)說明
此服務(wù)創(chuàng)建用于線程間同步的計數(shù)信號燈。初始信號燈計數(shù)指定為輸入?yún)?shù)。
參數(shù)
semaphore_ptr:指向信號燈控制塊的指針。
name_ptr:指向信號燈名稱的指針。
initial_count:指定此信號燈的初始計數(shù)。合法值的范圍為 0x00000000 至 0xFFFFFFFF。
返回值
TX_SUCCESS:(0X00) 成功創(chuàng)建信號燈。
TX_SEMAPHORE_ERROR:(0x0C) 信號燈指針無效。指針為 NULL 或已創(chuàng)建信號燈。
NX_CALLER_ERROR:(0x13) 此服務(wù)的調(diào)用方無效。
示例
TX_SEMAPHOREmy_semaphore; UINTstatus; /*Createacountingsemaphorewhoseinitialvalueis1. Thisistypicallythetechniqueusedtomakeabinary semaphore.Binarysemaphoresareusedtoprovide protectionoveracommonresource.*/ status=tx_semaphore_create(&my_semaphore, "my_semaphore_name",1); /*IfstatusequalsTX_SUCCESS,my_semaphoreisreadyfor use.*/
另請參閱
tx_semaphore_ceiling_put
tx_semaphore_delete
tx_semaphore_get
tx_semaphore_info_get
tx_semaphore_performance_info_get
tx_semaphore_performance_system_info_get
tx_semaphore_prioritize
tx_semaphore_put
tx_semaphore_put_notify
具體函數(shù)的中文說明可以參考:
https://docs.microsoft.com/zh-cn/azure/rtos/threadx/chapter4
具體函數(shù)的英文說明可以參考:
https://docs.microsoft.com/en-us/azure/rtos/threadx/threadx-smp/chapter4
2.3 信號量的應(yīng)用演示
2.3.1 工程目錄的建立
打開目標(biāo)工程文件夾“MM32F3270Project”:
移除原有樣例.c 文件sample_threadx.c:
參考sample_threadx.c建立main_semaphore_demo.c文件,并添加hardware目錄中的led.c、key.c到工程項目中。
注意:
需要在delay.c中配置USE_SYSTICK_DELAY 為 0。
#define USE_SYSTICK_DELAY 0
3Threadx 的信號量應(yīng)用
創(chuàng)建如下幾個任務(wù):
LED1閃爍指示當(dāng)前系統(tǒng)運行。
K2鍵按下,發(fā)送信號量同步信號。
任務(wù)接收到消息后,串口打印。
3.1 代碼實現(xiàn)
下載調(diào)試默認(rèn)會運行到main()函數(shù),如下為全部實現(xiàn)的代碼。
Demo演示代碼
/*Thisisasmalldemoofthehigh-performanceThreadXkernel.Itincludesexamplesofsix threadsofdifferentpriorities,usingamessagequeue,semaphore,andaneventflagsgroup.*/ #include"tx_api.h" #include"delay.h" #include"led.h" #include"key.h" #include"uart.h" #defineDEMO_STACK_SIZE1024 #defineTHREAD0_PRIORITY1 #defineTHREAD0_PREEMPTION_THRESHOLD1 #defineTHREAD1_PRIORITY2 #defineTHREAD1_PREEMPTION_THRESHOLD2 #defineTHREAD5_PRIORITY4 #defineTHREAD5_PREEMPTION_THRESHOLD4 //#defineTHREAD5_PREEMPTION_THRESHOLD_NEW0 /*DefinetheThreadXobjectcontrolblocks...*/ TX_THREADthread_0; TX_THREADthread_1; TX_THREADthread_5; TX_SEMAPHORESemaphore; /*Definethecountersusedinthedemoapplication...*/ ULONGthread_0_counter; ULONGthread_1_counter; ULONGthread_5_counter; /*Definethethreadstacks.*/ UCHARthread_0_stack[DEMO_STACK_SIZE]; UCHARthread_1_stack[DEMO_STACK_SIZE]; UCHARthread_5_stack[DEMO_STACK_SIZE]; /*Definethreadprototypes.*/ voidthread_0_entry(ULONGthread_input); voidthread_1_entry(ULONGthread_input); voidthread_5_entry(ULONGthread_input); volatileunsignedintbootloop; /*Definemainentrypoint.*/ intmain() { DELAY_Init();//cannotusesystick LED_Init(); KEY_Init(); CONSOLE_Init(115200); printf("!!!Start!!! "); /*EntertheThreadXkernel.*/ tx_kernel_enter(); } /*Definewhattheinitialsystemlookslike.*/ voidtx_application_define(void*first_unused_memory) { /*Createthread0.*/ tx_thread_create( &thread_0, "thread0", thread_0_entry, 0, thread_0_stack, DEMO_STACK_SIZE, THREAD0_PRIORITY, THREAD0_PREEMPTION_THRESHOLD, TX_NO_TIME_SLICE, TX_AUTO_START); /*Createthread1.*/ tx_thread_create( &thread_1, "thread1", thread_1_entry, 0, thread_1_stack, DEMO_STACK_SIZE, THREAD1_PRIORITY, THREAD1_PREEMPTION_THRESHOLD, TX_NO_TIME_SLICE, TX_AUTO_START); /*Createthread5.*/ tx_thread_create( &thread_5, "thread5", thread_5_entry, 5, thread_5_stack, DEMO_STACK_SIZE, THREAD5_PRIORITY, THREAD5_PREEMPTION_THRESHOLD, TX_NO_TIME_SLICE, TX_AUTO_START); /*Createasemaphoreforsignalsynchronization*/ tx_semaphore_create(&Semaphore,"Semaphore",0); } /*Definethetestthreads.*/ voidthread_0_entry(ULONGthread_input) { /*ThisthreadsimplycontrolsLEDflashingtoindicatethatthesystemisrunning*/ while(1) { /*Incrementthethreadcounter.*/ thread_0_counter++; LED1_TOGGLE(); /*Sleepfor200ticks.*/ tx_thread_sleep(200); } } voidthread_1_entry(ULONGthread_input) { UINTstatus; /*Thisthreadsimplysuccessfullyreceivesthesemaphoreandstartstoprintinformation*/ while(1) { /*Incrementthethreadcounter.*/ thread_1_counter++; status=tx_semaphore_get(&Semaphore,TX_WAIT_FOREVER); if(status==TX_SUCCESS) { /*Receivethesemaphore*/ printf("Synchronizationsemaphorereceived "); } } } voidthread_5_entry(ULONGthread_input) { UCHARt=0; /*Thisthreadsimplyscanbuttonispressedtosendthesemaphore.*/ while(1) { /*Incrementthethreadcounter.*/ thread_5_counter++; t=KEY_Scan(0); if(KEY1_PRES==t) { LED1_TOGGLE(); } elseif(KEY2_PRES==t){ LED2_TOGGLE(); /*K2ispressedtosendasemaphore*/ tx_semaphore_put(&Semaphore); } elseif(KEY3_PRES==t){ LED3_TOGGLE(); } elseif(KEY4_PRES==t){ LED4_TOGGLE(); } else{ tx_thread_sleep(10); } } }
3.2 下載與調(diào)試
運行程序,板載LED1閃爍。觀察串口調(diào)試助手,按下K2鍵,串口打印信息:
創(chuàng)建信號量初始值為 0,用于信號同步。任務(wù)5執(zhí)行按鍵掃描,當(dāng)K2按下時通過tx_semaphore_put發(fā)送信號量,對計數(shù)值執(zhí)行加1操作。任務(wù)1通過tx_semaphore_get用于信號量接收,對計數(shù)值執(zhí)行減1操作,實際運行情況是K2鍵每按下一次,串口打印一條信息,Demo演示成功。
4小結(jié)
Azure RTOS 使用信號量能夠方便地實現(xiàn)任務(wù)之間的同步和資源共享機制,結(jié)合MM32F3270的強大性能,可以實現(xiàn)Azure RTOS廣泛的應(yīng)用場景。
審核編輯:湯梓紅
-
mcu
+關(guān)注
關(guān)注
146文章
17751瀏覽量
358770 -
RTOS
+關(guān)注
關(guān)注
24文章
837瀏覽量
120630 -
開發(fā)板
+關(guān)注
關(guān)注
25文章
5432瀏覽量
101237 -
信號量
+關(guān)注
關(guān)注
0文章
53瀏覽量
8484 -
Azure
+關(guān)注
關(guān)注
1文章
125瀏覽量
13150
原文標(biāo)題:靈動微課堂 (第240講)|使用MM32F3270基于Azure RTOS信號量的應(yīng)用
文章出處:【微信號:MindMotion-MMCU,微信公眾號:靈動MM32MCU】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
MM32F3270系列32位MCU的特點有哪些
使用MM32F3270基于Azure RTOS定時器組的應(yīng)用
靈動微電子MM32F3270系列MCU的特點介紹
基于MM32F3270 以太網(wǎng) Client使用

評論