dsp數(shù)字信號處理課程設(shè)計-- µcos-ii在dsp上的任務(wù)通訊_第1頁
已閱讀1頁,還剩25頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、<p>  《DSP技術(shù)及應(yīng)用》課程設(shè)計報告</p><p>  選題名稱: µC/OS-II在DSP上的任務(wù)通訊 </p><p>  系(院): 計算機(jī)工程學(xué)院 </p><p>  專 業(yè): 計算機(jī)科學(xué)與技術(shù)(嵌入式系統(tǒng)軟件設(shè)計)</p><p>  

2、班 級: 計算機(jī)1073班 </p><p>  姓 名: 學(xué) 號: </p><p>  指導(dǎo)教師: </p><p>  學(xué)年學(xué)期: 2009 ~ 2010 學(xué)年 第 2

3、學(xué)期 </p><p>  2010年 6 月 12 日</p><p><b>  摘要:</b></p><p>  在µC/OS-II中,有多種方法可以保護(hù)任務(wù)之間的共享數(shù)據(jù)和提供任務(wù)之間的通訊。一是利用宏OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()來關(guān)閉中斷和打開中斷。二是

4、利用函數(shù)OSSchedLock()和OSSchekUnlock()對µC/OS-II中的任務(wù)調(diào)度函數(shù)上鎖和開鎖。本文將介紹另外三種用于數(shù)據(jù)共享和任務(wù)通訊的方法:信號量、郵箱和消息隊列。本文將著重介紹了在DSP上任務(wù)和中斷服務(wù)子程序之間是如何進(jìn)行通訊的。一個任務(wù)或者中斷服務(wù)子程序可以通過事件控制塊ECB來向另外的任務(wù)發(fā)信號,所有的信號都被看成是事件。一個任務(wù)還可以等待另一個任務(wù)或中斷服務(wù)子程序給它發(fā)送信號,只有任務(wù)可以等待事件發(fā)

5、生,中斷服務(wù)子程序是不能這樣做的。對于處于等待狀態(tài)的任務(wù),還可以給它指定一個最長等待時間,以此來防止因為等待的事件沒有發(fā)生而無限期地等下去。多個任務(wù)可以同時等待同一個事件的發(fā)生,當(dāng)該事件發(fā)生后,所有等待該事件的任務(wù)中,優(yōu)先級最高的任務(wù)得到了該事件并進(jìn)入就緒狀態(tài),準(zhǔn)備執(zhí)行。這些事件,可以是信號量、郵箱或者消息隊列等。</p><p>  關(guān)鍵詞:µC/OS-II;信號量;郵箱;消息隊列;DSP</p

6、><p><b>  目錄</b></p><p><b>  1 課題綜述1</b></p><p>  1.1 課題性質(zhì)和目的1</p><p>  1.2 課題設(shè)計任務(wù)1</p><p>  1.3 課題設(shè)計要求1</p><p>  1

7、.4 課題背景1</p><p><b>  2 系統(tǒng)分析2</b></p><p>  2.1 CCS簡介2</p><p>  2.2 µC/OS-II簡介3</p><p><b>  2.3 信號量3</b></p><p><b> 

8、 2.4 郵箱4</b></p><p>  2.5 消息隊列5</p><p>  3 系統(tǒng)詳細(xì)設(shè)計8</p><p>  3.1 建立一個郵箱,OSMboxCreate()8</p><p>  3.2 等待一個郵箱中的消息,OSMboxPend()9</p><p>  3.3 發(fā)送一個消息

9、到郵箱中,OSMboxPost()11</p><p>  3.4 無等待地從郵箱中得到一個消息, OSMboxAccept()13</p><p>  3.5 查詢一個郵箱的狀態(tài), OSMboxQuery()14</p><p>  3.6 用郵箱作二值信號量15</p><p>  3.7 用郵箱實現(xiàn)延時,而不使用OSTimeDl

10、y()15</p><p><b>  4 源程序16</b></p><p><b>  總 結(jié)20</b></p><p><b>  參考文獻(xiàn)21</b></p><p><b>  1 課題綜述</b></p><p&

11、gt;  1.1 課題性質(zhì)和目的</p><p>  《DSP技術(shù)及應(yīng)用》課程設(shè)計是一項重要的實踐性教育環(huán)節(jié),是學(xué)生在校期間必須接受的一項工程訓(xùn)練。在課程設(shè)計過程中,在教師指導(dǎo)下,運用工程的方法,通過一個簡單課題的設(shè)計練習(xí),可使學(xué)生初步體驗定點DSP應(yīng)用系統(tǒng)的設(shè)計過程、設(shè)計要求、完成的工作內(nèi)容和具體的設(shè)計方法,了解必須提交的各項工程文件,也達(dá)到鞏固、充實和綜合運用所學(xué)知識解決實際問題的目的。</p>

12、<p>  通過課程設(shè)計,應(yīng)能加強(qiáng)學(xué)生如下能力的培養(yǎng):獨立工作能力和創(chuàng)造力;綜合運用專業(yè)及基礎(chǔ)知識,解決實際工程技術(shù)問題的能力;查閱圖書資料、產(chǎn)品手冊和各種工具書的能力;工程繪圖的能力;程序編寫的能力;編寫技術(shù)報告和編制技術(shù)資料的能力。</p><p>  1.2 課題設(shè)計任務(wù)</p><p>  布置一定難度的設(shè)計課題,要求獨立或協(xié)作完成。在設(shè)計過程中,養(yǎng)成良好的電路設(shè)計、編

13、程習(xí)慣,學(xué)會分析實際問題能力,系統(tǒng)設(shè)計的能力和系統(tǒng)綜合的能力,鍛煉代碼調(diào)試技巧,撰寫設(shè)計文檔。</p><p>  1.3 課題設(shè)計要求</p><p>  在課程教學(xué)大綱主要內(nèi)容和基本要求的基礎(chǔ)上,結(jié)合課程體系的實際需求及學(xué)生的實踐能力、實驗條件等外部因素,選擇恰當(dāng)?shù)脑O(shè)計課題,既體現(xiàn)教學(xué)目的,又能反映實際教學(xué)情況。安排充足的實踐課時,配備專門指導(dǎo)老師。學(xué)生完成設(shè)計任務(wù)后,應(yīng)按要求提交課程

