版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
第9章RT-Thread嵌入式實時操作系統(tǒng)9.1RT-Thread概述RT-Thread,全稱是RealTime-Thread,顧名思義,它是一個嵌入式實時多線程操作系統(tǒng),基本屬性之一是支持多任務,允許多個任務同時運行并不意味著處理器在同一時刻真地執(zhí)行了多個任務。RT-Thread主要采用C語言編寫,淺顯易懂,方便移植。它把面向?qū)ο蟮脑O計方法應用到實時系統(tǒng)設計中,使得代碼風格優(yōu)雅、架構清晰、系統(tǒng)模塊化并且可裁剪性非常好。資源有限的MCU可用RT-ThreadNANO版,需約3KBFlash和1.2KBRAM,極簡內(nèi)核。資源豐富設備可用在線管理工具快速裁剪模塊,支持豐富功能包和復雜界面交互。RT-Thread體積小、成本低、功耗低、啟動快,適合資源受限場合,具備高實時性。主平臺是32位MCU,也支持ARM9、ARM11、Cortex-A等帶MMU的應用處理器。RTT主要運行平臺是32位的MCU,在特定應用場合也適用于Cortex-A系列級別的MPU。RTT系統(tǒng)完全開源。遵循ApacheLicense2.0開源許可協(xié)議,可以免費在商業(yè)產(chǎn)品中使用,并且不需要公開私有代碼。1. RT-Thread的實時核心RT-Thread的實時核心是一個精巧、高效、高度可定制的實時核心,功能特點如下:(1)采用C語言風格的內(nèi)核面向?qū)ο笤O計,完美的模塊化設計。(2)具備高度的可裁剪性和可伸縮性,其最小版本資源占用極低,僅需2.5KROM和1KRAM。(3)支持所有的MCU架構(ARM、MIPS、Xtensa、Risc-V、C-sky)。(4)支持幾乎所有主流的MCU、WiFi芯片,包括STM32F/L系列、NXPLPC/Kinetis系列、GD32系列、樂鑫ESP32、Realtek871X、Marvell88MW300、CypressFM系列、新唐M系列等。(5)支持KeilMDK/RVDSarmcc,GNUGCC,IAR等多種主流編譯器。2. RT-Thread設備框架RT-Thread設備框架如圖9-1所示。圖9-1RT-Thread設備框架RT-Thread設備框架功能特點如下:(1)設備框架提供標準接口訪問底層設備,上層應用采用抽象的設備接口進行底層硬件的訪問操作,上層應用與底層硬件設備無關;更換底層驅(qū)動時,不需要更改上層應用代碼,從而降低系統(tǒng)耦合性,提高設備可靠性。(2)當前支持的設備類型:字符型設備、塊設備、網(wǎng)絡設備、聲音設備、圖形設備和Flash設備等。3. RT-Thread設備虛擬文件系統(tǒng)框架RT-Thread設備虛擬文件系統(tǒng)框架如圖9-2所示。圖9-2RT-Thread設備虛擬文件系統(tǒng)框架設備虛擬文件系統(tǒng)主要面向小型設備,功能特點如下:(1)類似Linux虛擬文件系統(tǒng)方式的融合了多種文件系統(tǒng)的超級文件系統(tǒng)。(2)為上層應用提供統(tǒng)一的文件訪問接口,無需關心底層文件系統(tǒng)的具體實現(xiàn)及存儲方式。(3)支持系統(tǒng)內(nèi)同時存在多種不同的文件系統(tǒng)。(4)支持FAT(包括長文件名、中文文件名)、UFFS、NFSv3、ROMFS和RAMFS等多種文件系統(tǒng)。(5)支持SPINORFlash、NandFlash、SD卡等多種存儲介質(zhì)。(6)面向MCU的NFTL閃存轉(zhuǎn)換層,完成NANDFlash上的日志,壞塊管理,擦寫均衡,掉電保護等功能。4. RT-Thread協(xié)議棧RT-Thread協(xié)議棧如圖9-3所示。圖9-3RT-Thread協(xié)議棧RT-Thread協(xié)議棧功能特點如下:(1)支持廣域網(wǎng)LoRa,NB-IoT,無線局域網(wǎng)Wi-Fi、藍牙BLE,有線以太網(wǎng)。(2)支持IPV4、IPV6、UDP、PPP協(xié)議。(3)支持TLS、DTLS安全傳輸。(4)支持HTTP、HTTPS、WebSocket、MQTT、LWM2M協(xié)議。(5)支持Modbus、Canopen工業(yè)協(xié)議。5. 音頻流媒體框架音頻流媒體框架如圖9-4所示。圖9-4音頻流媒體框架音頻流媒體框架功能特點如下:(1)適合MCU的輕型流媒體音頻框架,資源占用小,響應快。(2)支持wav、mp3、aac、flac、m4a、alac、speex、opus、amr等音頻格式。(3)支持流媒體協(xié)議:http、hls、rtsp、rtp、shoutcast。(4)支持媒體渲染協(xié)議:DLNA、Airplay、QQPlay。(5)支持語音識別及語音合成。6. PersimmonUI圖形庫PersimmonUI圖形庫是一套小型,現(xiàn)代化的圖形庫,功能特點如下:(1)支持多點觸摸操作,實現(xiàn)滑屏,拖拽,旋轉(zhuǎn),牽引等多種界面動畫增強效果。(2)按鈕,圖片框,列表,面板,卡片,輪轉(zhuǎn)等基礎控件,以及窗口上的懸浮帶透明效果控件。(3)使用類似signal/slot的方式,靈活的把界面事件映射到用戶動作。(4)支持TTF矢量字體,針對MCU優(yōu)化的自定義圖像格式,大幅提升圖片加載和渲染速度。(5)支持多國語言。7. 低功耗管理低功耗管理功能特點如下:(1)自動休眠,系統(tǒng)空閑時休眠省電(支持睡眠模式,定時喚醒模式,停止模式)。(2)自動調(diào)頻調(diào)壓,系統(tǒng)激活工作時,根據(jù)程序設定值或基于芯片性能動態(tài)調(diào)節(jié)運行時頻率。(3)對用戶應用透明,用戶應用不需要關心功耗情況,系統(tǒng)自動進入休眠狀態(tài)。8. 應用接口APIRT-Thread支持各類標準接口,方便移植各類應用程序:(1)兼容于POSIX(IEEEStd1003.1,2004版本)。(2)支持ARMCMSIS接口。(3)CMSISCORE。(4)CMSISDSP。(5)CMSISRTOS。(6)支持C++應用環(huán)境。9.2RT-Thread架構RT-Thread與其他很多RTOS如FreeRTOS、uC/OS的主要區(qū)別之一是,它不僅僅是一個實時內(nèi)核,還具備豐富的中間層組件。RT-Thread操作系統(tǒng)架構如圖9-5所示。從下往上依次包括內(nèi)核層、組件服務層和軟件包三層。圖9-5RT-Thread操作系統(tǒng)架構1.內(nèi)核層內(nèi)核層含RT-Thread內(nèi)核和libcpu/BSP。RT-Thread內(nèi)核負責多線程、調(diào)度、信號、郵箱、消息隊列、內(nèi)存和定時器等。libcpu/BSP含芯片移植和板級支持,與底層硬件相關。?2.組件服務層組件服務層采用模塊化設計,包括設備框架、低功耗管理、FinSH控制臺、WiFi管理器、USB協(xié)議棧、DFS虛擬文件系統(tǒng)、網(wǎng)絡架構、異常處理、鍵值數(shù)據(jù)庫等組件模塊,各組件模塊高內(nèi)聚、低耦合,是在RT-Thread內(nèi)核之上的上層軟件模塊。3.軟件包軟件包是運行于RTT物聯(lián)網(wǎng)操作系統(tǒng)平臺上,面向不同應用領域的通用軟件組件,由描述信息、源代碼、庫文件組成。RTT提供了開放的軟件包平臺,存放了大量官方提供或開發(fā)者提供的軟件包,這些軟件包具有很強的可重用性,極大地方便了開發(fā)者在最短時間內(nèi),完成應用開發(fā),是RTT生態(tài)的重要組成部分。9.3內(nèi)核基礎內(nèi)核是操作系統(tǒng)最基礎也是最重要的部分。RT-ThreadRT-Thread內(nèi)核及底層架構如圖9-6所示,內(nèi)核處于硬件層之上,內(nèi)核部分包括內(nèi)核庫、實時內(nèi)核實現(xiàn)。9.3.1RT-Thread內(nèi)核介紹圖9-6RT-Thread內(nèi)核及底層架構內(nèi)核庫是內(nèi)核獨立運行的精簡C庫子集,依編譯器不同,包含內(nèi)容略異。GNUGCC編譯器通常帶更多標準C庫實現(xiàn)。C庫提供strcpy、memcpy等函數(shù),RT-Thread用部分加rt_前綴避免重名。實時內(nèi)核實現(xiàn)對象管理、線程調(diào)度、通信、時鐘和內(nèi)存管理,最小占用3KBROM和1.2KBRAM。1.線程調(diào)度線程是RT-Thread中最小調(diào)度單位,調(diào)度算法為基于優(yōu)先級的全搶占式多線程調(diào)度。中斷、調(diào)度器鎖代碼不可搶占,其他部分均可搶占,包括調(diào)度器自身。支持最多256優(yōu)先級,默認32優(yōu)先級,0為最高,低優(yōu)先級給空閑線程,支持同優(yōu)先級時間片輪轉(zhuǎn)調(diào)度。2.時鐘管理RT-Thread時鐘管理基于時鐘節(jié)拍,最小時鐘單位。提供單次觸發(fā)定時器,事件發(fā)一次后停止。周期觸發(fā)定時器,定時周期事件,需手動停止。定時器支持HARD_TIMER和SOFTTIMER兩種模式。定時回調(diào)函數(shù)實現(xiàn)定時服務,用戶按實時性需求選擇。3.線程間同步RT-Thread用信號和互斥量實現(xiàn)線程同步,線程通過獲取釋放完成同步。互斥量采用優(yōu)先級繼承解決優(yōu)先級翻轉(zhuǎn),支持優(yōu)先級或先進先出等待方式。線程通過事件集發(fā)送接收同步,支持多事件“或”和“與”觸發(fā),適合等待多個事件。4.線程間通信RT-Thread支持郵箱和消息隊列通信,郵箱郵件固定4字節(jié),消息隊列接收變長消息。消息緩存在自身內(nèi)存,郵箱效率高于消息隊列,均可安全用于中斷服務例程。通信支持線程按優(yōu)先級或先進先出方式等待和獲取消息。5.內(nèi)存管理RT-Thread支持靜態(tài)內(nèi)存池管理,分配時間恒定。靜態(tài)內(nèi)存池空時,申請線程掛起或等待超時后放棄申請并返回。其他線程釋放內(nèi)存時,會喚醒掛起的申請線程。動態(tài)內(nèi)存堆管理提供針對小內(nèi)存和大內(nèi)存系統(tǒng)的slab算法。memheap管理多地址非連續(xù)內(nèi)存堆,實現(xiàn)多個內(nèi)存堆合一操作。6.I/O設備管理RT-Thread將PIN、I2C、SPI、USB、UART等外設統(tǒng)一注冊,建立設備管理子系統(tǒng),支持按名稱訪問。通過統(tǒng)一API訪問硬件,根據(jù)設備類型掛接事件,設備事件觸發(fā)時由驅(qū)動通知應用程序。啟動流程是了解一個系統(tǒng)的開始,RT-Thread支持多種平臺和多種編譯器,而rtthread_startup()函數(shù)是RTT規(guī)定的統(tǒng)一啟動入口,其執(zhí)行順序是:系統(tǒng)先從啟動文件開始運行,然后進入RTT啟動函數(shù)rtthread_startup(),最后進入用戶入口函數(shù)main()。以RT-ThreadStudio為例,用戶程序入口為位于main.c文件中的啟動流程main()函數(shù)。系統(tǒng)啟動后先運行startup_stm32f407.s文件中的匯編程序,完成堆棧指針設置、PC指針設置、系統(tǒng)時鐘配置、變量存儲設置等,最后運行“blen-try”指令后跳轉(zhuǎn)到components.c文件中調(diào)用entry()函數(shù),如圖9-7和圖9-8所示。9.3.2RT-Thread啟動流程圖9-7運行blentry()指令圖9-8調(diào)用entry()函數(shù)進而調(diào)用rtthread_startup()函數(shù),啟動RT-Thread操作系統(tǒng),如圖9-9所示。圖9-9調(diào)用rtthread_startup()函數(shù)在運行rt-thread_startup()函數(shù)時調(diào)用rt_application_init()函數(shù),創(chuàng)建并啟動main()線程,如圖9-10所示,等調(diào)度器工作后進入mian.c文件中運行main()函數(shù),完成系統(tǒng)啟動。圖9-10創(chuàng)建并啟動main()線程RT-Thread啟動流程如圖9-11所示。圖9-11RT-Thread啟動流程其中rtthreadstartup()函數(shù)的代碼參考書中內(nèi)容。一般MCU包含F(xiàn)lash和RAM兩類存儲空間,F(xiàn)lash相當于硬盤,RAM相當于內(nèi)存。RT-ThreadStudio將程序編譯后分為text、data和bss3個程序段,程序編譯結(jié)果如圖9-12所示,顯示了各程序段大小、目標文件(rtthread.elf)、占用Flash及RAM大小等信息。9.3.3RT-Thread程序內(nèi)存分布圖9-12程序編譯結(jié)果自動初始化機制是指初始化函數(shù)在系統(tǒng)啟動過程中被自動調(diào)用,需要在函數(shù)定義處通過宏定義的方式進行自動初始化聲明,無須顯式調(diào)用。例如在某驅(qū)動中通過宏定義告知系統(tǒng)啟動時需要調(diào)用的函數(shù),代碼如下:intxxx_init(void){?return0;}INIT_BOARD_EXPORT(xxx_init);9.3.4自動初始化機制代碼最后的INIT_BOARD_EXPORT(xxx_init)表示使用自動初始化功能,xxx_init()函數(shù)在系統(tǒng)初始化時會被自動調(diào)用。1.靜態(tài)內(nèi)核對象和動態(tài)內(nèi)核對象RT-Thread采用面向?qū)ο笤O計,線程、信號、互斥量、定時器等為內(nèi)核對象。內(nèi)核對象分靜態(tài)和動態(tài)兩種,靜態(tài)預分配資源占用RAM,時間確定,不依賴內(nèi)存堆管理器。動態(tài)對象運行時申請內(nèi)存,依賴內(nèi)存堆,刪除后釋放RAM,兩種方式根據(jù)環(huán)境需求選擇。2.內(nèi)核對象管理架構RTT內(nèi)核對象管理系統(tǒng)通過對象容器管理線程、信號等對象,鏈接鏈表,提高系統(tǒng)靈活性,不依賴內(nèi)存分配方式。RTT內(nèi)核對象容器及鏈表如圖9-14所示。9.3.5內(nèi)核對象模型圖9-14RTT內(nèi)核對象容器及鏈表9.4線程管理日常中解決大問題會分解為多個小問題,逐個解決。在多線程操作系統(tǒng),開發(fā)者將復雜應用劃分為可調(diào)度的小任務,合理執(zhí)行以滿足實時性能和時間要求。例如讓嵌人式系統(tǒng)執(zhí)行這樣的任務,即系統(tǒng)通過傳感器采集數(shù)據(jù),并通過顯示屏將數(shù)據(jù)顯示出來,在多線程實時系統(tǒng)中,可以將該任務分解成兩個子任務,如圖9-15所示。任務1不間斷地讀取傳感器數(shù)據(jù),并將數(shù)據(jù)寫到共享內(nèi)存中,任務2周期性地從共享內(nèi)存中讀取數(shù)據(jù),并將傳感器數(shù)據(jù)輸出到顯示屏上。圖9-15傳感器數(shù)據(jù)接收任務與顯示任務的切換執(zhí)行RT-Thread管理系統(tǒng)和用戶線程,分別由內(nèi)核和應用創(chuàng)建。線程對象從內(nèi)核對象容器分配,刪除線程時對應對象也被刪除。對象容器與線程對象如圖9-16所示,每個線程都有重要的屬性,如線程控制塊、線程棧、入口函數(shù)等。9.4.1線程管理的功能特點圖9-16對象容器與線程對象RT-Thread的搶占式調(diào)度器從就緒列表中選最高優(yōu)先級線程執(zhí)行,確保高優(yōu)先級任務優(yōu)先占用CPU。運行線程若使高優(yōu)先級線程就緒,當前線程讓出CPU,高優(yōu)先級線程立即運行。中斷使高優(yōu)先級線程就緒,中斷結(jié)束掛起被中斷線程,調(diào)度器保存上下文后切換線程。1.線程控制塊在RT-Thread中,線程控制塊由結(jié)構體structrtthread表示。線程控制塊是操作系統(tǒng)用于管理線程的數(shù)據(jù)結(jié)構,它會存放線程的一些信息,例如優(yōu)先級、線程名稱、線程狀態(tài)等,也包含線程與線程之間連接用的鏈表結(jié)構、線程等待事件集合等,詳細定義如下:/*線程控制塊*/structrt_thread{/*rt對象*/charname[RT_NAME_MAX];/*線程名稱*/rt_uint8_ttype;/*對象類型*/9.4.2線程的工作機制rt_uint8_tf1ags;/*標志位*/
rt_liatt1ist/*對象列表*/rc_1istttlist/*線程列表*//*棧指針與入口指針*/vaid*sp;/*棧指針*/vaid*entry;/*入口函數(shù)指針*/void*parameter;/*參數(shù)*/vaid*stack_addr;/*棧地址指針*/rt_uint32_tstack_sizer;/*棧大小*//*錯誤代碼*/rt_err_terror;/線程錯誤代碼/rt_uint8_tstat;/*線程狀態(tài)//優(yōu)先級*/rt_uint8_tcurrentpriority;/*當前優(yōu)先級*/rt_uint8_tInitpriority;/*初始優(yōu)先級*/rt_uint32_tnumber_mask;rt_ubase_tinit_tick;/*線程初始化計數(shù)值*/rt_ubase_tremaining_tick;/*線程剩余計數(shù)值*/structrt_timerthread_timer;/*內(nèi)置線程定時器*/vcid(cleanup)(structrt_thread*tid);/*線程退出清除函數(shù)*/rt_uint32_tuser_data;/*用戶數(shù)據(jù)*/};2.線程的重要屬性根據(jù)線程控制塊的定義,線程具有一些重要屬性,如線程名稱、線程入口函數(shù)、線程棧、線程優(yōu)先級、時間片、線程狀態(tài)、錯誤代碼等。(1)線程名稱。線程名稱即線程的名字,由用戶命名,命名規(guī)則遵循C語言變量命名規(guī)則,通常以字母開頭,線程名稱的最大長度由rtconfig.h中的宏RT_NAMEMAX指定,默認長度為8位,多余部分會被自動截掉。(2)線程棧。RT-Thread線程具有獨立的棧,當進行線程切換時,會將當前線程的上下文保存在棧中,當線程要恢復運行時,再從棧中讀取上下文信息進行恢復。線程棧的增長方向是與芯片構架密切相關的,RT-Thread3.1.0以前的版本均只支持棧由高地址向低地址增長,對于ARMCortexM架構,線程棧如圖9-17所示。圖9-17線程棧(ARM)(3)線程狀態(tài)。線程運行時僅一線程占CPU,RT-Thread中線程有5種狀態(tài),系統(tǒng)根據(jù)運行情況動態(tài)調(diào)整線程狀態(tài)。(4)線程優(yōu)先級。RT-Thread線程的優(yōu)先級表示線程被調(diào)度的優(yōu)先程度。每個線程都具有優(yōu)先級,線程越重要,被賦予的優(yōu)先級就越高,該線程被調(diào)度的可能性就越大。(5)時間片。每個線程都有時間片參數(shù),但時間片僅對優(yōu)先級相同的就緒狀態(tài)線程有效。假設有2個優(yōu)先級相同的就緒狀態(tài)線程A與B,A線程的時間片設置為10,B線程的時間片設置為5,那么當系統(tǒng)中不存在比A優(yōu)先級高的就緒狀態(tài)線程時,系統(tǒng)會在A、B線程間來回切換執(zhí)行,并且每次對A線程執(zhí)行10個節(jié)拍的時長,對B線程執(zhí)行5個節(jié)拍的時長,如圖9-18所示。圖9-18相同優(yōu)先級時間片輪轉(zhuǎn)(6)線程的入口函數(shù)。線程控制塊中的entry是線程的入口函數(shù),它是線程實現(xiàn)預期功能的函數(shù)。線程的入口函數(shù)由用戶設計實現(xiàn),一般有以下兩種代碼模式。①無限循環(huán)模式:在實時系統(tǒng)中,線程通常是被動式的。這是由實時系統(tǒng)的特性所決定的,實時系統(tǒng)通常總是等待外界事件的發(fā)生,而后進行相應的服務。voidthread_entry(void*paramenter){while(1){/*等待事件的發(fā)生*//*對事件進行服務、進行處理*/}}②順序執(zhí)行或有限次循環(huán)模式:簡單的順序語句、dowhile()或for()循環(huán)等,此類線程不會循環(huán)或不會永久循環(huán),可稱它們?yōu)椤耙淮涡浴本€程,它們一定會被執(zhí)行完畢。在執(zhí)行完畢后,線程將被系統(tǒng)自動刪除。staticvoidthread_entry(void*parameter){/*處理事務#1*/?/*處理事務#2*/?/*處理事務#3*/}3.線程狀態(tài)切換RT-Thread提供一系列的操作系統(tǒng)調(diào)用接口,使得線程的狀態(tài)在這5種狀態(tài)之間來回切換。幾種狀態(tài)之間的轉(zhuǎn)換關系如圖9-19所示。圖9-19線程狀態(tài)轉(zhuǎn)換圖4.系統(tǒng)線程系統(tǒng)線程是指由系統(tǒng)創(chuàng)建的線程,用戶線程是由用戶程序調(diào)用線程管理接口創(chuàng)建的線程,在RT-Thread內(nèi)核中的系統(tǒng)線程有空閑線程和主線程。(1)空閑線程。空閑線程是最低優(yōu)先級且永遠就緒,無其他就緒線程時被調(diào)度,通常死循環(huán)且不能掛起,有特殊用途。(2)主線程。在系統(tǒng)啟動時,系統(tǒng)會創(chuàng)建main線程,它的人口函數(shù)為main_thread_entry(),用戶的應用入口函數(shù)main()就是從這里真正開始的。系統(tǒng)調(diào)度器啟動后,main線程就開始運行,過程如圖9-20所示,用戶可以在main()函數(shù)里添加自己的應用程序初始化代碼。圖9-20主線程調(diào)用過程線程的相關操作如圖9-21所示,包括創(chuàng)建/初始化線程、啟動線程、運行線程、刪除/脫離線程。動態(tài)線程用rt_thread_create從堆自動分配棧和句柄,需初始化heap;靜態(tài)線程用rt_thread_init,棧和句柄由用戶分配。9.4.3線程的管理方式圖9-21線程相關操作1. 創(chuàng)建和刪除線程一個線程要成為可執(zhí)行的對象,就必須由操作系統(tǒng)的內(nèi)核來為它創(chuàng)建一個線程??梢酝ㄟ^如下接口創(chuàng)建一個動態(tài)線程:rt_thread_trt_thread_create(constchar*name,void(*entry)(void*parameter),void*parameter,rt_uint32_tstack_size,rt_uint8_tpriority,rt_uint32_ttick);2. 初始化和脫離線程線程的初始化可以使用下面的函數(shù)接口完成,它用于初始化靜態(tài)線程對象:rt_err_trt_thread_init(structrt_thread*thread,constchar*name,void(*entry)(void*parameter),void*parameter,void*stack_start,rt_uint32tstack_size,rt_uint8_tpriority,rt_uint32ttick);3. 啟動線程創(chuàng)建(初始化)的線程狀態(tài)處于初始狀態(tài),并未進入就緒線程的調(diào)度隊列,我們可以在線程初始化/創(chuàng)建成功后調(diào)用下面的函數(shù)接口讓該線程進入就緒狀態(tài):rt_err_trt_thread_startup(rt_thread_tthread);當調(diào)用這個函數(shù)時,線程的狀態(tài)會更改為就緒狀態(tài),并且線程會被放到相應優(yōu)先級隊列中等待調(diào)度。如果新啟動的線程優(yōu)先級比當前線程優(yōu)先級高,將立刻切換到這個新線程。下面介紹RT-Thread對線程操作的一些常用函數(shù)。1. 線程掛起函數(shù)rt_thread_suspend()掛起指定線程。被掛起的線程絕不會得到處理器的使用權,不管該線程具有什么優(yōu)先級。2. 線程恢復函數(shù)rt_thread_resume()線程恢復使掛起線程重入就緒,保留狀態(tài)并繼續(xù)運行,若最高優(yōu)先級則觸發(fā)上下文切換。9.4.4常用的線程函數(shù)如何使用RT-Thread的線程,先從最簡單的創(chuàng)建線程開始,點亮一個LED。1. 硬件初始化本節(jié)創(chuàng)建的線程需要用到開發(fā)板上的LED,所以先要將LED相關的函數(shù)初始化好,具體是在board.c的rt_hw_board_init()函數(shù)中初始化,具體見代碼清單參考書中內(nèi)容。2. 創(chuàng)建單線程—SRAM靜態(tài)內(nèi)存下面創(chuàng)建一個單線程,線程使用的棧和線程控制塊都使用靜態(tài)內(nèi)存,即預先定義好的全局變量,這些預先定義好的全局變量都存在內(nèi)部的SRAM中。9.4.5創(chuàng)建線程(1)定義線程函數(shù)。線程實際上就是一個無限循環(huán)且不帶返回值的C函數(shù)。目前,我們創(chuàng)建一個這樣的線程,讓開發(fā)板上面的LED燈以500ms的頻率閃爍,具體實現(xiàn)見代碼清單如下。定義線程函數(shù):1staticvoidled1_thread_entry(void*parameter)2{3 while(1)4{5LED1_ON; 6 rt_thread_delay(500); /*延時500個tick*/ 78 LED1_OFF; 910 rt_thread_delay(500); /*延時500個tick*/
11 } 12 } (2)定義線程棧。RT-Thread中線程獨立,??臻g單獨保存在全局變量中,棧占用MCURAM,多線程需更多RAM。MCU支持線程數(shù)受RAM限制,棧空間需地址對齊,ARM架構要求4字節(jié)對齊。通過ALIGN(RT_ALIGN_SIZE)語句實現(xiàn)棧地址對齊,確保變量地址滿足對齊要求。(3)定義線程控制塊。定義線程函數(shù)和棧后,還需定義線程控制塊(線程身份證),它是包含線程全部信息的結(jié)構體。(4)初始化線程。線程三要素是主體函數(shù)、棧和控制塊,RT-Thread用rt_thread_init()將這三者關聯(lián),令線程能被系統(tǒng)啟動。(5)啟動線程。當線程初始化好后,是處于線程初始態(tài)(RT_THREAD_INIT),并不能夠參與操作系統(tǒng)的調(diào)度,只有當線程進入就緒態(tài)(RT_THREAD_READY)之后才能參與操作系統(tǒng)的調(diào)度。線程由初始態(tài)進入就緒態(tài)可由函數(shù)rt_thread_startup()來實現(xiàn)。(6)main.c文件內(nèi)容。現(xiàn)在把線程主體,線程棧,線程控制塊這三部分代碼統(tǒng)一放到main.c中,具體程序代碼參考書中內(nèi)容。3. 下載驗證用DAP仿真將程序下載到野火STM32板,LED閃爍表明靜態(tài)內(nèi)存單線程已運行。當前例程線程棧和控制塊為靜態(tài),由用戶預定義,使用較少。一般在線程創(chuàng)建時動態(tài)分配棧和控制塊內(nèi)存,更常用。9.5消息隊列消息隊列是另一種常用的線程間通信方式,是郵箱的擴展。它可以應用于多種場合:線程間的消息交換、使用串口接收不定長數(shù)據(jù)等。RT-Thread中使用隊列數(shù)據(jù)結(jié)構實現(xiàn)線程異步通信工作,具有如下特性:(1)消息支持先進先出方式排隊與優(yōu)先級排隊方式,支持異步讀寫工作方式。(2)讀隊列支持超時機制。(3)支持發(fā)送緊急消息,這里的緊急消息是往隊列頭發(fā)送消息。(4)可以允許不同長度(不超過隊列節(jié)點最大值)的任意類型消息。(5)一個線程能夠從任意一個消息隊列接收和發(fā)送消息。(6)多個線程能夠從同一個消息隊列接收和發(fā)送消息。(7)當隊列使用結(jié)束后,需要通過刪除隊列操作釋放內(nèi)存函數(shù)回收。消息隊列緩存不定長消息,線程或中斷寫入,讀取線程空時掛起,有消息喚醒,支持異步通信。如圖9-22所示,線程或中斷服務例程可以將一條或多條消息放入消息隊列中。同樣,一個或多個線程也可以從消息隊列中獲得消息。當有多個消息發(fā)送到消息隊列時,通常將先進大消息隊列的消息先傳給線程,也就是說,線程先得到的是最先進入消息隊列的消息,即先進先出(FIFO)原則。9.5.1消息隊列的工作機制圖9-22消息隊列工作示意圖RT-Throad操作系統(tǒng)的消息隊列對象由多個元素組成,當消息隊列被創(chuàng)建時,它就被分配了消息隊列控制塊:消息隊列名稱、內(nèi)存緩沖區(qū)、消息大小以及隊列長度等。在RT-Thread中,消息隊列控制塊是操作系統(tǒng)用于管理消息隊列的一個數(shù)據(jù)結(jié)構,由結(jié)構體structrtmessagequeue表示。另外一種C表達方式rt_mq_t,表示的是消息隊列的句柄,在C語言中的實現(xiàn)是消息隊列控制塊的指針。消息隊列控制塊結(jié)構的詳細定義請見以下代碼:structrt_messagequeue{structrt_ipc_objectparent;void*msg_poo1,/*指向存放消息的消息池的指針*/rt_uint16_tmsg_size,/*每個消息的長度*/rt_uint16_t.max_msgs,/*最大能夠容納的消息數(shù)*/9.5.2消息隊列控制塊rt_uint16_tentry/*隊列中已有的消息數(shù)*/void*msg_queue_head,/*消息鏈表頭*/void*msg_queue_tail,/*消息鏈表尾*/void*msg_queue_free,/*空閑消息鏈表*/};typedefstructrt_messagequeue*rt_mq_tirt_messagequeue對象從rtipc_bject中派生,由IPC容器所管理。消息隊列控制塊是一個結(jié)構體,其中含有消息隊列相關的重要參數(shù),在消息隊列的功能實現(xiàn)中起著重要的作用。消息隊列的相關接口如圖9-23所示,對一個消息隊列的操作包含:創(chuàng)建/初始化消息隊列、發(fā)送消息、接收消息、刪除/脫離消息隊列。9.5.3消息隊列的管理方式圖9-23消息隊列相關接口?使用隊列模塊的典型流程如下:(1)創(chuàng)建消息隊列rt_mq_create。(2)寫隊列操作函數(shù)rt_mq_send。(3)讀隊列操作函數(shù)rt_mq_recv。(4) 刪除隊列rt_mq_delete。1.消息隊列創(chuàng)建函數(shù)rt_mq_create()消息隊列創(chuàng)建函數(shù)rt_mq_create()用于用戶自定義消息隊列的參數(shù),如長度、句柄和節(jié)點大小。定義隊列句柄并不等于創(chuàng)建隊列,必須調(diào)用此函數(shù)進行實際創(chuàng)建。函數(shù)成功創(chuàng)建時返回消息隊列句柄,失敗時返回RT_NULL。9.5.4 常用消息隊列的函數(shù)2.消息隊列刪除函數(shù)rt_mq_delete()消息隊列刪除函數(shù)rt_mq_delete()用于刪除指定的消息隊列并釋放其所有資源。刪除操作會喚醒因訪問此隊列而阻塞的線程,并從阻塞鏈表中移除它們。如果傳入的消息隊列句柄無效,則無法刪除該隊列。3.消息隊列發(fā)送消息函數(shù)rt_mq_send()rt_mq_send()允許線程或中斷服務程序向消息隊列發(fā)送消息。當消息隊列有空閑消息塊時,發(fā)送成功;否則返回錯誤碼-RT_EFULL。發(fā)送者需要指定消息隊列的句柄、消息內(nèi)容和消息大小。發(fā)送的消息會被復制到消息隊列尾部。4.消息隊列接收消息函數(shù)rt_mq_recv()rt_mq_recv()用于從消息隊列接收消息,支持阻塞機制,用戶可定義等待時間。接收成功后,消息隊列頭部的消息會被轉(zhuǎn)移到空閑消息鏈表中。此函數(shù)將接收到的消息存儲到用戶定義的地址和大小的緩沖區(qū)中。9.6信號信號(又稱為軟中斷信號),在軟件層次上是對中斷機制的一種模擬,在原理上,一個線程收到一個信號與處理器收到一個中斷請求是類似的。用于線程間異常通知,無需線程等待,線程用rt_thread_kill()發(fā)送信號。收到信號的線程對各種信號有不同的處理方法,處理方法可以分為三類:?(1)第一種是類似中斷的處理程序,對于需要處理的信號,線程可以指定處理函數(shù),由該函數(shù)來處理。9.6.1信號的工作機制(2)第二種方法是,忽略某個信號,對該信號不做任何處理,就像未發(fā)生過一樣。(3)第三種方法是,對該信號的處理保留系統(tǒng)的默認值。信號工作機制如圖9-24所示。假設線程1需要對信號進行處理,首先線程1安裝一個信號并解除阻塞,并在安裝的同時設定對信號的異常處理方式;然后其他線程可以給線程1發(fā)送信號,觸發(fā)線程1對該信號的處理。當信號被傳遞給線程1時,如果它正處于掛起狀態(tài),那會把狀態(tài)改為就緒狀態(tài)去處理對應的信號。如果它正處于運行狀態(tài),那么會在它當前的線程?;A上建立新棧幀空間去處理對應的信號,需要注意的是,使用的線程棧大小也會相應增加。圖9-24信號工作機制對于信號的操作,有以下幾種:安裝信號、阻塞信號、解除阻塞、發(fā)送信號、等待信號。信號的相關接口如圖圖9-25所示。9.6.2信號的管理方式圖9-25信號相關接口1.信號安裝線程需安裝信號,確定信號值與動作映射,指定接收信號時執(zhí)行的操作。其詳細定義請見以下代碼:rt_sighandler_trtsignal_install(intsigno,rt_sighandler_thandler);其中rt_sighandlert是定義信號處理函數(shù)的函數(shù)指針類型。在安裝信號時設定handler參數(shù),決定了該信號的不同的處理方法。處理方法可以分為三種:(1)類似中斷的處理方式,參數(shù)指向當信號發(fā)生時用戶自定義的處理函數(shù),由該函數(shù)來處理。(2)參數(shù)設為SIG_IGN,忽略某個信號,對該信號不做任何處理,就像未發(fā)生過一樣。(3)參數(shù)設為SIG_DFL,系統(tǒng)會調(diào)用默認的處理函數(shù)_signal_default_handler()。2.阻塞信號阻塞信號,也可以理解為屏蔽信號。如果該信號被阻塞,則該信號將不會傳達給安裝此信號的線程,也不會引發(fā)軟中斷處理。調(diào)用rt_signal_mask()可以使信號阻塞:voidrt_signalmask(intsigno);3.解除信號阻塞線程中可以安裝好幾個信號,使用此函數(shù)可以對其中一些信號給予“關注”,那么發(fā)送這些信號都會引發(fā)該線程的軟中斷。調(diào)用rt_signal_unmask()可以解除信號阻塞:voidrt_signal_unmask(intsigno);4.發(fā)送信號當需要進行異常處理時,可以給設定了處理異常的線程發(fā)送信號,調(diào)用rt_thread_kill()可以向任何線程發(fā)送信號:intrt_thread_kill(rt_threadttid,intsig);5.等待信號等待set信號的到來,如果沒有等到該信號,則將線程掛起,直到等到該信號或者等待時間超過指定的超時時間timeout。如果等到了該信號,則將指向該信號體的指針存入si,下面是等待信號的函數(shù)。intrt_signal_wait(constrt_sigsett*set,rt_siginfo_t*si,rt_int32ttimeout);其中rtsiginfo_t是定義信號信息的數(shù)據(jù)類型。1.信號創(chuàng)建函數(shù)rt_sem_create()信號創(chuàng)建函數(shù)rt_sem_create()用于創(chuàng)建二值或計數(shù)信號。用戶需要傳入信號名稱、初始值、阻塞喚醒策略和信號句柄。二值信號的取值范圍是0和1,計數(shù)信號可用個數(shù)范圍是0~65535。2.信號刪除函數(shù)rt_sem_delete()信號刪除函數(shù)rt_sem_delete()刪除指定信號并釋放其資源。刪除操作會喚醒因訪問此信號而阻塞的線程,并從阻塞鏈表中移除它們。如果信號未創(chuàng)建,則無法刪除。9.6.3常用信號函數(shù)接口3.信號釋放函數(shù)rt_sem_release()rt_sem_release()用于釋放信號,每調(diào)用一次該函數(shù)就釋放一個信號。二值信號的范圍為0和1,計數(shù)信號的范圍為0~65535,不能無限制釋放信號。釋放信號后,其他線程可以獲取已釋放的信號。4.信號獲取函數(shù)rt_sem_take()信號獲取函數(shù)rt_sem_take()用于獲取信號。當信號有效時,線程獲取后信號值減一,信號值為零時,線程將進入阻塞態(tài)。獲取信號時需指定等待時間,超時未獲取到信號返回-RT_ETIMEOUT。9.7互斥量互斥量又稱互斥型信號,是一種特殊的二值信號,它和信號不同的是,它支持互斥量所有權、遞歸訪問以及防止優(yōu)先級翻轉(zhuǎn)的特性,用于實現(xiàn)對臨界資源的獨占式處理。任意時刻互斥量的狀態(tài)只有兩種,開鎖或閉鎖。線程持有互斥量時鎖閉鎖,釋放時開鎖。支持遞歸訪問,持有線程可重復鎖定,無掛起,不同于普通信號會死鎖。9.7.1 互斥量的基本概念RT-Thread用優(yōu)先級繼承算法防止優(yōu)先級翻轉(zhuǎn),提升低優(yōu)先級線程優(yōu)先級至最高等待線程水平,執(zhí)行完釋放資源后恢復。互斥量支持優(yōu)先級繼承,信號不支持,保證高優(yōu)先級線程阻塞時間最短,降低優(yōu)先級翻轉(zhuǎn)危害。舉個例子,現(xiàn)在有3個線程分別為H線程(High)、M線程(Middle)、L線程(Low),3個線程的優(yōu)先級順序為H線程>M線程>L線程。H線程可打斷M和L,M可打斷L。若資源被L占用,H申請資源阻塞,優(yōu)先級翻轉(zhuǎn)現(xiàn)象出現(xiàn)。此時M喚醒并搶占CPU,延遲L線程繼續(xù)執(zhí)行,導致H等待時間變長。9.7.2 互斥量的優(yōu)先級繼承機制最高優(yōu)先級H因低優(yōu)先級L和中間優(yōu)先級M變得阻塞,響應變慢,不被允許。無優(yōu)先級繼承時,資源保護導致優(yōu)先級翻轉(zhuǎn),嚴重影響系統(tǒng)響應與穩(wěn)定性。優(yōu)先級翻轉(zhuǎn)圖解如圖9-26所示。圖9-26優(yōu)先級翻轉(zhuǎn)圖解優(yōu)先級繼承9-27所示。圖9-27優(yōu)先級繼承多線程中,多個線程需獨占訪問同一臨界資源,RT-Thread用互斥量保護資源,避免訪問沖突。線程獲得互斥量后,互斥量閉鎖,其他線程等待,確保資源獨占訪問。等待線程按用戶定義時間等待,直到互斥量釋放,方可訪問資源?;コ饬可湘i解鎖交替,保證任一時刻僅一線程訪問臨界資源,確保安全。互斥量工作機制如圖9-28所示。9.7.3 互斥量的工作機制圖9-28互斥量工作機制在RT-Thread中,互斥量控制塊是操作系統(tǒng)用于管理互斥量的一個數(shù)據(jù)結(jié)構,由結(jié)構體structrt_mutex表示。另外一種C表達方式rt_mutext,表示的是互斥量的句柄,在C語言中的實現(xiàn)是指互斥量控制塊的指針?;コ饬靠刂茐K結(jié)構的詳細定義如下。structrt_mutex{structrt_ipc_objectparent;/*繼承自rt_ipc_object*/rt_uint16_tvalue;/*互斥量的值*/rt_uint8_toriginalpriority;/*持有線程的原始優(yōu)先級*/rt_uint8_thold;/*持有線程的持有次數(shù)*/structrt_thread*owner;/*當前擁有互斥量的線程*/9.7.4 互斥量控制塊};/*rt_mutextt為指向互斥量結(jié)構體的指針類型*/typedefstructrt_mutex*rt_mutex_t;rt_mutex對象從rt_ipc_object中派生,由IPC容器所管理?;コ饬靠刂茐K中含有互斥量相關的重要參數(shù),在互斥量功能的實現(xiàn)中起著重要的作用。互斥量相關接口如圖9-29所示。對一個互斥量的操作包含創(chuàng)建/初始化互斥量、獲取互斥量、釋放互斥量、刪除/脫離互斥量。9.7.5互斥量的管理方式圖9-29互斥量相關接口1.創(chuàng)建和刪除互斥量創(chuàng)建一個互斥量時,內(nèi)核首先創(chuàng)建一個互斥量控制塊,然后完成對該控制塊的初始化工作。創(chuàng)建互斥量使用下面的函數(shù)接口:rt_mutex_trt_mutex_create(constchar*name,rt_uint8_tflag);調(diào)用rt_mutex_create函數(shù)創(chuàng)建互斥量,分配并初始化mutex對象及IPC父類。flag為RT_IPC_FLAG_PRIO時,高優(yōu)先級線程優(yōu)先獲資源;為RT_IPC_FLAG_FIFO時,線程按先來先得順序獲資源。當不再使用互斥量時,可通過刪除互斥量以釋放系統(tǒng)資源,這適用于動態(tài)創(chuàng)建的互斥量。刪除互斥量使用下面的函數(shù)接口:rt_err_trt_mutex_delete(rt_mutex_tmutex);當刪除一個互斥量時,所有等待此互斥量的線程都將被喚醒,等待線程獲得的返回值是-RTERROR。然后系統(tǒng)將該互斥量從內(nèi)核對象管理器鏈表中刪除并釋放互斥量占用的內(nèi)存空間。2.初始化和脫離互斥量靜態(tài)互斥量對象的內(nèi)存是在系統(tǒng)編譯時由編譯器分配的,一般位于讀寫數(shù)據(jù)段或未初始化數(shù)據(jù)段中。在使用這類靜態(tài)互斥量對象前,需要先進行初始化。初始化互斥量使用下面的函數(shù)接口:rt_err_trt_mutex_init(rt_mutex_tmutex,constchar*name,rt_uint8_tflag);脫離互斥量使用下面的函數(shù)接口:rt_err_trt_mutex_detach(rt_mutextmutex);3.獲取互斥量當線程獲取了互斥量,該線程就有了該互斥量的所有權,即某一時刻一個互斥量只能被一個線程持有。獲取互斥量使用下面的函數(shù)接口:
rt_err_trt_mutex_take(rt_mutex_tmutex,rt_int32_ttime);4.釋放互斥量當線程完成互斥資源的訪問后,應盡快釋放它占有的互斥量,使得其他線程能及時獲取該互斥量。釋放互斥量使用下面的函數(shù)接口:
rt_err_trt_mutex_release(rtmutex_tmutex);只有持有互斥量的線程才能釋放,釋放一次持有計數(shù)減1。計數(shù)為零時,互斥量變可用,等待線程被喚醒。持有時優(yōu)先級提升,釋放后優(yōu)先級恢復,防止優(yōu)先級反轉(zhuǎn)。該機制保障系統(tǒng)優(yōu)先級合理穩(wěn)定,避免長期優(yōu)先級異常。1.互斥量創(chuàng)建函數(shù)rt_mutex_create()rt_mutex_create()用于創(chuàng)建互斥量,保護臨界資源。用戶需定義互斥量句柄,指定互斥量名稱。創(chuàng)建成功返回互斥量句柄,否則返回RT_NULL。2.互斥量刪除函數(shù)rt_mutex_delete()rt_mutex_delete()根據(jù)互斥量句柄刪除互斥量,系統(tǒng)回收資源。刪除時,所有阻塞在互斥量的線程被喚醒,返回錯誤碼-RT_ERROR,互斥量句柄失效。9.7.6互斥量函數(shù)接口3.互斥量釋放函數(shù)rt_mutex_release()線程使用資源后調(diào)用rt_mutex_release()釋放互斥量。此函數(shù)減持有計數(shù),持有計數(shù)為零時,互斥量變?yōu)殚_鎖狀態(tài),等待線程被喚醒。線程優(yōu)先級恢復原設定。4.互斥量獲取函數(shù)rt_mutex_take()線程調(diào)用rt_mutex_take()獲取互斥量的所有權。當互斥量處于開鎖狀態(tài)時,線程可成功獲取。否則線程被掛起,等待持有線程釋放互斥量。持有值會遞增。9.8事件集事件集實現(xiàn)線程間同步通信,無數(shù)據(jù)傳輸。支持一對多、多對多同步,線程可等待任意或全部事件發(fā)生喚醒,多線程同步多事件。事件集合用32位無符號整型表示,每位代表一個事件。邏輯或為獨立型同步,任一事件發(fā)生喚醒線程;邏輯與為關聯(lián)型同步,所有事件發(fā)生喚醒線程。多線程環(huán)境下,線程之間往往需要同步操作,一個事件發(fā)生即是一個同步。事件可以提供一對多、多對多的同步操作。一對多同步模型:一個線程等待多個事件的觸發(fā);多對多同步模型:多個線程等待多個事件的觸發(fā)。9.8.1事件集的基本概念線程可以通過創(chuàng)建事件來實現(xiàn)事件的觸發(fā)和等待操作。RT-Thread的事件僅用于同步,不提供數(shù)據(jù)傳輸功能。RT-Thread提供的事件集具有如下特點:(1)事件與線程相關聯(lián),事件獨立。32位事件集合標識線程發(fā)生的事件類型,每位代表一種事件,0未發(fā)生,1已發(fā)生。(2)事件僅用于同步,不提供數(shù)據(jù)傳輸功能。(3)事件無排隊性,即多次向線程發(fā)送同一事件(如果線程還未來得及讀走),等效于只發(fā)送一次。(4)允許多個線程對同一事件進行讀寫操作。(5)支持事件等待超時機制。接收事件時可按感興趣事件類型接收,成功后用RT_EVENT_FLAG_CLEAR清除已接收事件,否則不清除。用戶可自定義讀取模式,等待全部或任意感興趣事件。發(fā)送事件時設置對應位為1,可同時寫多個事件,觸發(fā)線程調(diào)度。清除事件時精準清零對應位,事件獨立管理,不綁定線程。事件集合為32位變量,每位表一事件,0未發(fā)生,1已觸發(fā),支持最多32種事件。事件集合set(一個32位的變量)如圖9-30所示。9.8.2 事件集的工作機制圖9-30事件集合set(一個32位的變量)事件喚醒機制,當線程因為等待某個或者多個事件發(fā)生而進入阻塞態(tài),當事件發(fā)生的時候會被喚醒,事件喚醒線程示意圖如圖9-31所示。圖9-31事件喚醒線程示意圖線程1用邏輯或(RT_EVENT_FLAG_OR)關注事件3或事件5,任一觸發(fā)即可喚醒線程并處理。線程2用邏輯與(RT_EVENT_FLAG_AND)關注事件3和事件5,需兩事件皆觸發(fā)才喚醒線程處理。僅有一個事件觸發(fā)時,線程2繼續(xù)等待另一個事件發(fā)生后才被喚醒。接收函數(shù)若option設置清除事件位,線程喚醒后事件3和事件5標志位會被清零防止重復處理。若不清除標志位,事件繼續(xù)保持設置狀態(tài),允許其他線程后續(xù)喚醒處理這些事件。在RT-Thread中,事件集控制塊是操作系統(tǒng)用于管理事件的一個數(shù)據(jù)結(jié)構,由結(jié)構體structrt_event表示。另外一種C表達方式rt_eventt表示的是事件集的句柄,在C語言中的實現(xiàn)是事件集控制塊的指針。事件集控制塊結(jié)構的詳細定義如下。structrt_event{structrt_ipc_objectparent;/*繼承自rt_ipc_object類*//*事件集合,每一位表示1個事件,位的值可以標記某事件是否發(fā)生*/rt_uint32tset;};/*rt_eventt是指向事件結(jié)構體的指針類型*/9.8.3事件集控制塊typedefstructrt_event*rt_event_t;rt_event對象從rt_ipc_object中派生,由IPC容器所管理。事件集控制塊中含有與事件集相關的重要參數(shù),在事件集功能的實現(xiàn)中起著重要的作用。事件集相關接口如圖9-32所示,對一個事件集的操作包含:創(chuàng)建/初始化事件集、發(fā)送事件、接收事件、刪除/脫離事件集。9.8.4事件集的管理方式圖9-32事件相關接口1.創(chuàng)建和刪除事件集當創(chuàng)建一個事件集時,內(nèi)核首先創(chuàng)建一個事件集控制塊,然后對該事件集控制塊進行基本的初始化,創(chuàng)建事件集使用下面的函數(shù)接口:rt_event_trt_eventcreate(constchar*name,rt_uint8_tflag);刪除事件集可以使用下面的函數(shù)接口:rt_err_trt_event_delete(rtevent_tevent);2.初始化和脫離事件集靜態(tài)事件集對象的內(nèi)存是在系統(tǒng)編譯時由編譯器分配的,一般放于讀寫數(shù)據(jù)段或未初始化數(shù)據(jù)段中。在使用靜態(tài)事件集對象前,需要先對它進行初始化操作。初始化事件集使用下面的函數(shù)接口:rt_err_trt_event_init(rt_eventtevent,constchar*name,rt_uint8_tflag);脫離事件集使用下面的函數(shù)接口:rt_err_trt_eventdetach(rt_event_tevent);3.發(fā)送事件發(fā)送事件函數(shù)可以發(fā)送事件集中的一個或多個事件,如下:rt_err_trt_event_send(rt_event_tevent,rt_uint32_tset);使用該函數(shù)接口時,通過參數(shù)set指定的事件標志來設定event事件集對象的事件標志值,然后遍歷event事件集對象上的等待線程鏈表,判斷是否有線程的事件激活要求與當前event對象事件標志值匹配,如果有,則喚醒該線程。4.接收事件內(nèi)核用32位無符號整數(shù)表示事件集,每位代表一個事件。通過“邏輯與”或“邏輯或”參數(shù),線程分別在所有或任一事件發(fā)生時被激活。接收事件使用下面的函數(shù)接口:rt_err_trt_event_recv(rt_event_tevent,rt_uint32_tset,rt_uint8_toption,rt_int32_ttimeout,rt_uint32_t*recved);1.事件創(chuàng)建函數(shù)rt_event_create()rt_event_create()用于創(chuàng)建事件對象。內(nèi)核初始化事件控制塊,成功時返回事件句柄,否則返回RT_NULL。需要定義指向事件控制塊的指針,即事件句柄。2.事件刪除函數(shù)rt_event_delete()rt_event_delete()用來刪除事件對象并釋放系統(tǒng)資源,需傳入事件句柄執(zhí)行刪除操作。此操作適用于一次性或不再使用事件,防止資源浪費和內(nèi)存泄漏,提高系統(tǒng)效率。9.8.5事件函數(shù)接口3.事件發(fā)送函數(shù)rt_event_send()rt_event_send()通過參數(shù)設定事件標志位,遍歷等待線程列表,喚醒符合條件的線程。即設置事件標志位為1,并查看是否有線程等待該事件,從而喚醒線程。4.事件接收函數(shù)rt_event_recv()rt_event_recv()檢查事件是否發(fā)生,并獲取事件標記。用戶通過“邏輯與”、“邏輯或”等操作接收感興趣的事件。函數(shù)實現(xiàn)了超時等待機制,返回RT_EOK,-RT_ETIMEOUT,或-RT_ERROR。9.9軟件定時器定時器,是指從指定的時刻開始,經(jīng)過一個指定時間,然后觸發(fā)一個超時事件,用戶可以自定義定時器的周期與頻率。類似生活中的鬧鐘,我們可以設置鬧鐘每天什么時候響,還能設置響的次數(shù),是響一次還是每天都響。定時器有硬件定時器和軟件定時器之分:硬件定時器由芯片提供,外部晶振輸入時鐘,配置寄存器控制,到點觸發(fā)中斷,精度高達納秒級。軟件定時器基于硬件定時器,由系統(tǒng)提供接口,不受硬件資源限制,實現(xiàn)類似功能。9.9.1 軟件定時器的基本概念硬件定時器到時自動中斷,用戶在中斷中處理;軟件定時器指定超時函數(shù),到時調(diào)用處理操作。軟件定時器觸發(fā)超時函數(shù),依系統(tǒng)時鐘周期定時。超時函數(shù)快進快出,不能阻塞線程運行。定時周期是兩次超時函數(shù)觸發(fā)的Tick間隔,通?;赟ysTick作為基礎時鐘。RT-Thread操作系統(tǒng)提供軟件定時器功能,軟件定時器的使用相當于擴展了定時器的數(shù)量,允許創(chuàng)建更多的定時業(yè)務。RT-Thread軟件定時器具有如下功能:(1)靜態(tài)裁剪:能通過宏關閉軟件定時器功能。(2)軟件定時器創(chuàng)建。(3)軟件定時器啟動。(4)軟件定時器停止。(5)軟件定時器刪除。周期模式:這個定時器會按照設置的定時時間循環(huán)執(zhí)行超時函數(shù),直到用戶將定時器刪除,軟件定時器的單次模式與周期模式如圖9-33所示。圖9-33軟件定時器的單次模式與周期模式RT-Thread創(chuàng)建定時器可選軟硬件,硬件定時器超時函數(shù)在中斷上下文,軟件定時器超時函數(shù)在線程上下文。RT-Thread中在rtdef.h中定義了相關的宏定義來選擇定時器的工作模式:(1)RT_TIMER_FLAG_HARD_TIMER為硬件定時器。(2)RT_TIMER_FLAG_SOFT_TIMER為軟件定時器。軟件定時器為系統(tǒng)資源,創(chuàng)建時分配內(nèi)存。啟動后根據(jù)rt_tick和設定時間計算喚醒timeout,掛入rt_soft_timer_list列表。在RT-Thread定時器模塊中維護著兩個重要的全局變量:(1)rt_tick,它是一個32位無符號的變量,用于記錄當前系統(tǒng)經(jīng)過的tick時間,當硬件定時器中斷來臨時,它將自動增加1。(2)新激活的定時器按超時升序插入rt_soft_timer_list。定時器線程掃描首個定時器,超時則調(diào)用超時函數(shù),否則線程休眠,因后續(xù)定時器時間更晚。9.9.2 軟件定時器的工作機制使用軟件定時器時候要注意以下幾點:(1)軟件定時器的超時函數(shù)中應快進快出,絕對不允許使用任何可能引軟件定時器起線程掛起或者阻塞的API接口,在超時函數(shù)中也絕對不允許出現(xiàn)死循環(huán)。(2)軟件定時器占用一個隊列和線程資源,線程優(yōu)先級默認RT_TIMER_THREAD_PRIO,確保定時器及時響應和平衡資源分配。(3)創(chuàng)建單次軟件定時器,該定時器超時執(zhí)行完超時函數(shù)后,系統(tǒng)會自動刪除該軟件定時器,并回收資源。(4)定時器線程的堆棧大小默認為RT_TIMER_THREAD_STACK_SIZE,512個字節(jié)。RT-Thread給用戶提供的只是一些基礎函數(shù),使用任何一個內(nèi)核的資源都需要用戶自己去創(chuàng)建,就像線程、信號等這些RT-Thread的資源,所以,使用軟件定時器也是需要我們自己去創(chuàng)建的,軟件定時器的創(chuàng)建函數(shù)使用起來是很簡單的,軟件定時器的超時函數(shù)需要自己實現(xiàn),軟件定時器的工作模式以及定時器的定時時間按需選擇即可。9.9.3 軟件定時器的使用9.10郵箱郵箱在操作系統(tǒng)中是一種常用的IPC通信方式,郵箱可以在線程與線程之間。郵箱通信開銷低效高,常用于線程間及中斷與線程間消息傳遞,適合傳指針等小數(shù)據(jù)。每封郵件固定4字節(jié),適合存指針,大消息通過指針傳遞緩沖區(qū)地址。線程讀取郵箱消息,無郵件時按阻塞時間掛起,有消息時喚醒線程,屬于異步通信。郵箱支持多個郵件及多線程讀取,遵循FIFO原則,且線程優(yōu)先級高者優(yōu)先獲得郵件。9.9.1郵箱的基本概念RT-Thread中使用郵箱實現(xiàn)線程異步通信工作,具有如下特性:(1)郵件支持先進先出方式排隊與優(yōu)先級排隊方式,支持異步讀寫工作方式。(2)發(fā)送與接收郵件均支持超時機制。(3)一個線程能夠從任意一個消息隊列接收和發(fā)送郵件。(4)多個線程能夠向同一個郵箱發(fā)送郵件和從中接收郵件。(5)郵箱中的每一封郵件只能容納固定的4字節(jié)內(nèi)容(可以存放地址)。(6)當隊列使用結(jié)束后,需要通過刪除郵箱以釋放內(nèi)存。RT-Thread操作系統(tǒng)的郵箱用于線程間通信,特點是開銷比較低,效率較高。郵箱中的每一封郵件只能容納固定的4字節(jié)內(nèi)容(針對32位處理系統(tǒng),指針的大小即為4個字節(jié),所
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025新疆科技學院第三批招聘具有高級職稱的事業(yè)編制專任教師備考題庫(32人)及一套參考答案詳解
- 2026中國武夷實業(yè)股份有限公司國際事業(yè)部招聘1人備考題庫有完整答案詳解
- 2025湖北武漢市蔡甸區(qū)公立學校招聘4人備考題庫及答案詳解1套
- 2025廣西柳州市林業(yè)科學研究所招聘編外聘用人員1人備考題庫及參考答案詳解1套
- 2025雄安人才服務有限公司市場營銷類崗位招聘5人備考題庫附答案詳解
- 2026廣西賀州市昭平縣赴玉林師范學院招聘教師68人備考題庫附答案詳解
- 2026四川自貢市消防救援支隊第一批次面向社會招錄政府專職消防員48人備考題庫完整參考答案詳解
- 2025云南西雙版納州景洪市城市投資開發(fā)有限公司第三次社會招聘4人備考題庫及參考答案詳解
- 2026北京建筑大學第一批次聘用制崗位招聘16人備考題庫及完整答案詳解
- 2026廣東深圳市龍崗區(qū)半導體與集成電路生態(tài)促進中心選調(diào)事業(yè)單位工作人員4人備考題庫有答案詳解
- 兒童呼吸道感染用藥指導
- 防意外傷害安全班會課件
- 2025年國家基本公共衛(wèi)生服務考試試題(附答案)
- 2025年醫(yī)院社區(qū)衛(wèi)生服務中心工作總結(jié)及2026年工作計劃
- 2025-2026學年北師大版七年級生物上冊知識點清單
- 委托作品協(xié)議書
- 食品加工廠乳制品設備安裝方案
- 2025至2030中國芳綸纖維行業(yè)發(fā)展分析及市場發(fā)展趨勢分析與未來投資戰(zhàn)略咨詢研究報告
- 尾牙宴活動策劃方案(3篇)
- 魯教版(2024)五四制英語七年級上冊全冊綜合復習默寫 (含答案)
- 生蠔課件教學課件
評論
0/150
提交評論