版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、目 錄 摘摘 要要 .2 2 第一章第一章嵌入式系統(tǒng)簡介嵌入式系統(tǒng)簡介 .3 3 1.1 研究背景.3 1.2 嵌入式系統(tǒng)的發(fā)展?fàn)顩r.3 第二章第二章 uc/os-iiuc/os-ii 任務(wù)間通訊與同步的實(shí)現(xiàn)任務(wù)間通訊與同步的實(shí)現(xiàn).5 5 2.1 開發(fā)環(huán)境介紹.5 2.1.1 jx44b0 教學(xué)實(shí)驗(yàn)系統(tǒng)的組成.5 2.1.2 adt ide 集成開發(fā)環(huán)境.5 2.2 任務(wù)間通訊與同步的實(shí)現(xiàn)步驟.6 2.2.1 事件控制塊 ecb .8 2.2.2 初始化一個(gè)事件控制塊,oseventwaitlistinit().12 2.2.3 使一個(gè)任務(wù)進(jìn)入就緒態(tài),oseventtaskrdy().12 2
2、.2.4 使一個(gè)任務(wù)進(jìn)入等待某事件發(fā)生狀態(tài), oseventtaskwait().15 2.2.5 信號(hào)量.16 2.2.7 郵箱.22 結(jié)束語結(jié)束語 .2727 參考文獻(xiàn)參考文獻(xiàn) .2828 致致 謝謝 .2929 摘摘 要要 嵌入式系統(tǒng)的迅速發(fā)展,對(duì)人類社會(huì)諸多領(lǐng)域產(chǎn)生了巨大的影響。在嵌入式的 操作系統(tǒng)中,c/os-ii 以其優(yōu)秀的性能越來越引起人們的關(guān)注。在今天,嵌入式 操作系統(tǒng)層出不窮,而且他們以其各自不同的特色廣泛分布于通信、航空航天、汽 車、醫(yī)療、電子消費(fèi)等不同的領(lǐng)域。因此,開發(fā)和架構(gòu)這種操作系統(tǒng)是符合時(shí)代發(fā) 展的需要。研究嵌入式系統(tǒng) uc/os-ii 任務(wù)間通訊和同步旨在提高通信
3、速度和安全 性,研究用幾種不同的方法(如用宏、函數(shù)、信號(hào)量、郵箱、隊(duì)列)實(shí)現(xiàn) uc/os-ii 任務(wù)間通訊和同步,保護(hù)任務(wù)之間的共享數(shù)據(jù)具有很好的實(shí)用性??紤]到設(shè)計(jì)的通 用性,選擇在 jj44b0 arm 嵌入式開發(fā)環(huán)境下,實(shí)現(xiàn)對(duì) uc/os-ii 任務(wù)間通訊和同 步功能的設(shè)計(jì),并實(shí)現(xiàn) uc/os-ii 操作系統(tǒng)下使用信號(hào)量、郵箱、隊(duì)列解決任務(wù)之間 的同步問題,探討 uc/os-ii 操作系統(tǒng)下任務(wù)間通訊的方法。 關(guān)鍵字關(guān)鍵字: : 嵌入式系統(tǒng), c/os-ii,通訊和同步,arm 第一章 嵌入式系統(tǒng)簡介 1.1 研究背景 近年來,隨著軟件資源的成熟和完善,嵌入式系統(tǒng)的發(fā)展可謂日新越異,其應(yīng)
4、用更是涉及金融、航天、電信、網(wǎng)絡(luò)、信息家電、醫(yī)療、工業(yè)控制、軍事等各個(gè)領(lǐng) 域,以致一些學(xué)者斷言嵌入式技術(shù)將成為后pc時(shí)代的主宰;同時(shí)可實(shí)現(xiàn)強(qiáng)大功能的 risc、dsp架構(gòu)芯片不斷涌現(xiàn),我國也令人可喜地推出了龍芯、方舟等 32 位嵌入式 處理器。目前,嵌入式技術(shù)已成為通信和消費(fèi)類產(chǎn)品的共同發(fā)展方向。嵌入式系統(tǒng) 幾乎包括了生活中的所有電器設(shè)備,如掌上、移動(dòng)計(jì)算設(shè)備、電視機(jī)頂盒、 手機(jī)上網(wǎng)、數(shù)字電視、多媒體、汽車、微波爐、數(shù)字相機(jī)、家庭自動(dòng)化系統(tǒng)、電梯、 空調(diào)、安全系統(tǒng)、自動(dòng)售貨機(jī)、蜂窩式電話、消費(fèi)電子設(shè)備、工業(yè)自動(dòng)化儀表與醫(yī) 療儀器等。嵌入式系統(tǒng)自其誕生以來已經(jīng)經(jīng)歷了幾十年的風(fēng)風(fēng)雨雨。在經(jīng)濟(jì)不景氣
5、 的現(xiàn)在,許多人相信資訊家電、智慧型手機(jī)與pda等產(chǎn)品將是挽救臺(tái)灣pc王國的最 後一張王牌,而這張王牌的正確名稱應(yīng)該稱作嵌入式系統(tǒng) (embedded system), 上述所有的產(chǎn)品全都屬於嵌入式系統(tǒng)的一項(xiàng)分支。 1.2 嵌入式系統(tǒng)的發(fā)展?fàn)顩r 在展望未來之前,先來大致回顧一下嵌入式系統(tǒng)的歷史。1987 年到 1997 年的 十年是asic風(fēng)行的十年,而后的十年,也就是 1997 年到 2007 年是現(xiàn)場可編程器件 的大好時(shí)光,制造標(biāo)準(zhǔn)化但應(yīng)用定制化是這個(gè)階段的明顯特征。 圖 1.0 “許氏循環(huán)”和“牧本浪潮”與嵌入式系統(tǒng)核心技術(shù)發(fā)展規(guī)律 圖 1.0 通過我國科學(xué)家許居衍院士發(fā)表的“許氏循環(huán)”
6、以及日本科學(xué)家牧本次 夫的“牧本浪潮”(makimotos wave)總結(jié)和預(yù)測了嵌入式系統(tǒng)核心技術(shù)的發(fā)展規(guī) 律。通過這張圖我們不難看出應(yīng)用微電子技術(shù)成果之上的嵌入式系統(tǒng)的演進(jìn)過程。 1977 到 1987 年的十年是嵌入式系統(tǒng)微處理器時(shí)代,嵌入式系統(tǒng)通過對(duì)微處理器和 微控制器軟件編程來實(shí)現(xiàn)板極的功能,隨著時(shí)代的發(fā)展與科學(xué)的進(jìn)步,軟編程已經(jīng) 漸漸不能適應(yīng)嵌入式系統(tǒng)對(duì)于板極功能實(shí)現(xiàn)的要求,于是,就出現(xiàn)了硬編程這一概 念。當(dāng)今,嵌入式系統(tǒng)對(duì)軟硬雙可編程提出了需求,軟核進(jìn)入fpga成為了時(shí)代的需 要,因此嵌入式系統(tǒng)技術(shù)也隨之進(jìn)入了軟核(soft core)時(shí)代。就目前而言, fpga的利用率已經(jīng)超過
7、了 90,應(yīng)用fpga的產(chǎn)品也廣泛出現(xiàn)在我們的日常生活之中, 如pdp/lcd電視,投影儀,dvd等等。而如何實(shí)現(xiàn)fpga的高利用率也就成為了目前嵌 入式系統(tǒng)的一個(gè)焦點(diǎn)問題。就目前而言,可以從三個(gè)方面實(shí)現(xiàn)fpga的高利用率。(1)工 藝上的創(chuàng)新,通過采用 7 到 10 層的金屬層大大提高了fpga的利用率和布線成功率。 (2)結(jié)構(gòu)的創(chuàng)新,通過靈活的內(nèi)部可配置功能模塊和在fpga中不斷完善i/o、dsp和 存儲(chǔ)器等功能提高性能。(3)eda設(shè)計(jì)平臺(tái)的創(chuàng)新,使得fpga設(shè)計(jì)學(xué)習(xí)的門檻大為降 低,更具有可用性。 以信息家電為代表的互聯(lián)網(wǎng)時(shí)代嵌入式產(chǎn)品,不僅為嵌入式市場展現(xiàn)了美好前 景,注入了新的生命
8、;同時(shí)也對(duì)嵌入式系統(tǒng)技術(shù),特別是軟件技術(shù)提出新的挑戰(zhàn)。 這主要包括:支持日趨增長的功能密度、靈活的網(wǎng)絡(luò)聯(lián)接、輕便的移動(dòng)應(yīng)用和多媒 體的信息處理,此外,當(dāng)然還需對(duì)付更加激烈的市場競爭。 第二章 uc/os-ii 任務(wù)間通訊與同步的實(shí)現(xiàn) 2.1 開發(fā)環(huán)境介紹 jx44b0 教學(xué)實(shí)驗(yàn)系統(tǒng)是一套硬件、軟件集成的,基于 arm 的完整的教學(xué)實(shí)驗(yàn)系 統(tǒng),系統(tǒng)包含豐富的硬件資源、完善優(yōu)越的調(diào)試手段和詳盡的教學(xué)實(shí)驗(yàn)教程。此系 統(tǒng)具有如下的特點(diǎn): 1使用方便:adt ide 采用了一個(gè)通用的界面,可以非常方便的進(jìn)行工程管理、 編輯、編譯、鏈接和調(diào)試,使得我們可以很快地進(jìn)入到具體的實(shí)驗(yàn)中; 2接口豐富:含多種外設(shè)
9、接口:led 輸出、7 段碼輸出、lcd 輸出、a/d 轉(zhuǎn)換 接口、不進(jìn)電機(jī)接口、網(wǎng)絡(luò)接口、ide 接口、cf 卡接口、gprs 模塊和 gps 模塊等; 3擴(kuò)充性好:采用模塊化設(shè)計(jì),便于硬件升級(jí)換代,并提高豐富的擴(kuò)展以便 擴(kuò)充外部接口; 4實(shí)驗(yàn)豐富:本系統(tǒng)專門為嵌入式系統(tǒng)教學(xué)進(jìn)行了定制,精心設(shè)計(jì)了多個(gè)實(shí) 驗(yàn),包括嵌入式開發(fā)基礎(chǔ)實(shí)驗(yàn)、基本接口實(shí)驗(yàn)、bootloader 及操作系統(tǒng)實(shí)驗(yàn)和高級(jí) 接口實(shí)驗(yàn)。 2.1.1 jx44b0 教學(xué)實(shí)驗(yàn)系統(tǒng)的組成 1adt ide 集成開發(fā)環(huán)境; 2adt emulator for arm jtag 仿真器; 3jx44b0 系列教學(xué)實(shí)驗(yàn)箱:jx44b01b、
10、jx44b01、jx44b0 2、jx44b03; 4各種連接線、電源適配器以及實(shí)驗(yàn)指導(dǎo)書; 2.1.2 adt ide 集成開發(fā)環(huán)境 adt ide 是一套應(yīng)用于嵌入式軟件開發(fā)的新一代集成開發(fā)環(huán)境,它提供高效、 清晰、可視化的嵌入式軟件開發(fā)平臺(tái),包括一整套完備的面向嵌入式系統(tǒng)的開發(fā)和 調(diào)試工具:編輯器、編譯器、鏈接器、工程管理器以及調(diào)試器等。adt ide 運(yùn)行于 window nt、98、2000 及 xp,采用類 visual stdio 界面風(fēng)格,其界面如圖 3.0 所 示。 圖 2.0 adt ide 集成開發(fā)環(huán)境界面 2.2 任務(wù)間通訊與同步的實(shí)現(xiàn)步驟 在 c/os-ii 中,有多
11、種方法可以保護(hù)任務(wù)之間的共享數(shù)據(jù)和提供任務(wù)之間的 通訊。其中最主要的有兩種: 一是利用宏 os_enter_critical()和 os_exit_critical()來關(guān)閉中斷和打開中 斷。當(dāng)兩個(gè)任務(wù)或者一個(gè)任務(wù)和一個(gè)中斷服務(wù)子程序共享某些數(shù)據(jù)時(shí),可以采用這 種方法; 二是利用函數(shù) osschedlock()和 osschekunlock()對(duì) c/os-ii 中的任務(wù)調(diào)度函 數(shù)上鎖和開鎖。用這種方法也可以實(shí)現(xiàn)數(shù)據(jù)的共享。 這里將介紹另外三種用于數(shù)據(jù)共享和任務(wù)通訊的方法:信號(hào)量、郵箱和消息隊(duì) 列。 圖 2.1 介紹了任務(wù)和中斷服務(wù)子程序之間是如何進(jìn)行通訊的。 一個(gè)任務(wù)或者中斷服務(wù)子程序可以通
12、過事件控制塊 ecb(event control blocks)來向另外的任務(wù)發(fā)信號(hào)。這里,所有的信號(hào)都被看成是事件(event)。 這也說明為什么上面把用于通訊的數(shù)據(jù)結(jié)構(gòu)叫做事件控制塊。一個(gè)任務(wù)還可以等待 另一個(gè)任務(wù)或中斷服務(wù)子程序給它發(fā)送信號(hào)。這里要注意的是,只有任務(wù)可以等待 事件發(fā)生,中斷服務(wù)子程序是不能這樣做的。對(duì)于處于等待狀態(tài)的任務(wù),還可以給 它指定一個(gè)最長等待時(shí)間,以此來防止因?yàn)榈却氖录]有發(fā)生而無限期地等下去。 多個(gè)任務(wù)可以同時(shí)等待同一個(gè)事件的發(fā)生。在這種情況下,當(dāng)該事件發(fā)生后, 所有等待該事件的任務(wù)中,優(yōu)先級(jí)最高的任務(wù)得到了該事件并進(jìn)入就緒狀態(tài),準(zhǔn)備 執(zhí)行。上面講到的事件,可
13、以是信號(hào)量、郵箱或者消息隊(duì)列等。當(dāng)事件控制塊是一 個(gè)信號(hào)量時(shí),任務(wù)可以等待它,也可以給它發(fā)送消息。 圖 2.1事件控制塊的使用 2.2.1 事件控制塊 ecb c/os-ii 通過 ucos_ii.h 中定義的 os_event 數(shù)據(jù)結(jié)構(gòu)來維護(hù)一個(gè)事件控制塊 的所有信息程序清單 l3.1,也就是本章開篇講到的事件控制塊 ecb。該結(jié)構(gòu)中除 了包含了事件本身的定義,如用于信號(hào)量的計(jì)數(shù)器,用于指向郵箱的指針,以及指 向消息隊(duì)列的指針數(shù)組等,還定義了等待該事件的所有任務(wù)的列表。 程序清單 l3.1 是該數(shù)據(jù)結(jié)構(gòu)的定義。 程序清單 l3.1 ecb 數(shù)據(jù)結(jié)構(gòu) typedef struct void *
14、oseventptr; /* 指向消息或者消息隊(duì)列的指針 */ int8u oseventtblos_event_tbl_size; /* 等待任務(wù)列表 */ int16u oseventcnt; /* 計(jì)數(shù)器(當(dāng)事件是信號(hào)量時(shí)) */ int8u oseventtype; /* 時(shí)間類型 */ int8u oseventgrp; /* 等待任務(wù)所在的組 */ os_event; .oseventptr 指針,只有在所定義的事件是郵箱或者消息隊(duì)列時(shí)才使用。當(dāng)所定義的 事件是郵箱時(shí),它指向一個(gè)消息,而當(dāng)所定義的事件是消息隊(duì)列時(shí),它指向一個(gè)數(shù) 據(jù)結(jié)構(gòu)。 .oseventtbl 和 .osevent
15、grp 很像前面講到的 osrdytbl和 osrdygrp,只不過 前兩者包含的是等待某事件的任務(wù),而后兩者包含的是系統(tǒng)中處于就緒狀態(tài)的任務(wù)。 .oseventcnt 當(dāng)事件是一個(gè)信號(hào)量時(shí),.oseventcnt 是用于信號(hào)量的計(jì)數(shù)器。 .oseventtype 定義了事件的具體類型。它可以是信號(hào)量(os_event_sem)、郵箱 (os_event_type_mbox)或消息隊(duì)列(os_event_type_q)中的一種。用戶要根據(jù) 該域的具體值來調(diào)用相應(yīng)的系統(tǒng)函數(shù),以保證對(duì)其進(jìn)行的操作的正確性。 當(dāng)一個(gè)事件發(fā)生后,該事件的等待事件列表中優(yōu)先級(jí)最高的任務(wù),也即在. oseventtbl中
16、,所有被置 1 的位中,優(yōu)先級(jí)代碼最小的任務(wù)得到該事件。圖 3.2 給出了.oseventgrp 和.oseventtbl之間的對(duì)應(yīng)關(guān)系。該關(guān)系可以描述為: 當(dāng).oseventtbl0中的任何一位為 1 時(shí),.oseventgrp 中的第 0 位為 1。 當(dāng).oseventtbl1中的任何一位為 1 時(shí),.oseventgrp 中的第 1 位為 1。 當(dāng).oseventtbl2中的任何一位為 1 時(shí),.oseventgrp 中的第 2 位為 1。 當(dāng).oseventtbl3中的任何一位為 1 時(shí),.oseventgrp 中的第 3 位為 1。 當(dāng).oseventtbl4中的任何一位為 1 時(shí),
17、.oseventgrp 中的第 4 位為 1。 當(dāng).oseventtbl5中的任何一位為 1 時(shí),.oseventgrp 中的第 5 位為 1。 當(dāng).oseventtbl6中的任何一位為 1 時(shí),.oseventgrp 中的第 6 位為 1。 當(dāng).oseventtbl7中的任何一位為 1 時(shí),.oseventgrp 中的第 7 位為 1。 圖 2.2 事件的等待任務(wù)列表 下面的代碼將一個(gè)任務(wù)放到事件的等待任務(wù)列表中。 程序清單 l3.2將一個(gè)任務(wù)插入到事件的等待任務(wù)列表中 pevent-oseventgrp |= osmaptblprio 3; pevent-oseventtblprio 3
18、|= osmaptblprio 其中,prio 是任務(wù)的優(yōu)先級(jí),pevent 是指向事件控制塊的指針。從程序清單 l3.2 可以看出,插入一個(gè)任務(wù)到等待任務(wù)列表中所花的時(shí)間是相同的,和表中現(xiàn)有 多少個(gè)任務(wù)無關(guān)。從圖 3.2 中可以看出該算法的原理:任務(wù)優(yōu)先級(jí)的最低 3 位決定 了該任務(wù)在相應(yīng)的.oseventtbl中的位置,緊接著的 3 位則決定了該任務(wù)優(yōu)先級(jí) 在.oseventtbl中的字節(jié)索引。該算法中用到的查找表 osmaptbl(定義在 os_core.c 中)一般在 rom 中實(shí)現(xiàn)。 表表3.13.1 osmaptblosmaptbl indexindexbitbit maskmas
19、k (binary)(binary) 000000001 100000010 200000100 300001000 400010000 500100000 601000000 710000000 從等待任務(wù)列表中刪除一個(gè)任務(wù)的算法則正好相反,如程序清單 l3.3 所示。 程序清單 l3.3 從等待任務(wù)列表中刪除一個(gè)任務(wù) if (pevent-oseventtblprio 3 該代碼清除了任務(wù)在.oseventtbl中的相應(yīng)位,并且,如果其所在的組中不 再有處于等待該事件的任務(wù)時(shí)(即.oseventtblprio3為 0),將.oseventgrp 中的相應(yīng)位也清除了。和上面的由任務(wù)優(yōu)先級(jí)確定
20、該任務(wù)在等待表中的位置的算法 類似,從等待任務(wù)列表中查找處于等待狀態(tài)的最高優(yōu)先級(jí)任務(wù)的算法,也不是從. oseventtbl0開始逐個(gè)查詢,而是采用了查找另一個(gè)表 osunmaptbl256。這里, 用于索引的 8 位分別代表對(duì)應(yīng)的 8 組中有任務(wù)處于等待狀態(tài),其中的最低位具有最 高的優(yōu)先級(jí)。用這個(gè)值索引,首先得到最高優(yōu)先級(jí)任務(wù)所在的組的位置(07 之間 的一個(gè)數(shù))。然后利用.oseventtbl中對(duì)應(yīng)字節(jié)再在 osunmaptbl中查找,就可 以得到最高優(yōu)先級(jí)任務(wù)在組中的位置(也是 07 之間的一個(gè)數(shù))。這樣,最終就 可以得到處于等待該事件狀態(tài)的最高優(yōu)先級(jí)任務(wù)了。程序清單 l3.4 是該算法
21、的具 體實(shí)現(xiàn)代碼。 程序清單 l3.4 在等待任務(wù)列表中查找最高優(yōu)先級(jí)的任務(wù) y = osunmaptblpevent-oseventgrp; x = osunmaptblpevent-oseventtbly; prio = (y oseventgrp = 0 x00; for (i = 0; i oseventtbli = 0 x00; 2.2.3 使一個(gè)任務(wù)進(jìn)入就緒態(tài),oseventtaskrdy() 程序清單 l3.6 是函數(shù) oseventtaskrdy()的源代碼。當(dāng)發(fā)生了某個(gè)事件,該事 件等待任務(wù)列表中的最高優(yōu)先級(jí)任務(wù)要置于就緒態(tài)時(shí),該事件對(duì)應(yīng)的 ossempost(), osmb
22、oxpost(),osqpost(),和 osqpostfront()函數(shù)調(diào)用 oseventtaskrdy()實(shí)現(xiàn)該 操作。換句話說,該函數(shù)從等待任務(wù)隊(duì)列中刪除 hpt 任務(wù)(highest priority task),并把該任務(wù)置于就緒態(tài)。圖 3.4 給出了 oseventtaskrdy()函數(shù)最開始的 4 個(gè)動(dòng)作。 該函數(shù)首先計(jì)算 hpt 任務(wù)在.oseventtbl中的字節(jié)索引,其結(jié)果是一個(gè)從 0 到 os_lowest_prio/8+1 之間的數(shù),并利用該索引得到該優(yōu)先級(jí)任務(wù)在.oseventgrp 中的位屏蔽碼。然后,oseventtaskrdy()函數(shù)判斷 hpt 任務(wù)在.os
23、eventtbl中相 應(yīng)位的位置,其結(jié)果是一個(gè)從 0 到 os_lowest_prio/8+1 之間的數(shù),以及相應(yīng)的位 屏蔽碼。根據(jù)以上結(jié)果,oseventtaskrdy()函數(shù)計(jì)算出 hpt 任務(wù)的優(yōu)先級(jí),然后就 可以從等待任務(wù)列表中刪除該任務(wù)了。 任務(wù)的任務(wù)控制塊中包含有需要改變的信息。知道了 hpt 任務(wù)的優(yōu)先級(jí),就可 以得到指向該任務(wù)的任務(wù)控制塊的指針、。因?yàn)樽罡邇?yōu)先級(jí)任務(wù)運(yùn)行條件已經(jīng)得到 滿足,必須停止 ostimetick()函數(shù)對(duì).ostcbdly 域的遞減操作,所以 oseventtaskrdy()直接將該域清澈。因?yàn)樵撊蝿?wù)不再等待該事件的發(fā)生,所以 oseventtaskrd
24、y()函數(shù)將其任務(wù)控制塊中指向事件控制塊的指針指向 null。如果 oseventtaskrdy()是由 osmboxpost()或者 osqpost()調(diào)用的,該函數(shù)還要將相應(yīng)的 消息傳遞給 hpt,放在它的任務(wù)控制塊中。另外,當(dāng) oseventtaskrdy()被調(diào)用時(shí), 位屏蔽碼 msk 作為參數(shù)傳遞給它。該參數(shù)是用于對(duì)任務(wù)控制塊中的位清零的位屏蔽 碼,和所發(fā)生事件的類型相對(duì)應(yīng)。最后,根據(jù).ostcbstat 判斷該任務(wù)是否已處于就 緒狀態(tài)。如果是, 則將 hpt 插入到 c/os-ii 的就緒任務(wù)列表中。注意,hpt 任務(wù)得 到該事件后不一定進(jìn)入就緒狀態(tài),也許該任務(wù)已經(jīng)由于其它原因掛起
25、了。另外, .oseventtaskrdy()函數(shù)要在中斷禁止的情況下調(diào)用。 程序清單 l3.6 使一個(gè)任務(wù)進(jìn)入就緒狀態(tài) void oseventtaskrdy (os_event *pevent, void *msg, int8u msk) os_tcb *ptcb; int8u x; int8u y; int8u bitx; int8u bity; int8u prio; y = osunmaptblpevent-oseventgrp; bity = osmaptbly; x = osunmaptblpevent-oseventtbly; bitx = osmaptblx; prio =
26、(int8u)(y oseventtbly ptcb = ostcbpriotblprio; ptcb-ostcbdly = 0; ptcb-ostcbeventptr = (os_event *)0; #if (os_q_en #else msg = msg; #endif ptcb-ostcbstat if (ptcb-ostcbstat = os_stat_rdy) osrdygrp |= bity; osrdytbly |= bitx; 圖 2.4 使一個(gè)任務(wù)進(jìn)入就緒狀態(tài) 2.2.4 使一個(gè)任務(wù)進(jìn)入等待某事件發(fā)生狀態(tài), oseventtaskwait() 程序清單 l3.7 是 ose
27、venttaskwait()函數(shù)的源代碼。當(dāng)某個(gè)任務(wù)要等待一個(gè) 事件的發(fā)生時(shí),相應(yīng)事件的 ossempend(),osmboxpend()或者 osqpend()函數(shù)會(huì)調(diào) 用該函數(shù)將當(dāng)前任務(wù)從就緒任務(wù)表中刪除,并放到相應(yīng)事件的事件控制塊的等待任 務(wù)表中。 程序清單 l3.7 使一個(gè)任務(wù)進(jìn)入等待狀態(tài) void oseventtaskwait (os_event *pevent) ostcbcur-ostcbeventptr = pevent; if (osrdytblostcbcur-ostcby pevent-oseventtblostcbcur-ostcby |= ostcbcur-ostc
28、bbitx; pevent-oseventgrp |= ostcbcur-ostcbbity; 在該函數(shù)中,首先將指向事件控制塊的指針放到任務(wù)的任務(wù)控制塊中,接著將 任務(wù)從就緒任務(wù)表中刪除,并把該任務(wù)放到事件控制塊的等待任務(wù)表中。 2.2.5 信號(hào)量 c/os-ii 中的信號(hào)量由兩部分組成:一個(gè)是信號(hào)量的計(jì)數(shù)值,它是一個(gè) 16 位的 無符號(hào)整數(shù)(0 到 65,535 之間);另一個(gè)是由等待該信號(hào)量的任務(wù)組成的等待任 務(wù)表。用戶要在 os_cfg.h 中將 os_sem_en 開關(guān)量常數(shù)置成 1,這樣 c/os-ii 才能 支持信號(hào)量。 在使用一個(gè)信號(hào)量之前,首先要建立該信號(hào)量,也即調(diào)用 oss
29、emcreate()函數(shù) (見下一節(jié)),對(duì)信號(hào)量的初始計(jì)數(shù)值賦值。該初始值為 0 到 65,535 之間的一個(gè) 數(shù)。如果信號(hào)量是用來表示一個(gè)或者多個(gè)事件的發(fā)生,那么該信號(hào)量的初始值應(yīng)設(shè) 為 0。如果信號(hào)量是用于對(duì)共享資源的訪問,那么該信號(hào)量的初始值應(yīng)設(shè)為 1(例 如,把它當(dāng)作二值信號(hào)量使用)。最后,如果該信號(hào)量是用來表示允許任務(wù)訪問 n 個(gè)相同的資源,那么該初始值顯然應(yīng)該是 n,并把該信號(hào)量作為一個(gè)可計(jì)數(shù)的信號(hào) 量使用。 c/os-ii 提供了 5 個(gè)對(duì)信號(hào)量進(jìn)行操作的函數(shù)。它們是:ossemcreate(), ossempend(),ossempost(),ossemaccept()和 os
30、semquery()函數(shù)。圖 3.5 說明了 任務(wù)、中斷服務(wù)子程序和信號(hào)量之間的關(guān)系。圖中用鑰匙或者旗幟的符號(hào)來表示信 號(hào)量:如果信號(hào)量用于對(duì)共享資源的訪問,那么信號(hào)量就用鑰匙符號(hào)。符號(hào)旁邊的 數(shù)字 n 代表可用資源數(shù)。對(duì)于二值信號(hào)量,該值就是 1;如果信號(hào)量用于表示某事 件的發(fā)生,那么就用旗幟符號(hào)。 圖 2.5 任務(wù)、中斷服務(wù)子程序和信號(hào)量之間的關(guān)系 程序清單 l3.9 建立一個(gè)信號(hào)量 os_event *ossemcreate (int16u cnt) os_event *pevent; os_enter_critical(); pevent = oseventfreelist;(1) i
31、f (oseventfreelist != (os_event *)0) oseventfreelist = (os_event *)oseventfreelist-oseventptr; os_exit_critical(); if (pevent != (os_event *)0) pevent-oseventtype = os_event_type_sem; pevent-oseventcnt = cnt; oseventwaitlistinit(pevent); return (pevent); 等待一個(gè)信號(hào)量, ossempend() 程序清單 l3.10 是 ossempend()
32、函數(shù)的源代碼。它首先檢查指針 pevent 所指 的任務(wù)控制塊是否是由 ossemcreate()建立的。如果信號(hào)量當(dāng)前是可用的(信號(hào)量 的計(jì)數(shù)值大于 0),將信號(hào)量的計(jì)數(shù)值減 1,然后函數(shù)將“無錯(cuò)”錯(cuò)誤代碼返回給 它的調(diào)用函數(shù)。顯然,如果正在等待信號(hào)量,這時(shí)的輸出正是我們所希望的,也是 運(yùn)行 ossempend()函數(shù)最快的路徑。 如果此時(shí)信號(hào)量無效(計(jì)數(shù)器的值是 0),ossempend()函數(shù)要進(jìn)一步檢查它的 調(diào)用函數(shù)是不是中斷服務(wù)子程序。在正常情況下,中斷服務(wù)子程序是不會(huì)調(diào)用 ossempend()函數(shù)的。這里加入這些代碼,只是為了以防萬一。當(dāng)然,在信號(hào)量有 效的情況下,即使是中斷服務(wù)
33、子程序調(diào)用的 ossempend(),函數(shù)也會(huì)成功返回,不 會(huì)出任何錯(cuò)誤。 因?yàn)楫?dāng)前任務(wù)已經(jīng)不是就緒態(tài)了,所以任務(wù)調(diào)度函數(shù)將下一個(gè)最高優(yōu)先級(jí)的任 務(wù)調(diào)入,準(zhǔn)備運(yùn)行。當(dāng)信號(hào)量有效或者等待時(shí)間到后,調(diào)用 ossempend()函數(shù)的任 務(wù)將再一次成為最高優(yōu)先級(jí)任務(wù)。這時(shí) ossched()函數(shù)返回。這之后,ossempend() 要檢查任務(wù)控制塊中的狀態(tài)標(biāo)志,看該任務(wù)是否仍處于等待信號(hào)量的狀態(tài)。如果是, 說明該任務(wù)還沒有被 ossempost()函數(shù)發(fā)出的信號(hào)量喚醒。事實(shí)上,該任務(wù)是因?yàn)?等待超時(shí)而由 timetick()函數(shù)把它置為就緒狀態(tài)的。這種情況下,ossempend()函 數(shù)調(diào)用 ose
34、ventto()函數(shù)將任務(wù)從等待任務(wù)列表中刪除,并返回給它的調(diào)用任務(wù)一 個(gè)“超時(shí)”的錯(cuò)誤代碼。如果任務(wù)的任務(wù)控制塊中的 os_stat_sem 標(biāo)志位沒有置位, 就認(rèn)為調(diào)用 ossempend()的任務(wù)已經(jīng)得到了該信號(hào)量,將指向信號(hào)量 ecb 的指針從 該任務(wù)的任務(wù)控制塊中刪除,并返回給調(diào)用函數(shù)一個(gè)“無錯(cuò)”的錯(cuò)誤代碼。 程序清單 l3.10 等待一個(gè)信號(hào)量 void ossempend (os_event *pevent, int16u timeout, int8u *err) os_enter_critical(); if (pevent-oseventtype != os_event_ty
35、pe_sem) os_exit_critical(); *err = os_err_event_type; if (pevent-oseventcnt 0) pevent-oseventcnt-; os_exit_critical(); *err = os_no_err; else if (osintnesting 0) os_exit_critical(); *err = os_err_pend_isr; else ostcbcur-ostcbstat |= os_stat_sem; ostcbcur-ostcbdly = timeout; oseventtaskwait(pevent);
36、os_exit_critical(); ossched(); os_enter_critical(); if (ostcbcur-ostcbstat os_exit_critical(); *err = os_timeout; else ostcbcur-ostcbeventptr = (os_event *)0; os_exit_critical(); *err = os_no_err; 發(fā)送一個(gè)信號(hào)量, ossempost() 程序清單 l3.11 是 ossempost()函數(shù)的源代碼。它首先檢查參數(shù)指針 pevent 指向的任務(wù)控制塊是否是 ossemcreate()函數(shù)建立的,接著檢
37、查是否有任務(wù)在等待 該信號(hào)量。如果該任務(wù)控制塊中的.oseventgrp 域不是 0,說明有任務(wù)正在等待該 信號(hào)量。這時(shí),就要調(diào)用函數(shù) oseventtaskrdy(),oseventtaskrdy(),把其中的 最高優(yōu)先級(jí)任務(wù)從等待任務(wù)列表中刪除并使它進(jìn)入就緒狀態(tài)。然后,調(diào)用 ossched()任 務(wù)調(diào)度函數(shù)檢查該任務(wù)是否是系統(tǒng)中的最高優(yōu)先級(jí)的就緒任務(wù)。如果是,這時(shí)就要 進(jìn)行任務(wù)切換當(dāng) ossempost()函數(shù)是在任務(wù)中調(diào)用的,準(zhǔn)備執(zhí)行該就緒任務(wù)。如 果不是,ossched()直接返回,調(diào)用 ossempost()的任務(wù)得以繼續(xù)執(zhí)行。如果這時(shí)沒 有任務(wù)在等待該信號(hào)量,該信號(hào)量的計(jì)數(shù)值就簡單
38、地加 1。 上面是由任務(wù)調(diào)用 ossempost()時(shí)的情況。當(dāng)中斷服務(wù)子程序調(diào)用該函數(shù)時(shí), 不會(huì)發(fā)生上面的任務(wù)切換。如果需要,任務(wù)切換要等到中斷嵌套的最外層中斷服務(wù) 子程序調(diào)用 osintexit()函數(shù)后才能進(jìn)行。 程序清單 l3.11 發(fā)出一個(gè)信號(hào)量 int8u ossempost (os_event *pevent) os_enter_critical(); if (pevent-oseventtype != os_event_type_sem) os_exit_critical(); return (os_err_event_type); if (pevent-oseventgrp)
39、 oseventtaskrdy(pevent, (void *)0, os_stat_sem); os_exit_critical(); ossched(); return (os_no_err); else if (pevent-oseventcnt oseventcnt+; os_exit_critical(); return (os_no_err); else os_exit_critical(); return (os_sem_ovf); 無等待地請(qǐng)求一個(gè)信號(hào)量, ossemaccept() 當(dāng)一個(gè)任務(wù)請(qǐng)求一個(gè)信號(hào)量時(shí),如果該信號(hào)量暫時(shí)無效,也可以讓該任務(wù)簡單 地返回,而不是進(jìn)入睡眠等
40、待狀態(tài)。這種情況下的操作是由 ossemaccept()函數(shù)完 成的,其源代碼見程序清單 l3.12。該函數(shù)在最開始也是檢查參數(shù)指針 pevent 指 向的事件控制塊是否是由 ossemcreate()函數(shù)建立的,接著從該信號(hào)量的事件控制 塊中取出當(dāng)前計(jì)數(shù)值,并檢查該信號(hào)量是否有效(計(jì)數(shù)值是否為非 0 值)。如果有 效,則將信號(hào)量的計(jì)數(shù)值減 1,然后將信號(hào)量的原有計(jì)數(shù)值返回給調(diào)用函數(shù)。調(diào)用 函數(shù)需要對(duì)該返回值進(jìn)行檢查。如果該值是 0,說明該信號(hào)量無效。如果該值大于 0,說明該信號(hào)量有效,同時(shí)該值也暗示著該信號(hào)量當(dāng)前可用的資源數(shù)。應(yīng)該注意 的是,這些可用資源中,已經(jīng)被該調(diào)用函數(shù)自身占用了一個(gè)(該
41、計(jì)數(shù)值已經(jīng)被減 1)。中斷服務(wù)子程序要請(qǐng)求信號(hào)量時(shí),只能用 ossemaccept()而不能用 ossempend(),因?yàn)橹袛喾?wù)子程序是不允許等待的。 程序清單 l3.12 無等待地請(qǐng)求一個(gè)信號(hào)量 int16u ossemaccept (os_event *pevent) int16u cnt; os_enter_critical(); if (pevent-oseventtype != os_event_type_sem) os_exit_critical(); return (0); cnt = pevent-oseventcnt; if (cnt 0) pevent-oseventc
42、nt-; os_exit_critical(); return (cnt); 查詢一個(gè)信號(hào)量的當(dāng)前狀態(tài), ossemquery() 和其它與信號(hào)量有關(guān)的函數(shù)一樣,ossemquery()也是先檢查 pevent 指向的事 件控制塊是否是 ossemcreate()產(chǎn)生的,然后將等待任務(wù)列表和計(jì)數(shù)值從 os_event 結(jié)構(gòu)拷貝到 os_sem_data 結(jié)構(gòu)變量中去。 程序清單 l3.13 查詢一個(gè)信號(hào)量的狀態(tài) int8u ossemquery (os_event *pevent, os_sem_data *pdata) int8u i; int8u *psrc; int8u *pdest;
43、os_enter_critical(); if (pevent-oseventtype != os_event_type_sem) os_exit_critical(); return (os_err_event_type); pdata-oseventgrp = pevent-oseventgrp; psrc = pdest = for (i = 0; i oscnt = pevent-oseventcnt; os_exit_critical(); return (os_no_err); 2.2.7 郵箱 郵箱是 c/os-ii 中另一種通訊機(jī)制,它可以使一個(gè)任務(wù)或者中斷服務(wù)子程序 向另一個(gè)
44、任務(wù)發(fā)送一個(gè)指針型的變量。該指針指向一個(gè)包含了特定“消息”的數(shù)據(jù) 結(jié)構(gòu)。為了在 c/os-ii 中使用郵箱,必須將 os_cfg.h 中的 os_mbox_en 常數(shù)置為 1。 使用郵箱之前,必須先建立該郵箱。該操作可以通過調(diào)用 osmboxcreate()函數(shù) 來完成(見下節(jié)),并且要指定指針的初始值。一般情況下,這個(gè)初始值是 null, 但也可以初始化一個(gè)郵箱,使其在最開始就包含一條消息。如果使用郵箱的目的是 用來通知一個(gè)事件的發(fā)生(發(fā)送一條消息),那么就要初始化該郵箱為 null,因?yàn)?在開始時(shí),事件還沒有發(fā)生。如果用戶用郵箱來共享某些資源,那么就要初始化該 郵箱為一個(gè)非 null 的指
45、針。在這種情況下,郵箱被當(dāng)成一個(gè)二值信號(hào)量使用。 c/os-ii 提供了 5 種對(duì)郵箱的操作:osmboxcreate(),osmboxpend(), osmboxpost(),osmboxaccept()和 osmboxquery()函數(shù)。圖 f3.6 描述了任務(wù)、中 斷服務(wù)子程序和郵箱之間的關(guān)系,這里用符號(hào)“i”表示郵箱。郵箱包含的內(nèi)容是 一個(gè)指向一條消息的指針。一個(gè)郵箱只能包含一個(gè)這樣的指針(郵箱為滿時(shí)),或 者一個(gè)指向 null 的指針(郵箱為空時(shí))。從圖 3.6 可以看出,任務(wù)或者中斷服務(wù) 子程序可以調(diào)用函數(shù) osmboxpost(),但是只有任務(wù)可以調(diào)用函數(shù) osmboxpend(
46、)和 osmboxquery()。 圖 2.6 任務(wù)、中斷服務(wù)子程序和郵箱之間的關(guān)系 建立一個(gè)郵箱,osmboxcreate() 程序清單 l3.14 是 osmboxcreate()函數(shù)的源代碼,基本上和函數(shù) ossemcreate()相似。不同之處在于事件控制塊的類型被設(shè)置成 os_event_type_mboxl3.14(1),以及使用.oseventptr 域來容納消息指針,而不 是使用.oseventcnt 域l3.14(2)。 osmboxcreate()函數(shù)的返回值是一個(gè)指向事件控制塊的指針l3.14(3)。這個(gè)指針 在調(diào)用函數(shù) osmboxpend(),osmboxpost()
47、,osmboxaccept()和 osmboxquery()時(shí)使 用。因此,該指針可以看作是對(duì)應(yīng)郵箱的句柄。值得注意的是,如果系統(tǒng)中已經(jīng)沒 有事件控制塊可用,函數(shù) osmboxcreate()將返回一個(gè) null 指針。 郵箱一旦建立,是不能被刪除的。比如,如果有任務(wù)正在等待一個(gè)郵箱的信息,這 時(shí)刪除該郵箱,將有可能產(chǎn)生災(zāi)難性的后果。 程序清單 l3.14 建立一個(gè)郵箱 os_event *osmboxcreate (void *msg) os_event *pevent; os_enter_critical(); pevent = oseventfreelist; if (oseventfr
48、eelist != (os_event *)0) oseventfreelist = (os_event *)oseventfreelist-oseventptr; os_exit_critical(); if (pevent != (os_event *)0) pevent-oseventtype = os_event_type_mbox; pevent-oseventptr = msg; oseventwaitlistinit(pevent); return (pevent); 等待一個(gè)郵箱中的消息,osmboxpend() 程序清單 l3.15 是 osmboxpend()函數(shù)的源代碼。
49、同樣,它和 ossempend()也很 相似,因此,在這里只講述其中的不同之處。osmboxpend()首先檢查該事件控制塊 是由 osmboxcreate()函數(shù)建立的。當(dāng).oseventptr 域是一個(gè)非 null 的指針時(shí),說 明該郵箱中有可用的消息。這種情況下,osmboxpend()函數(shù)將該域的值復(fù)制到局部 變量 msg 中,然后將.oseventptr 置為 null。這正是我們所期望的,也是執(zhí)行 osmboxpend()函數(shù)最快的路徑。 如果郵箱中沒有可用的消息,osmboxpend()的調(diào)用任務(wù)就被掛起,直到郵箱中 有了消息或者等待超時(shí)。當(dāng)有其它的任務(wù)向該郵箱發(fā)送了消息后(或者
50、等待時(shí)間超 時(shí)),這時(shí),該任務(wù)再一次成為最高優(yōu)先級(jí)任務(wù),ossched()返回。這時(shí), osmboxpend()函數(shù)要檢查是否有消息被放到該任務(wù)的任務(wù)控制塊中。如果有,那么 該次函數(shù)調(diào)用成功,對(duì)應(yīng)的消息被返回到調(diào)用函數(shù)。 程序清單 l3.15 等待一個(gè)郵箱中的消息 void *osmboxpend (os_event *pevent, int16u timeout, int8u *err) void *msg; os_enter_critical(); if (pevent-oseventtype != os_event_type_mbox) os_exit_critical(); *err
51、= os_err_event_type; return (void *)0); msg = pevent-oseventptr; if (msg != (void *)0) pevent-oseventptr = (void *)0; os_exit_critical(); *err = os_no_err; else if (osintnesting 0) os_exit_critical(); *err = os_err_pend_isr; else ostcbcur-ostcbstat |= os_stat_mbox; ostcbcur-ostcbdly = timeout; oseventtaskwait(pevent); os_exit_critical(); ossched(); os_enter_critical(); if (msg = ostcbcur-ostcbmsg) != (void *)0) ostcbcur-ostcbmsg = (void *)0; ostcbcur-ostcbstat = os_stat_rdy; ostcbcur-ostcbeventptr = (os_event *)0; os_exit_critical()
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年版:物業(yè)托管經(jīng)營合同標(biāo)準(zhǔn)文本
- 素描動(dòng)物寫生課程設(shè)計(jì)
- 自動(dòng)清潔式黑板課程設(shè)計(jì)
- 藝術(shù)能力訓(xùn)練課程設(shè)計(jì)
- 2024公有云和互聯(lián)網(wǎng)創(chuàng)新實(shí)踐報(bào)告-英特爾中國
- 工藝課程設(shè)計(jì)
- 數(shù)字系統(tǒng)課程設(shè)計(jì)教程
- 思維能力訓(xùn)練課程設(shè)計(jì)
- 暖通空調(diào)大學(xué)課程設(shè)計(jì)
- 液壓缸端蓋課程設(shè)計(jì)
- 安徽省馬鞍山市2023-2024學(xué)年高一上學(xué)期期末考試物理試題(含答案解析)
- 心理健康對(duì)學(xué)生學(xué)習(xí)成績的影響
- 食品生產(chǎn)企業(yè)員工食品安全培訓(xùn)
- 小學(xué)數(shù)學(xué)綜合素質(zhì)評(píng)價(jià)專項(xiàng)方案
- 模型預(yù)測控制現(xiàn)狀與挑戰(zhàn)
- 閩教版2023版3-6年級(jí)全8冊(cè)英語單詞表
- MOOC創(chuàng)新創(chuàng)業(yè)與管理基礎(chǔ)(東南大學(xué))
- 華為財(cái)務(wù)分析報(bào)告
- 快速出具舊機(jī)動(dòng)車評(píng)估報(bào)告
- 人員保有培訓(xùn)課件
- 水上拋石安全專項(xiàng)施工方案
評(píng)論
0/150
提交評(píng)論