14、設(shè)計報告,課程設(shè)計報告力求規(guī)范化。</p><p><b>  1.4 課題背景</b></p><p>  在µC/OS-II中,有多種方法可以保護(hù)任務(wù)之間的共享數(shù)據(jù)和提供任務(wù)之間的通訊。一是利用宏OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()來關(guān)閉中斷和打開中斷。當(dāng)兩個任務(wù)或者一個任務(wù)和一個中斷服務(wù)子程序共享某些數(shù)據(jù)時,可以

15、采用OS_ENTER_CRITICAL() 和 OS_EXIT_CRITICAL()及OS_CPU.H。二是利用函數(shù)OSSchedLock()和OSSchekUnlock()對µC/OS-II中的任務(wù)調(diào)度函數(shù)上鎖和開鎖。用這種方法也可以實現(xiàn)數(shù)據(jù)的共享,給調(diào)度器上鎖和開鎖。本文將介紹另外三種用于數(shù)據(jù)共享和任務(wù)通訊的方法:信號量、郵箱和消息隊列。本文將著重介紹了任務(wù)和中斷服務(wù)子程序之間是如何進(jìn)行通訊的。 一個任務(wù)或者中斷服務(wù)子程序

16、可以通過事件控制塊ECB來向另外的任務(wù)發(fā)信號,所有的信號都被看成是事件。一個任務(wù)還可以等待另一個任務(wù)或中斷服務(wù)子程序給它發(fā)送信號,只有任務(wù)可以等待事件發(fā)生,中斷服務(wù)子程序是不能這樣做的。對于處于等待狀態(tài)的任務(wù),還可以給它指定一個最長等待時間,以此來防止因為等待的事件沒有發(fā)生而無限期地等下去。多個任務(wù)可以同時等待同一個事</p><p><b>  2 系統(tǒng)分析</b></p>

17、<p><b>  2.1 CCS簡介</b></p><p>  CCS是一種針對TMS320系列DSP的集成開發(fā)環(huán)境,在Windows操作系統(tǒng)下,采用圖形接口界面,提供有環(huán)境配置、源文件編輯、程序調(diào)試、跟蹤和分析等工具。 CCS有兩種工作模式,即 軟件仿真器模式:可以脫離DSP芯片,在PC機(jī)上模擬DSP的指令集和工作機(jī)制,主要用于前期算法實現(xiàn)和調(diào)試。 硬件在線編程模式:可以實時

18、運行在DSP芯片上,與硬件開發(fā)板相結(jié)合在線編程和調(diào)試應(yīng)用程序。</p><p>  CCS的開發(fā)系統(tǒng)主要由以下組件構(gòu)成:TMS320C54x集成代碼產(chǎn)生工具;CCS集成開發(fā)環(huán)境;DSP/BIOS實時內(nèi)核插件及其應(yīng)用程序接口API;實時數(shù)據(jù)交換的RTDX插件以及相應(yīng)的程序接口API;由TI公司以外的第三方提供的各種應(yīng)用模塊插件。</p><p>  CCS的功能十分強(qiáng)大,它集成了代碼的編輯、

19、編譯、鏈接和調(diào)試等諸多功能,而且支持C/C++和匯編的混合編程,其主要功能如下:具有集成可視化代碼編輯界面,用戶可通過其界面直接編寫C、匯編、.cmd文件等;含有集成代碼生成工具,包括匯編器、優(yōu)化C編譯器、鏈接器等,將代碼的編輯、編譯、鏈接和調(diào)試等諸多功能集成到一個軟件環(huán)境中;高性能編輯器支持匯編文件的動態(tài)語法加亮顯示,使用戶很容易閱讀代碼,發(fā)現(xiàn)語法錯誤;工程項目管理工具可對用戶程序?qū)嵭许椖抗芾?。在生成目?biāo)程序和程序庫的過程中,建立不同

20、程序的跟蹤信息,通過跟蹤信息對不同的程序進(jìn)行分類管理;基本調(diào)試工具具有裝入執(zhí)行代碼、查看寄存器、存儲器、反匯編、變量窗口等功能,并支持C源代碼級調(diào)試;斷點工具,能在調(diào)試程序的過程中,完成硬件斷點、軟件斷點和條件斷點的設(shè)置;探測點工具,可用于算法的仿真,數(shù)據(jù)的實時監(jiān)視等;分析工具,包括模擬器和仿真器分析,可用于模擬和監(jiān)視硬件的功能、評價代碼執(zhí)行的時鐘;數(shù)據(jù)的圖形顯示工具,可以將運算結(jié)果用圖形顯示,包括顯示時域/頻域波形、眼圖、星座圖、圖像

21、等,并能進(jìn)行自動刷新;提供GEL工具。利用GEL擴(kuò)展語言,用戶可以編寫自己的控</p><p>  CCS支持多DSP的調(diào)試,支持RTDX技術(shù),可在不中斷目標(biāo)系統(tǒng)運行的情況下,實現(xiàn)DSP與其他應(yīng)用程序的數(shù)據(jù)交換,提供DSP/BIOS工具,增強(qiáng)對代碼的實時分析能力。</p><p>  2.2 µC/OS-II簡介</p><p>  uC/OS是一種免費

22、公開源代碼、結(jié)構(gòu)小巧、具有可剝奪實時內(nèi)核的實時操作系統(tǒng)。μC/OS-II 的前身是μC/OS,最早出自于1992 年美國嵌入式系統(tǒng)專家Jean J.Labrosse 在《嵌入式系統(tǒng)編程》雜志的5月和6月刊上刊登的文章連載,并把μC/OS 的源碼發(fā)布在該雜志的B B S 上。</p><p>  μC/OS和μC/OS-II是專門為計算機(jī)的嵌入式應(yīng)用設(shè)計的, 絕大部分代碼是用C語言編寫的。CPU硬件相關(guān)部分是用匯編

