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

下載本文檔

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

文檔簡介

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

2、班 級: 計算機1073班 </p><p>  姓 名: 學 號: </p><p>  指導教師: </p><p>  學年學期: 2009 ~ 2010 學年 第 2

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

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

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

6、><p><b>  目錄</b></p><p><b>  1 課題綜述1</b></p><p>  1.1 課題性質和目的1</p><p>  1.2 課題設計任務1</p><p>  1.3 課題設計要求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)詳細設計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>  總 結20</b></p><p><b>  參考文獻21</b></p><p><b>  1 課題綜述</b></p><p&

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

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

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

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

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

16、可以通過事件控制塊ECB來向另外的任務發(fā)信號,所有的信號都被看成是事件。一個任務還可以等待另一個任務或中斷服務子程序給它發(fā)送信號,只有任務可以等待事件發(fā)生,中斷服務子程序是不能這樣做的。對于處于等待狀態(tài)的任務,還可以給它指定一個最長等待時間,以此來防止因為等待的事件沒有發(fā)生而無限期地等下去。多個任務可以同時等待同一個事</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)境配置、源文件編輯、程序調試、跟蹤和分析等工具。 CCS有兩種工作模式,即 軟件仿真器模式:可以脫離DSP芯片,在PC機上模擬DSP的指令集和工作機制,主要用于前期算法實現(xiàn)和調試。 硬件在線編程模式:可以實時

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

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

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

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

22、公開源代碼、結構小巧、具有可剝奪實時內(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是專門為計算機的嵌入式應用設計的, 絕大部分代碼是用C語言編寫的。CPU硬件相關部分是用匯編

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

41、郵箱一旦建立,是不能被刪除的。比如,如果有任務正在等待一個郵箱的信息,這時刪除該郵箱,將有可能產(chǎn)生災難性的后果。 </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ù)建立的。當.OSEventPtr域是一個非NULL的指針時,說明該郵箱中有可用的消息。這種情況下,OSMboxPend()函數(shù)將該域的值復制到局部變量msg中,然后將.OSEventPtr置為NULL。這正是我們所期望的,也是執(zhí)行OS

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

48、沒有可用的消息,OSMboxPend()的調用任務就被掛起,直到郵箱中有了消息或者等待超時。當有其它的任務向該郵箱發(fā)送了消息后(或者等待時間超時),這時,該任務再一次成為最高優(yōu)先級任務,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ù)中,通過檢查任務控制塊中的.OSTCBStat域中的OS_ STAT _MBOX位,可以知道是否等待超時。如果該域被置1,說明任務等待已經(jīng)超時。這時,通過調用函數(shù)OSEventTo()可以將任務從郵箱的等待

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

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

64、該任務是否是系統(tǒng)中最高優(yōu)先級的就緒任務。如果是,執(zhí)行任務切換,該任務得以執(zhí)行。如果該任務不是最高優(yōu)先級的任務,OSSched()返回,OSMboxPost()的調用函數(shù)繼續(xù)執(zhí)行。如果沒有任何任務等待該消息,指向消息的指針就被保存到郵箱中(假設此時郵箱中的指針不是非NULL的)。這樣,下一個調用OSM boxPend()函數(shù)的任務就可以立刻得到該消息了。注意,如果OSMboxPost()函數(shù)是從中斷服務子程序中調用的,那么,這時并不發(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>  應用程序也可以以無等待的方式從郵箱中得到消息。這可以通過下面程序中的OSMboxAccept()函數(shù)來實現(xiàn)。OSMboxAccept()函數(shù)開始也是檢查事件控制塊是否是由OSMboxCreate()函數(shù)建立的。接著,它得到郵箱中的當前內(nèi)容,并判斷是否有消息是可用的。如果郵箱中有消息,就把郵箱清空,而郵箱中原來指向消息的指針被返回給OSMboxAccept()的調用函數(shù)。OSMboxAccept

73、()函數(shù)的調用函數(shù)必須檢查該返回值是否為NULL。如果該值是NULL,說明郵箱是空的,沒有可用的消息。如果該值是非NULL值,說明郵箱中有消息可用,而且該調用函數(shù)已經(jī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ù)使應用程序可以隨時查詢一個郵箱的當前狀態(tài)。下面是該函數(shù)的源代碼。它需要兩個參數(shù):一個是指向郵箱的指針pevent。該指針是在建立該郵箱時,由OSMboxCreate()函數(shù)返回的;另一個是指向用來保存有關郵箱的信息的OS_MBOX _ DATA數(shù)據(jù)結構的指針pdata。在調用OSMboxCreate()函數(shù)

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

80、。然后,將郵箱中的等待任務列表和郵箱中的消息從OS_EVENT數(shù)據(jù)結構復制到OS_MBOX_DATA數(shù)據(jù)結構。</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>  一個郵箱可以被用作二值的信號量。首先,在初始化時,將郵箱設置為一個非零的指針(如 void *1)。這樣,一個任務可以調用OSMboxPend()函數(shù)

86、來請求一個信號量,然后通過調用OSMboxPost()函數(shù)來釋放一個信號量。下面程序說明了這個過程是如何工作的。如果用戶只需要二值信號量和郵箱,這樣做可以節(jié)省代碼空間。這時可以將OS_SEM_EN設置為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、獲得對資源的訪問權 */ </p><p><b>  .</b></p><p>  . /* 任務獲得信號量,對資源進行訪問 */ </p><p><b>  .</b></p><p>  OSMboxPost(MboxSem, (void*)1); /* 釋放對資源的訪問權 */ &

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()在指定的時間結束之前,向該郵箱發(fā)送了一個“啞”消息,Task1()就會提前開始繼續(xù)執(zhí)行。這和調用OSTimeDlyResume()函數(shù)的功能是一樣的。注意,這里忽略了對返回的消息的檢查,因為此時關心的不是得到了什么樣的消息。 </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); /* 延時該任務 */ </p><p><b>  .</b></p><p>  . /* 延時結束后執(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); /* 取消任務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端口及外設初始狀態(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>  總結</b></p><p>  通過本次課程設計,我掌握了µC/OS-II中用郵箱的方法保護任務之間的共享數(shù)據(jù)和提供任務之間的通訊,同時也對DSP有了更好的掌握。在其的過程中我們遇到了很多問題,如:CCS軟件的調試和硬件的實現(xiàn)等。整個課程設計的難點在于軟件的調試。在課程設計的最后才發(fā)現(xiàn)了缺少一個.lib系統(tǒng)文件

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

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

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

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

溫馨提示

  • 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. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論