23、語言編寫的、總量約200行的匯編語言部分被壓縮到最低限度,為的是便于移植到任何一種其它的CPU上。用戶只要有標(biāo)準(zhǔn)的ANSI的C交叉編譯器,有匯編器、連接器等軟件工具,就可以將μC/OS-II嵌人到開發(fā)的產(chǎn)品中。μC/OS-II具有執(zhí)行效率高、占用空間小、實時性能優(yōu)良和可擴(kuò)展性強(qiáng)等特點, 最小內(nèi)核可編譯至 2KB 。μC/OS-II 已經(jīng)移植到了幾乎所有知名的CPU上。</p><p>  嚴(yán)格地說uC/OS-II

24、只是一個實時操作系統(tǒng)內(nèi)核,它僅僅包含了任務(wù)調(diào)度,任務(wù)管理,時間管理,內(nèi)存管理和任務(wù)間的通信和同步等基本功能。沒有提供輸入輸出管理,文件系統(tǒng),網(wǎng)絡(luò)等額外的服務(wù)。但由于uC/OS-II良好的可擴(kuò)展性和源碼開放,這些非必須的功能完全可以由用戶自己根據(jù)需要分別實現(xiàn)。</p><p>  uC/OS-II目標(biāo)是實現(xiàn)一個基于優(yōu)先級調(diào)度的搶占式的實時內(nèi)核,并在這個內(nèi)核之上提供最基本的系統(tǒng)服務(wù),如信號量,郵箱,消息隊列,內(nèi)存管理

25、,中斷管理等。</p><p><b>  2.3 信號量 </b></p><p>  µC/OS-II中的信號量由兩部分組成:一個是信號量的計數(shù)值,它是一個16位的無符號整數(shù)(0 到65,535之間);另一個是由等待該信號量的任務(wù)組成的等待任務(wù)表。用戶要在OS_CFG.H中將OS_SEM_EN開關(guān)量常數(shù)置成1,這樣µC/OS-II才能支持信號量

26、。 在使用一個信號量之前,首先要建立該信號量,也即調(diào)用OSSemCreate()函數(shù),對信號量的初始計數(shù)值賦值。該初始值為0到65,535之間的一個數(shù)。如果信號量是用來表示一個或者多個事件的發(fā)生,那么該信號量的初始值應(yīng)設(shè)為0。如果信號量是用于對共享資源的訪問,那么該信號量的初始值應(yīng)設(shè)為1(例如,把它當(dāng)作二值信號量使用)。最后,如果該信號量是用來表示允許任務(wù)訪問n個相同的資源,那么該初始值顯然應(yīng)該是n,并把該信號量作為一個可計數(shù)的信號量使

27、用。 </p><p>  µC/OS-II提供了5個對信號量進(jìn)行操作的函數(shù)。它們是:OSSemCreate(),OSSemPend(),OSSemPost(),OSSemAccept()和OSSemQuery()函數(shù)。圖2-1說明了任務(wù)、中斷服務(wù)子程序和信號量之間的關(guān)系。圖中用鑰匙或者旗幟的符號來表示信號量:如果信號量用于對共享資源的訪問,那么信號量就用鑰匙符號。符號旁邊的數(shù)字N代表可用資源數(shù)。對于二

28、值信號量,該值就是1;如果信號量用于表示某事件的發(fā)生,那么就用旗幟符號。這時的數(shù)字N代表事件已經(jīng)發(fā)生的次數(shù)。從圖2-1中可以看出OSSemPost()函數(shù)可以由任務(wù)或者中斷服務(wù)子程序調(diào)用,而OSSemPend()和OSSemQuery()函數(shù)只能有任務(wù)程序調(diào)用。 </p><p><b>  2.4 郵箱 </b></p><p>  郵箱是µC/OS-II

29、中另一種通訊機(jī)制,它可以使一個任務(wù)或者中斷服務(wù)子程序向另一個任務(wù)發(fā)送一個指針型的變量。該指針指向一個包含了特定“消息”的數(shù)據(jù)結(jié)構(gòu)。為了在µC/OS-II中使用郵箱,必須將OS_CFG.H中的OS_MBOX_EN常數(shù)置為1。使用郵箱之前,必須先建立該郵箱。該操作可以通過調(diào)用OSMboxCreate()函數(shù)來完成,并且要指定指針的初始值。一般情況下,這個初始值是NULL,但也可以初始化一個郵箱,使其在最開始就包含一條消息。如果使用

30、郵箱的目的是用來通知一個事件的發(fā)生(發(fā)送一條消息),那么就要初始化該郵箱為NULL,因為在開始時,事件還沒有發(fā)生。如果用戶用郵箱來共享某些資源,那么就要初始化該郵箱為一個非NULL的指針。在這種情況下,郵箱被當(dāng)成一個二值信號量使用。µC/OS-II提供了5種對郵箱的操作:OSMboxCreate(),OSMboxPend(),OSMboxPost(), OSMboxAccept()和OSMboxQuery()函數(shù)。圖2-2描述

31、了任務(wù)、中斷服務(wù)子程序和郵箱之間的關(guān)系,這里用符號“I”表示郵箱。郵箱包含的內(nèi)容是一個指向一條消息的指針。一個郵箱只能</p><p>  圖 2-2 任務(wù)、中斷服務(wù)子程序和郵箱之間的關(guān)系</p><p><b>  2.5 消息隊列 </b></p><p>  消息隊列是µC/OS-II中另一種通訊機(jī)制,它可以使一個任務(wù)或者中斷

32、服務(wù)子程序向另一個任務(wù)發(fā)送以指針方式定義的變量。因具體的應(yīng)用有所不同,每個指針指向的數(shù)據(jù)結(jié)構(gòu)變量也有所不同。為了使用µC/OS-II的消息隊列功能,需要在OS_CFG.H 文件中,將OS_Q_EN常數(shù)設(shè)置為1,并且通過常數(shù)OS_MAX_QS來決定µC/OS-II支持的最多消息隊列數(shù)。在使用一個消息隊列之前,必須先建立該消息隊列。這可以通過調(diào)用OSQCreate()函數(shù),并定義消息隊列中的單元數(shù)(消息數(shù))來完成。

33、81;C/OS-II提供了7個對消息隊列進(jìn)行操作的函數(shù):OSQCreate(),OSQPend(),OSQPost(), OSQPostFront(),OSQAccept(),OSQFlush()和OSQQuery()函數(shù)。圖2-3是任務(wù)、中斷服務(wù)子程序和消息隊列之間的關(guān)系。其中,消息隊列的符號很像多個郵箱。實際上,我們可以將消息隊列看作時多個郵箱組成的數(shù)組,只是它們共用一個等待任務(wù)列表。每個指針?biāo)赶虻臄?shù)據(jù)結(jié)構(gòu)是由具體的應(yīng)用程序決定的

34、。N代表了消息隊列中的總單元數(shù)。當(dāng)調(diào)用OSQPend()或者OSQAccept()</p><p>  圖 2-3 任務(wù)、中斷服務(wù)子程序和消息隊列之間的關(guān)系</p><p>  圖2-4是實現(xiàn)消息隊列所需要的各種數(shù)據(jù)結(jié)構(gòu)。這里也需要事件控制塊來記錄等待任務(wù)列表,而且,事件控制塊可以使多個消息隊列的操作和信號量操作、郵箱操作相同的代碼。當(dāng)建立了一個消息隊列時,一個隊列控制塊(OS_Q結(jié)構(gòu),見

35、OS_Q.C文件)也同時被建立,并通過OS_EVENT中的.OSEventPtr域鏈接到對應(yīng)的事件控制塊。在建立一個消息隊列之前,必須先定義一個含有與消息隊列最大消息數(shù)相同個數(shù)的指針數(shù)組。數(shù)組的起始地址以及數(shù)組中的元素數(shù)作為參數(shù)傳遞給OSQCreate()函數(shù)。事實上,如果內(nèi)存占用了連續(xù)的地址空間,也沒有必要非得使用指針數(shù)組結(jié)構(gòu)。文件OS_CFG.H中的常數(shù)OS_MAX_QS定義了在µC/OS- II中可以使用的最大消息隊列數(shù)

36、,這個值最小應(yīng)為2。µC/OS-II在初始化時建立一個空閑的隊列控制塊鏈表,如圖2-5所示。 </p><p>  圖2-4 用于消息隊列的數(shù)據(jù)結(jié)構(gòu)</p><p>  圖 2-5 空閑隊列控制塊鏈表</p><p>  隊列控制塊是一個用于維護(hù)消息隊列信息的數(shù)據(jù)結(jié)構(gòu),它包含了以下的一些域。這里,仍然在各個變量前加入一個[.]來表示它們是數(shù)據(jù)結(jié)構(gòu)中的一個域

37、。.OSQPtr在空閑隊列控制塊中鏈接所有的隊列控制塊。一旦建立了消息隊列,該域就不再有用了。而.OSQStart是指向消息隊列的指針數(shù)組的起始地址的指針。用戶應(yīng)用程序在使用消息隊列之前必須先定義該數(shù)組。 .OSQEnd是指向消息隊列結(jié)束單元的下一個地址的指針。該指針使得消息隊列構(gòu)成一個循環(huán)的緩沖區(qū)。 .OSQIn是指向消息隊列中插入下一條消息的位置的指針。當(dāng).OSQIn和.OSQEnd相等時,.OSQIn被調(diào)整指向消息隊列的起始單元。

38、 .OSQOut是指向消息隊列中下一個取出消息位置的指針。當(dāng).OSQOut和.OSQEnd相等時,.OSQOut被調(diào)整指向消息隊列的起始單元。 .OSQSize是消息隊列中總的單元數(shù)。該值是在建立消息隊列時由用戶應(yīng)用程序決定的。在µC/OS-II中,該值最大可以是6553 5。.OSQEntries是消息隊列中當(dāng)前的消息數(shù)量。當(dāng)消息隊列是空的時,該值為0。當(dāng)消息隊列滿了以后,該值和.OSQSize值一樣。 在消息隊列剛剛<

39、;/p><p>  圖 2-6 消息隊列是一個由指針組成的循環(huán)緩沖區(qū)</p><p><b>  3 系統(tǒng)詳細(xì)設(shè)計</b></p><p>  3.1 建立一個郵箱,OSMboxCreate() </p><p>  下面是OSMboxCreate()函數(shù)的源代碼。在于事件控制塊的類型被設(shè)置成OS_EVE NT_TYPE_M

40、BOX,以及使用.OSEventPtr域來容納消息指針,而不是使用.OSEventCnt域。OSMboxCreate()函數(shù)的返回值是一個指向事件控制塊的指針。這個指針在調(diào)用函數(shù)OSMboxPend (),OSMboxPost(),OSMboxAccept()和OSMb oxQuery()時使用。因此,該指針可以看作是對應(yīng)郵箱的句柄。值得注意的是,如果系統(tǒng)中已經(jīng)沒有事件控制塊可用,函數(shù)OSMboxCreate()將返回一個NULL指針。

41、郵箱一旦建立,是不能被刪除的。比如,如果有任務(wù)正在等待一個郵箱的信息,這時刪除該郵箱,將有可能產(chǎn)生災(zāi)難性的后果。 </p><p>  OS_EVENT *OSMboxCreate (void *msg) </p><p><b>  { </b></p><p>  OS_EVENT *pevent; </p><p>

42、;  OS_ENTER_CRITICAL(); </p><p>  pevent = OSEventFreeList; </p><p>  if (OSEventFreeList != (OS_EVENT *)0)</p><p><b>  { </b></p><p>  OSEventFreeList = (O

43、S_EVENT *)OSEventFreeList->OSEventPtr; </p><p><b>  } </b></p><p>  OS_EXIT_CRITICAL(); </p><p>  if (pevent != (OS_EVENT *)0) </p><p><b>  { </

44、b></p><p>  pevent->OSEventType = OS_EVENT_TYPE_MBOX; </p><p>  pevent->OSEventPtr = msg; </p><p>  OSEventWaitListI

45、nit(pevent); </p><p><b>  } </b></p><p>  return (pevent); </p><p><b>  } </b></p><p>  3.2 等待一個郵箱

46、中的消息,OSMboxPend() </p><p>  下面是OSMboxPend()函數(shù)的源代碼。OSMboxPend()首先檢查該事件控制塊是由OSMboxCreate()函數(shù)建立的。當(dāng).OSEventPtr域是一個非NULL的指針時,說明該郵箱中有可用的消息。這種情況下,OSMboxPend()函數(shù)將該域的值復(fù)制到局部變量msg中,然后將.OSEventPtr置為NULL。這正是我們所期望的,也是執(zhí)行OS

47、 MboxPend()函數(shù)最快的路徑。如果此時郵箱中沒有消息是可用的(.OSEvent Ptr域是NULL指針),OSMbox Pend()函數(shù)檢查它的調(diào)用者是否是中斷服務(wù)子程序。和OSSemPend()函數(shù)一樣,不能在中斷服務(wù)子程序中調(diào)用OSMboxPend(),因為中斷服務(wù)子程序是不能等待的。這里的代碼同樣是為了以防萬一.但是,如果郵箱中有可用的消息,即使從中斷服務(wù)子程序中調(diào)用OSMboxPend()函數(shù),也一樣是成功的。如果郵箱中

48、沒有可用的消息,OSMboxPend()的調(diào)用任務(wù)就被掛起,直到郵箱中有了消息或者等待超時。當(dāng)有其它的任務(wù)向該郵箱發(fā)送了消息后(或者等待時間超時),這時,該任務(wù)再一次成為最高優(yōu)先級任務(wù),OSS ched</p><p>  void *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err) </p><p><b>  

49、{ </b></p><p>  void *msg; </p><p>  OS_ENTER_CRITICAL(); </p><p>  if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) </p><p>  { </p><p

50、>  OS_EXIT_CRITICAL(); </p><p>  *err = OS_ERR_EVENT_TYPE; </p><p>  return ((void *)0); </p><p><b>  } </b></p><p>  msg = pevent->OSEventPtr; </p

51、><p>  if (msg != (void *)0) </p><p>  { </p><p>  pevent->OSEventPtr = (void *)0; </p><p>  OS_EXIT_C

52、RITICAL(); </p><p>  *err = OS_NO_ERR; </p><p><b>  } </b></p><p>  else if (OSIntNesting > 0) </p><p>  { </p><

53、;p>  OS_EXIT_CRITICAL(); </p><p>  *err = OS_ERR_PEND_ISR; </p><p><b>  } </b></p><p><b>  else </b></p><p><b>  { </b></p>

54、<p>  OSTCBCur->OSTCBStat |= OS_STAT_MBOX; </p><p>  OSTCBCur->OSTCBDly = timeout; </p><p>  OSEventTaskWait(pevent); </p><p>  OS_EXIT_CRITICAL

55、(); </p><p>  OSSched(); </p><p>  OS_ENTER_CRITICAL(); </p><p>  if ((msg = OSTCBCur->OSTCBMsg) != (void *)0) </p><p><b>  {</b></p><p>  O

56、STCBCur->OSTCBMsg = (void *)0; </p><p>  OSTCBCur->OSTCBStat= OS_STAT_RDY; </p><p>  OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; </p><p>  OS_EXIT_CRITICAL(); </p><

57、p>  *err= OS_NO_ERR; </p><p><b>  } </b></p><p>  else if (OSTCBCur->OSTCBStat & OS_STAT_MBOX) </p><p>  { </p><p>  OSEventTO(pevent);

58、 </p><p>  OS_EXIT_CRITICAL(); </p><p>  msg= (void *)0; </p><p>  *err= OS_TIMEOUT; </p><p><b>  } </b>&l

59、t;/p><p><b>  else { </b></p><p>  msg= pevent->OSEventPtr; </p><p>  pevent->OSEventPtr= (void *)0; </p><p>  OSTCBCur-&

60、gt;OSTCBEventPtr = (OS_EVENT *)0; </p><p>  OS_EXIT_CRITICAL(); </p><p>  *err= OS_NO_ERR; </p><p><b>  } </b></p><p><b>  } </b>&l

61、t;/p><p>  return (msg); </p><p><b>  } </b></p><p>  在OSMboxPend()函數(shù)中,通過檢查任務(wù)控制塊中的.OSTCBStat域中的OS_ STAT _MBOX位,可以知道是否等待超時。如果該域被置1,說明任務(wù)等待已經(jīng)超時。這時,通過調(diào)用函數(shù)OSEventTo()可以將任務(wù)從郵箱的等待

62、列表中刪除。因為此時郵箱中沒有消息,所以返回的指針是NULL。如果OS_STAT_MBOX位沒有被置1,說明所等待的消息已經(jīng)被發(fā)出。OSMboxPend()的調(diào)用函數(shù)得到指向消息的指針。此后,OSMboxPend()函數(shù)通過將郵箱事件控制塊的.OSEventPtr域置為NULL清空該郵箱,并且要將任務(wù)任務(wù)控制塊中指向郵箱事件控制塊的指針刪除。 </p><p>  3.3 發(fā)送一個消息到郵箱中,OSMboxPos

63、t() </p><p>  下面是OSMboxPost()函數(shù)的源代碼。檢查了事件控制塊是否是一個郵箱后,OSM boxPost()函數(shù)還要檢查是否有任務(wù)在等待該郵箱中的消息。如果事件控制塊中的OSEv entGrp域包含非零值,就暗示著有任務(wù)在等待該消息。這時,調(diào)用OSEventTaskRdy()將其中的最高優(yōu)先級任務(wù)從等待列表中刪除,加入系統(tǒng)的就緒任務(wù)列表中,準(zhǔn)備運行。然后,調(diào)用OSSched()函數(shù),檢查

64、該任務(wù)是否是系統(tǒng)中最高優(yōu)先級的就緒任務(wù)。如果是,執(zhí)行任務(wù)切換,該任務(wù)得以執(zhí)行。如果該任務(wù)不是最高優(yōu)先級的任務(wù),OSSched()返回,OSMboxPost()的調(diào)用函數(shù)繼續(xù)執(zhí)行。如果沒有任何任務(wù)等待該消息,指向消息的指針就被保存到郵箱中(假設(shè)此時郵箱中的指針不是非NULL的)。這樣,下一個調(diào)用OSM boxPend()函數(shù)的任務(wù)就可以立刻得到該消息了。注意,如果OSMboxPost()函數(shù)是從中斷服務(wù)子程序中調(diào)用的,那么,這時并不發(fā)生上

65、下文的切換。</p><p>  INT8U OSMboxPost (OS_EVENT *pevent, void *msg) </p><p><b>  { </b></p><p>  OS_ENTER_CRITICAL(); </p><p>  if (pevent->OSEventType != OS_

66、EVENT_TYPE_MBOX) </p><p><b>  { </b></p><p>  OS_EXIT_CRITICAL(); </p><p>  return (OS_ERR_EVENT_TYPE); </p><p><b>  } </b></p><p>

67、  if (pevent->OSEventGrp) </p><p>  { </p><p>  OSEventTaskRdy(pevent, msg, OS_STAT_MBOX); </p><p>  OS_EXIT_CRITICAL(); </p><p>  OS

68、Sched(); </p><p>  return (OS_NO_ERR); </p><p><b>  } </b></p><p><b>  else </b></p><p><b>  { </b&

69、gt;</p><p>  if (pevent->OSEventPtr != (void *)0) </p><p>  { </p><p>  OS_EXIT_CRITICAL(); </p><p>  return (OS_MBOX_FULL); </p><p><b

70、>  } </b></p><p><b>  else </b></p><p><b>  { </b></p><p>  pevent->OSEventPtr = msg; </p><p>  OS_EXIT_CRITICAL(); </p>&l

71、t;p>  return (OS_NO_ERR); </p><p><b>  } </b></p><p><b>  } </b></p><p><b>  } </b></p><p>  3.4 無等待地從郵箱中得到一個消息, OSMboxAccept() &

72、lt;/p><p>  應(yīng)用程序也可以以無等待的方式從郵箱中得到消息。這可以通過下面程序中的OSMboxAccept()函數(shù)來實現(xiàn)。OSMboxAccept()函數(shù)開始也是檢查事件控制塊是否是由OSMboxCreate()函數(shù)建立的。接著,它得到郵箱中的當(dāng)前內(nèi)容,并判斷是否有消息是可用的。如果郵箱中有消息,就把郵箱清空,而郵箱中原來指向消息的指針被返回給OSMboxAccept()的調(diào)用函數(shù)。OSMboxAccept

73、()函數(shù)的調(diào)用函數(shù)必須檢查該返回值是否為NULL。如果該值是NULL,說明郵箱是空的,沒有可用的消息。如果該值是非NULL值,說明郵箱中有消息可用,而且該調(diào)用函數(shù)已經(jīng)得到了該消息。中斷服務(wù)子程序在試圖得到一個消息時,應(yīng)該使用OSMbox Accept()函數(shù),而不能使用OSMboxPend()函數(shù)。OSMboxAccept()函數(shù)的另一個用途是,用戶可以用它來清空一個郵箱中現(xiàn)有的內(nèi)容。 </p><p>  v

74、oid *OSMboxAccept (OS_EVENT *pevent) </p><p><b>  { </b></p><p>  void *msg; </p><p>  OS_ENTER_CRITICAL(); </p><p>  if (pevent->OSEventType != OS_EVEN

75、T_TYPE_MBOX) </p><p><b>  { </b></p><p>  OS_EXIT_CRITICAL(); </p><p>  return ((void *)0); </p><p><b>  } </b></p><p>  msg = peve

76、nt->OSEventPtr; </p><p>  if (msg != (void *)0) </p><p>  { </p><p>  pevent->OSEventPtr = (void *)0;

77、 </p><p><b>  } </b></p><p>  OS_EXIT_CRITICAL(); </p><p>  return (msg); </p><p><b>  、} </b></p><p>  3

78、.5 查詢一個郵箱的狀態(tài), OSMboxQuery() </p><p>  OSMboxQuery()函數(shù)使應(yīng)用程序可以隨時查詢一個郵箱的當(dāng)前狀態(tài)。下面是該函數(shù)的源代碼。它需要兩個參數(shù):一個是指向郵箱的指針pevent。該指針是在建立該郵箱時,由OSMboxCreate()函數(shù)返回的;另一個是指向用來保存有關(guān)郵箱的信息的OS_MBOX _ DATA數(shù)據(jù)結(jié)構(gòu)的指針pdata。在調(diào)用OSMboxCreate()函數(shù)

79、之前,必須先定義該結(jié)構(gòu)變量,用來保存有關(guān)郵箱的信息。之所以定義一個新的數(shù)據(jù)結(jié)構(gòu),是因為這里關(guān)心的只是和特定郵箱有關(guān)的內(nèi)容,而非整個OS_EVENT數(shù)據(jù)結(jié)構(gòu)的內(nèi)容。后者還包含了另外兩個域(.OSEventCnt和.OSEventType),而OS_MBOX_DATA只包含郵箱中的消息指針(.OSMsg)和該郵箱現(xiàn)有的等待任務(wù)列表(.OSEventTbl[]和.OSEventGrp)。和前面的所以函數(shù)一樣,該函數(shù)也是先檢查事件控制是否是郵箱

80、。然后,將郵箱中的等待任務(wù)列表和郵箱中的消息從OS_EVENT數(shù)據(jù)結(jié)構(gòu)復(fù)制到OS_MBOX_DATA數(shù)據(jù)結(jié)構(gòu)。</p><p>  INT8U OSMboxQuery (OS_EVENT *pevent, OS_MBOX_DATA *pdata) </p><p><b>  { </b></p><p>  INT8U i; </p&

81、gt;<p>  INT8U *psrc; </p><p>  INT8U *pdest; </p><p>  OS_ENTER_CRITICAL(); </p><p>  if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) </p><p>  { <

82、;/p><p>  OS_EXIT_CRITICAL(); </p><p>  return (OS_ERR_EVENT_TYPE); </p><p><b>  } </b></p><p>  pdata->OSEventGrp = pevent->OSEventGrp;

83、</p><p>  psrc= &pevent->OSEventTbl[0]; </p><p>  pdest= &pdata->OSEventTbl[0]; </p><p>  for (i = 0; i < OS_EVENT_TBL_SIZE; i++) </p><p><b>  {

84、</b></p><p>  *pdest++ = *psrc++; </p><p><b>  } </b></p><p>  pdata->OSMsg= pevent->OSEventPtr; </p><p>  OS_EXIT_CRITICAL(); &l

85、t;/p><p>  return (OS_NO_ERR); </p><p><b>  } </b></p><p>  3.6 用郵箱作二值信號量 </p><p>  一個郵箱可以被用作二值的信號量。首先,在初始化時,將郵箱設(shè)置為一個非零的指針(如 void *1)。這樣,一個任務(wù)可以調(diào)用OSMboxPend()函數(shù)

86、來請求一個信號量,然后通過調(diào)用OSMboxPost()函數(shù)來釋放一個信號量。下面程序說明了這個過程是如何工作的。如果用戶只需要二值信號量和郵箱,這樣做可以節(jié)省代碼空間。這時可以將OS_SEM_EN設(shè)置為0,只使用郵箱就可以了。 </p><p>  OS_EVENT *MboxSem; </p><p>  void Task1 (void *pdata) </p><

87、;p><b>  { </b></p><p>  INT8U err; </p><p><b>  for (;;) </b></p><p><b>  { </b></p><p>  OSMboxPend(MboxSem, 0, &err); /*

88、獲得對資源的訪問權(quán) */ </p><p><b>  .</b></p><p>  . /* 任務(wù)獲得信號量,對資源進(jìn)行訪問 */ </p><p><b>  .</b></p><p>  OSMboxPost(MboxSem, (void*)1); /* 釋放對資源的訪問權(quán) */ &

89、lt;/p><p><b>  } </b></p><p><b>  } </b></p><p>  3.7 用郵箱實現(xiàn)延時,而不使用OSTimeDly() </p><p>  郵箱的等待超時功能可以被用來模仿OSTimeDly()函數(shù)的延時,如下程序所示。如果在指定的時間段TIMEOUT內(nèi),沒

90、有消息到來,Task1()函數(shù)將繼續(xù)執(zhí)行。這和OSTim eDly(TIMEOUT)功能很相似。但是,如果Task2()在指定的時間結(jié)束之前,向該郵箱發(fā)送了一個“啞”消息,Task1()就會提前開始繼續(xù)執(zhí)行。這和調(diào)用OSTimeDlyResume()函數(shù)的功能是一樣的。注意,這里忽略了對返回的消息的檢查,因為此時關(guān)心的不是得到了什么樣的消息。 </p><p>  OS_EVENT *MboxTimeDly;

91、</p><p>  void Task1 (void *pdata) </p><p><b>  { </b></p><p>  INT8U err; </p><p><b>  for (;;) </b></p><p><b>  { </b>

92、;</p><p>  OSMboxPend(MboxTimeDly, TIMEOUT, &err); /* 延時該任務(wù) */ </p><p><b>  .</b></p><p>  . /* 延時結(jié)束后執(zhí)行的代碼 */ </p><p><b>  . </b></p

93、><p><b>  } </b></p><p><b>  } </b></p><p>  void Task2 (void *pdata) </p><p><b>  { </b></p><p>  INT8U err; </p>

94、<p><b>  for (;;) </b></p><p><b>  { </b></p><p>  OSMboxPost(MboxTimeDly, (void *)1); /* 取消任務(wù)1的延時 */ </p><p><b>  . </b></p><

95、p><b>  . </b></p><p><b>  } </b></p><p><b>  } </b></p><p><b>  4 源程序</b></p><p>  #include "includes.h" &l

96、t;/p><p>  #include "ioports.h"</p><p>  #define IMR*(volatile unsigned int*)0x00</p><p>  #define IFR*(volatile unsigned int*)0x01</p><p>  #define TASK_STK_S

97、IZE 256 /* Size of each task's stacks (# of WORDs) */</p><p>  #define N_TASKS 2 /* Number of identical tasks */</p><p>  OS_STK TaskStk[N_TASKS][TASK_STK_SIZE]; /* Tasks stac

98、ks */</p><p>  OS_STK task_startStk[TASK_STK_SIZE];</p><p>  #define ADJUST_DSP_CLKclk_adjust</p><p>  void task_start(void *data);</p><p>  void task_led(void *d

99、ata);</p><p>  void task_segs(void *data);</p><p>  unsigned int seg7[16] = </p><p>  {0x03f|0x80, 0x006, 0x05b, 0x04f, 0x066, 0x06d, 0x07d, 0x007,</p><p>  0x07f, 0x06

100、f, 0x077, 0x07c, 0x039, 0x05e, 0x079, 0x071};</p><p>  /* mailbox event control blocks */</p><p>  OS_EVENT *Mbox;</p><p>  void hard_delay(int cnt)</p><p><b>  {

101、</b></p><p>  while(cnt--);</p><p><b>  }</b></p><p>  void clk_adjust()</p><p><b>  {</b></p><p>  asm("stm #0b, CLKM

102、D");</p><p>  asm("ChkForRdy:");</p><p>  asm("ldmCLKMD, A");</p><p>  asm("and #01b,A");</p><p>  asm("bc ChkFo

103、rRdy, ANEQ");</p><p>  asm("stm #33efh, CLKMD");</p><p>  asm("rpt #80h");</p><p>  asm("nop");</p><p><b>  }</b>&

104、lt;/p><p>  void main()</p><p>  { /* 板卡IO端口及外設(shè)初始狀態(tài)初始化 */</p><p>  LED_DAT = 0x01;</p><p>  ADJUST_DSP_CLK();</p><p>  INIT_C54(); </p><p><b

105、>  OSInit();</b></p><p>  OSTaskCreate(task_start, (void *)0, </p><p>  (void *)&task_startStk[TASK_STK_SIZE - 1], 0);</p><p>  OSStart();</p><p><b>

106、  while(1);</b></p><p><b>  }</b></p><p>  void task_start(void *data)</p><p><b>  { </b></p><p>  UBYTE err;</p><p>  OS_E

107、NTER_CRITICAL();</p><p>  StartTimer();/* install the C54x Timer */</p><p>  OS_EXIT_CRITICAL();</p><p>  Mbox = OSMboxCreate((void *)0); </p><p>  OSTaskCreate(

108、task_led, (void *)0, </p><p>  (void *)&TaskStk[0][TASK_STK_SIZE - 1], 2);</p><p>  OSTaskCreate(task_segs, (void *)0, </p><p>  (void *)&TaskStk[1][TASK_STK_SIZE - 1], 3);

109、</p><p><b>  for (;;){</b></p><p><b>  err++;</b></p><p>  OSTimeDly(100); /* Delay 100 clock tick */</p><p><b>  }</b></p>

110、<p><b>  }</b></p><p>  void task_led(void *data)</p><p><b>  {</b></p><p>  int index = 0;</p><p>  for( index = 0; ; index++)</p>

111、<p><b>  {</b></p><p>  OSMboxPost(Mbox, (void*)(index&0x07));</p><p>  LED_DAT = 0x01<<(index&0x07);</p><p>  OSTimeDly(2000); </p><p>

112、;<b>  }</b></p><p><b>  }</b></p><p>  void task_segs(void *data)</p><p><b>  {</b></p><p>  int Msg;</p><p>  INT8U

113、err;</p><p>  SEG7_CLOSE(2);</p><p>  SEG7_CLOSE(3);</p><p>  SEG7_CLOSE(4);</p><p>  SEG7_CLOSE(5);</p><p>  SEG7_CLOSE(6);</p><p>  SEG7_CL

114、OSE(7);</p><p>  SEG7_CLOSE(8);</p><p>  SEG7_OPEN(1);</p><p><b>  while(1)</b></p><p>  {/* wait for a message from the input mailbox */</p><p&

115、gt;  Msg = (int)OSMboxPend(Mbox, 0, &err);</p><p>  SEG7_DAT = ~seg7[Msg];</p><p><b>  }</b></p><p><b>  return;</b></p><p><b>  }<

116、/b></p><p><b>  總結(jié)</b></p><p>  通過本次課程設(shè)計,我掌握了µC/OS-II中用郵箱的方法保護(hù)任務(wù)之間的共享數(shù)據(jù)和提供任務(wù)之間的通訊,同時也對DSP有了更好的掌握。在其的過程中我們遇到了很多問題,如:CCS軟件的調(diào)試和硬件的實現(xiàn)等。整個課程設(shè)計的難點在于軟件的調(diào)試。在課程設(shè)計的最后才發(fā)現(xiàn)了缺少一個.lib系統(tǒng)文件

117、,通過添加其最后完成了調(diào)試。在硬件的實現(xiàn)方面也遇到了困難。終于經(jīng)過一次次的教訓(xùn)后,最終顯示了正確的結(jié)果。</p><p>  通過本次課程設(shè)計,對DSP硬件電路有了很多更新的認(rèn)識,讓原來紙面化的知識變成了實際的。也讓模擬電路、數(shù)字電路和DSP應(yīng)用相關(guān)的知識得到了鞏固,同時基本熟練了CCS軟件和其對應(yīng)試驗箱的使用。在實際的實踐過程中,不僅是讓我們了解DSP基礎(chǔ)的理論知識,更重要的是培養(yǎng)解決實際問題的能力,所以相信通

118、過此次實習(xí)可以提高我們分析設(shè)計能力和實踐能力,為后續(xù)課程的學(xué)習(xí)及實踐打下良好的基礎(chǔ)。</p><p>  在這次短短的課程實踐里,我們得到了zz老師的關(guān)心和幫助。他給了我們很多的信息,與我一起探討問題,詢問我遇到了哪些問題并耐心給予指導(dǎo)。當(dāng)我遇到技術(shù)上難以解決的問題時,他就會指導(dǎo)我們解決問題,他把自己多年來積累的經(jīng)驗教授給我,使我順利地完成了課程實踐任務(wù)。時間過得真快,大學(xué)生活不知不覺就走過了快3年了,在近3年的

119、大學(xué)學(xué)習(xí)和課程實踐階段的提高,使我們本身知識得到提高的同時,也增強(qiáng)了我們對未來工作的信心,我們相信自己未來兩年的學(xué)習(xí)更使我們有能力勝任將來的工作。</p><p><b>  參考文獻(xiàn)</b></p><p>  1 喬瑞萍,崔濤,張芳娟.TMS320C54x DSP原理及應(yīng)用.西安:西安電子科技大學(xué)出版社,2009</p><p>  2 李

120、利.DSP原理及應(yīng)用.北京:中國水利水電出版社,2004</p><p>  3 張勇.C/C++語言硬件程序設(shè)計——基于TMS320C5000系列DSP.西安:西安電子科技大學(xué)出版社 2003</p><p>  4 鄒彥.DSP原理及應(yīng)用.北京:電子工業(yè)出版社,2005</p><p>  5 張雄偉.DSP集成開發(fā)與應(yīng)用實例.北京:電子工業(yè)出版社,2002&l

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論