1、概述
VxWorks操作系統(tǒng)的集成環(huán)境叫Tornado。Tornado集成環(huán)境提供了高效明晰的圖形化的實(shí)時(shí)應(yīng)用開(kāi)發(fā)平臺(tái),它包括一套完整的面向
嵌入式系統(tǒng)的開(kāi)發(fā)和調(diào)測(cè)工具。Tornado環(huán)境采用主機(jī)-目標(biāo)機(jī)交叉開(kāi)發(fā)模型,應(yīng)用程序在主機(jī)的Windows環(huán)境下編譯鏈接生成可
執(zhí)行文件,下載到目標(biāo)機(jī),通過(guò)主機(jī)上的目標(biāo)服務(wù)器(Target Server)與目標(biāo)機(jī)上的目標(biāo)代理(Target Agent)的通信完成對(duì)
應(yīng)用程序的調(diào)試、分析。它主要由以下幾部分組成:
VxWorks高性能的實(shí)時(shí)操作系統(tǒng);
* 應(yīng)用編譯工具;
* 交互開(kāi)發(fā)工具;
下面對(duì)Tornado集成環(huán)境的各組件功能分別介紹:
* Tornado開(kāi)發(fā)環(huán)境
Tornado是集成了編輯器、編譯器、調(diào)試器于一體的高度集成的窗口環(huán)境,同樣也可以從Shell窗口下發(fā)命令和瀏覽。
* WindConfig:Tornado系統(tǒng)配置
通過(guò)WindConfig可選擇需要的組件組成VxWorks實(shí)時(shí)環(huán)境,并生成板級(jí)支持包BSP的配置。
通過(guò)修改config.h可以實(shí)現(xiàn)WindConfig的所有功能,并且,可以實(shí)現(xiàn)WindConfig不能實(shí)現(xiàn)的功能。
* WindSh:Tornado外殼
WindSh是一個(gè)駐留在主機(jī)內(nèi)的C語(yǔ)言解釋器,通過(guò)它可運(yùn)行下載到目標(biāo)機(jī)上的所有函數(shù),包括VxWorks和應(yīng)用函數(shù)。Tornado外殼
還能解釋常規(guī)的工具命令語(yǔ)言TCL。
WindSh不僅可以解釋幾乎所有的C語(yǔ)言表達(dá)式,而且可以實(shí)現(xiàn)所有的調(diào)試功能。它主要有以下調(diào)試功能:下載軟件模塊;刪除軟件模塊;
產(chǎn)生任務(wù);刪除任務(wù);設(shè)置斷點(diǎn);刪除斷點(diǎn);運(yùn)行、單步、繼續(xù)執(zhí)行程序;查看內(nèi)存、寄存器、變量;修改內(nèi)
存、寄存器、變量;查看任務(wù)列表、內(nèi)存使用情況、CPU利用率;查看特定的對(duì)象(任務(wù)、信號(hào)量、消息隊(duì)列、內(nèi)存分區(qū)、類);
復(fù)位目標(biāo)機(jī)。
* 瀏覽器
Tornado瀏覽器可查看內(nèi)存分配情況、任務(wù)列表、CPU利用率、系統(tǒng)目標(biāo)(如任務(wù)、消息隊(duì)列、信號(hào)量等)。這些信息可周期性地進(jìn)行更新。
* CrossWind:源碼級(jí)調(diào)試器
源碼級(jí)調(diào)試器CrossWind提供了圖形和命令行方式來(lái)調(diào)試,可進(jìn)行指定任務(wù)或系統(tǒng)級(jí)斷點(diǎn)設(shè)置、單步執(zhí)行、異常處理。
有些功能如修改內(nèi)存、寄存器、變量的值通過(guò)菜單操作是無(wú)法實(shí)現(xiàn)的,需要在WindSh中執(zhí)行原語(yǔ)操作實(shí)現(xiàn)。
* 駐留主機(jī)的目標(biāo)服務(wù)器
目標(biāo)服務(wù)器管理主機(jī)與目標(biāo)機(jī)的通信,所有與目標(biāo)機(jī)的交互工具都通過(guò)目標(biāo)服務(wù)器,它也管理主機(jī)上的目標(biāo)機(jī)符號(hào)表,提供目標(biāo)模塊的加
載和卸載。
* Tornado注冊(cè)器
所有目標(biāo)服務(wù)器注冊(cè)其提供的服務(wù)在注冊(cè)器中。注冊(cè)器映射用戶定義的目標(biāo)名到目標(biāo)服務(wù)器網(wǎng)絡(luò)地址。
* VxWorks
Tornado集成了VxWorks操作系統(tǒng)。
* 目標(biāo)代理程序
目標(biāo)代理程序是一個(gè)駐留在目標(biāo)機(jī)中的聯(lián)系Tornado工具和目標(biāo)機(jī)系統(tǒng)的組件。一般來(lái)說(shuō),目標(biāo)代理程序往往是不可見(jiàn)的。
3、MPC750/MCPN750上bootrom的制作
MPC750/MCPN750上的 bootrom用于初始化MPC750/MCPN750的硬件,通過(guò)網(wǎng)口加載 VxWorks 的內(nèi)核映象。因?yàn)镸PC750/MCPN750的bootrom
已經(jīng)制作,如果沒(méi)有特殊需要,不需重新制作bootrom。
制作MPC750/MCPN750上 bootrom的步驟:
* 在Tornado集成環(huán)境下,使用菜單命令Project | Make MCP750/MCPN750 | Comman Targets | clean刪除以前生成的bootrom文件,使用
菜單命令Project | Make MCP750/MCPN750 | Comman Targets | bootrom.hex生成bootrom文件。生成的bootrom文件在相應(yīng)的BSP目錄中
(MCP750為c:\tornado\target\config\mcp750,MCPN750為c:\tornado\target\config\mcpn750)
* 使用elftobin < bootRom > mcp750.bin 生成mcp750.bin 文件
* 啟動(dòng)TFTP服務(wù)器tftpd32.exe,設(shè)置下載文件(mcp750.bin)的目錄
* 用PPCBug啟動(dòng)目標(biāo)系統(tǒng)
* 運(yùn)行并配置超級(jí)終端。配置:9600bps波特率、8位數(shù)據(jù)位、1位停止位、無(wú)校驗(yàn)位、無(wú)流量控制。
* 在超級(jí)終端中,使用niot命令修改客戶(目標(biāo)機(jī))IP地址和服務(wù)器(主機(jī))IP地址
* 使用niop命令設(shè)置加載的文件名(mcp750.bin)
* 使用pflash 4000:FFF00 ff000100命令寫(xiě)FLASH B。
4、啟動(dòng)軟盤(pán)制作
目標(biāo)機(jī)啟動(dòng)軟盤(pán)用于啟動(dòng)目標(biāo)機(jī),通過(guò)網(wǎng)口使用Ftp協(xié)議從主機(jī)下載VxWorks映象。在X86平臺(tái)上,一般使用啟動(dòng)軟盤(pán)來(lái)啟動(dòng)目標(biāo)機(jī)。
.1 .啟動(dòng)盤(pán)的制作
在實(shí)時(shí)應(yīng)用系統(tǒng)的開(kāi)發(fā)調(diào)測(cè)階段,往往采用以PC機(jī)作為目標(biāo)機(jī)來(lái)調(diào)測(cè)程序。主機(jī)PC和目標(biāo)機(jī)PC之間可采取串口或是網(wǎng)口進(jìn)行聯(lián)結(jié)。由于大多數(shù)目標(biāo)已配有網(wǎng)卡,網(wǎng)絡(luò)聯(lián)結(jié)成為最簡(jiǎn)單快速的連接方式。串口聯(lián)結(jié)雖通信速率不高,也有它自己的優(yōu)點(diǎn),系統(tǒng)級(jí)任務(wù)調(diào)試(如中斷服務(wù)程序ISR)需使通信方式工作在Polled 模式,網(wǎng)口聯(lián)結(jié)就不支持,因此可以裁剪掉系統(tǒng)中網(wǎng)絡(luò)部分,以使VxWorks系統(tǒng)更小,滿足目標(biāo)板的內(nèi)存約束。下面分別對(duì)這兩種通信方式下目標(biāo)機(jī)VxWorks系統(tǒng)啟動(dòng)盤(pán)的制作作一簡(jiǎn)要介紹(以PC機(jī)為目標(biāo)系統(tǒng))。
串口通信時(shí)目標(biāo)機(jī)VxWorks系統(tǒng)啟動(dòng)盤(pán)的制作步驟:
1.修改通用配置文件\\Tornado\target\config\pc486\config.h.
在config.h文件中加入以下宏定義:
#define INCLUDE_WDB
#define INCLUDE_WDB_TTY_TEST
#undef WDB_COMM_TYPE
#define WDB_COMM_TYPE WDB_COMM_SERIAL /*定義通信方式為串口聯(lián)結(jié)*/
#define WDB_TTY_CHANNEL 1 /*通道號(hào)*/
#define WDB_TTY_BAUD 9600 /*串口速率,可設(shè)置至38400*/
#define WDB_TTY_DEV_NAME "tyCo/1"
#define CONSOLE_TTY 0
#define DEFAULT_BOOT_LINE \
"fd=0,0(0,0)hostname:/fd0/vxWorks h=主機(jī)ip e=目標(biāo)機(jī)ip u=主機(jī)上的登錄用戶名"
2. 在Tornado集成環(huán)境中執(zhí)行菜單命令Project | Make PC486 | Common Targets | clean刪除以前生成的文件,執(zhí)行菜單命令Project | Make PC486 | Boot Rom Targets | bootrom_uncmp編譯鏈接生成bootrom_uncmp ;再選擇VxWorks Target,編譯生成vxworks。
3.拷貝\\Tornado\target\config\pc486\bootrom_uncmp至\\Tornado\host\bin下;
4.重命名文件bootrom_uncmp為bootrom;
15.準(zhǔn)備一張已格式化的空盤(pán)插入軟驅(qū);
6.在目錄\\Tornado\host\bin下執(zhí)行命令 mkboot a: bootrom;
7.拷貝\\Tornado\target\config\pc486\VxWorks至軟盤(pán);
8.將系統(tǒng)制作盤(pán)插入目標(biāo)機(jī)軟驅(qū),加電啟動(dòng)目標(biāo)機(jī)即載入VxWorkst系統(tǒng)。
網(wǎng)口通信時(shí)目標(biāo)機(jī)VxWorks系統(tǒng)啟動(dòng)盤(pán)的制作步驟:
1.配置目標(biāo)機(jī)網(wǎng)卡,設(shè)置其中斷號(hào)和輸入輸出范圍(I/O地址);
2.修改通用配置文件\\Tornado\target\config\pc486\config.h.
針對(duì)不同的網(wǎng)卡,其名稱不同,如NE2000及其兼容網(wǎng)卡為ENE,3COM以太網(wǎng)卡為ELT,Intel網(wǎng)卡為EEX。
在config.h文件中修改相應(yīng)網(wǎng)卡類型(如網(wǎng)卡為3COM網(wǎng)卡)的定義部分:
#define IO_ADRS_ELT 網(wǎng)卡I/O地址
#define INT_LVL_ELT 網(wǎng)卡中斷號(hào)
并且修改#define DEFAULT_BOOT_LINE的定義:
#define DEFAULT_BOOT_LINE \
"elt(0,0)主機(jī)標(biāo)識(shí)名:C:\\tornado\\target\\config\\pc486\\vxWorks h=主機(jī)IP e=目標(biāo)機(jī)IP u=登錄用戶名 pw=口令 tn=目標(biāo)機(jī)名"
DEFAULT_BOOT_LINE宏定義,使缺省配置符合自己的調(diào)試環(huán)境
#define DEFAULT_BOOT_LINE \
"ene(0,0)host:c:/tornado/target/config/pc486/vxWorks h=129.9.75.39 e=129.9.49.7 u=x86 pw=x86 tn=x86"
ene(0,0) /* 啟動(dòng)設(shè)備為網(wǎng)卡 */
host /* 主機(jī)標(biāo)識(shí),可以任意填寫(xiě),不影響啟動(dòng)過(guò)程 */
c:\tornado\target\config\pc486\vxWorks /* 需要從主機(jī)加載的映象文件 */
h=129.9.75.39 /* 主機(jī)的IP地址 */
e=129.9.49.7 /* 目標(biāo)機(jī)的IP地址 */
u=x86 /* 用戶名,主機(jī)的Ftp服務(wù)器必須有相應(yīng)的同名用戶 */
pw=x86 /* 密碼,必須與主機(jī)的Ftp服務(wù)器相應(yīng)的同名用戶的密碼相同*/
tn=x86 /*目標(biāo)名,可以任意設(shè)置,不影響啟動(dòng)過(guò)程*/
3.主機(jī)信息的確定(可無(wú))
主機(jī)操作系統(tǒng)Win95安裝目錄下有一文件hosts.sam,向其中加入:
主機(jī)IP 主機(jī)名
目標(biāo)機(jī)IP 目標(biāo)機(jī)名
4.在Tornado集成環(huán)境中點(diǎn)取Project菜單,選取Make PC486,選擇Common Target,先進(jìn)行clean操作;再選擇Boot Rom Target,進(jìn)行bootrom_uncmp操作;再選擇VxWorks Target,進(jìn)行vxworks操作。
5.拷貝\\Tornado\target\config\pc486\bootrom_uncmp至\\Tornado\host\bin下;
6.重命名文件bootrom_uncmp為bootrom;
7.準(zhǔn)備一張已格式化的空盤(pán)插入軟驅(qū);
8.在目錄\\Tornado\host\bin下執(zhí)行命令 mkboot a: bootrom ;
9.啟動(dòng)Tornado組件FTP Server,在WFTPD窗口中選擇菜單Security中的User/right...,在其彈出窗口中選擇New User...,根據(jù)提示信息輸入登錄用戶名和口令,并且要指定下載文件vxWorks所在根目錄;還必選取主菜單Logging中Log options,使Enable Logging、Gets 、Logins 、Commands 、Warnings能。
10.將系統(tǒng)制作盤(pán)插入目標(biāo)機(jī)軟驅(qū),加電啟動(dòng)目標(biāo)機(jī)即通過(guò)FTP方式從主機(jī)下載VxWorkst系統(tǒng)。
2)主機(jī)Tornado環(huán)境配置
串口聯(lián)結(jié)時(shí)主機(jī)Tornado開(kāi)發(fā)環(huán)境的目標(biāo)服務(wù)器配置操作如下:
1.在Tornado集成環(huán)境中點(diǎn)取Tools菜單,選取Target Server,選擇config...;
2.在Configure Target Servers窗口中先給目標(biāo)服務(wù)器命名;
3.在配置目標(biāo)服務(wù)器窗口中的"Change Property"窗口中選擇Back End,在"Available Back"窗口中選擇wdbserial,再在"Serial Port"窗口中選擇主機(jī)與目標(biāo)機(jī)連接所占用的串口號(hào)(COM1,COM2),再在"Speed(bps)"窗口中選擇主機(jī)與目標(biāo)機(jī)間串口速率。
4. 在配置目標(biāo)服務(wù)器窗口中的"Change Property"窗口中選擇Core File and Symbols,
選擇File為BSP目標(biāo)文件所在目錄(本例為PC486目錄)的VxWorks.st,并選取為All Symbols.
5.在配置目標(biāo)服務(wù)器窗口中的"Change Property"窗口中的其它各項(xiàng)可根據(jù)需要選擇。
網(wǎng)口聯(lián)結(jié)時(shí)主機(jī)Tornado開(kāi)發(fā)環(huán)境的目標(biāo)服務(wù)器配置操作如下:
1.在Tornado集成環(huán)境中點(diǎn)取Tools菜單,選取Target Server,選擇config...;
2.在Configure Target Servers窗口中先給目標(biāo)服務(wù)器命名;
3.在配置目標(biāo)服務(wù)器窗口中的"Change Property"窗口中選擇Back End,在"Available Back"窗口中選擇wdbrpc,在"Target IP/Address"窗口中輸入目標(biāo)機(jī)IP。
4. 在配置目標(biāo)服務(wù)器窗口中的"Change Property"窗口中選擇Core File and Symbols,
選擇File為BSP目標(biāo)文件所在目錄(本例為PC486目錄)的VxWorks,并選取為All Symbols.
5.在配置目標(biāo)服務(wù)器窗口中的"Change Property"窗口中的其它各項(xiàng)可根據(jù)需要選擇。
以上的串口和網(wǎng)口聯(lián)結(jié)配置完成后,可按以下步驟和目標(biāo)機(jī)建立連接:
1.點(diǎn)擊Launch按鈕,連接主機(jī)和目標(biāo)機(jī),全部出現(xiàn)successed后即可進(jìn)入應(yīng)用程序調(diào)試。
2.點(diǎn)擊圖形按鈕中下拉框,選擇和主機(jī)相連的目標(biāo)機(jī)。
3.選擇Debugger菜單項(xiàng)中Download...,下載應(yīng)用程序到目標(biāo)板。
4. 選擇Debugger菜單項(xiàng)中Run...,調(diào)測(cè)應(yīng)用程序中某一任務(wù)或功能函數(shù)。
VxWorks系統(tǒng)目標(biāo)機(jī)啟動(dòng)盤(pán)的制作步驟:
焈 配置目標(biāo)機(jī)網(wǎng)卡,設(shè)置其中斷號(hào)和輸入輸出范圍(I/O地址);
焈 修改配置文件C:\Tornado\target\config\pc486\config.h。
不同的網(wǎng)卡,其名稱不同,如NE2000及其兼容網(wǎng)卡為ENE,3COM以太網(wǎng)卡為ELT,Intel網(wǎng)卡為EEX。根據(jù)目標(biāo)機(jī)的網(wǎng)卡類型、中斷號(hào)、I/O地址修改config.h文件中的相應(yīng)宏定義。以下以NE2000網(wǎng)卡(中斷號(hào)為10,I/O地址為0X300)為例說(shuō)明配置過(guò)程。
#define IO_ADRS_ENE 0x300 /*網(wǎng)卡I/O地址*/
#define INT_LVL_ENE 0x0a /*網(wǎng)卡中斷號(hào)*/
* 因?yàn)橛密洷P(pán)啟動(dòng)目標(biāo)機(jī)無(wú)法保存修改的信息,修改config.h文件中的DEFAULT_BOOT_LINE宏定義,使缺省配置符合自己的調(diào)試環(huán)境
#define DEFAULT_BOOT_LINE \
"ene(0,0)host:c:/tornado/target/config/pc486/vxWorks h=129.9.75.39 e=129.9.49.7 u=x86 pw=x86 tn=x86"
ene(0,0) /* 啟動(dòng)設(shè)備為網(wǎng)卡 */
host /* 主機(jī)標(biāo)識(shí),可以任意填寫(xiě),不影響啟動(dòng)過(guò)程 */
c:\tornado\target\config\pc486\vxWorks /* 需要從主機(jī)加載的映象文件 */
h=129.9.75.39 /* 主機(jī)的IP地址 */
e=129.9.49.7 /* 目標(biāo)機(jī)的IP地址 */
u=x86 /* 用戶名,主機(jī)的Ftp服務(wù)器必須有相應(yīng)的同名用戶 */
pw=x86 /* 密碼,必須與主機(jī)的Ftp服務(wù)器相應(yīng)的同名用戶的密碼相同*/
tn=x86 /*目標(biāo)名,可以任意設(shè)置,不影響啟動(dòng)過(guò)程*/
焈 在Tornado集成環(huán)境中執(zhí)行菜單命令Project | Make PC486 | Common Targets | clean刪除以前生成的文件,執(zhí)行菜單命令Project | Make PC486 | Boot Rom Targets | bootrom_uncmp編譯鏈接生成bootrom_uncmp。
* 拷貝c:\Tornado\target\config\pc486\bootrom_uncmp至c:\Tornado\host\bin下;
* 重命名文件bootrom_uncmp為bootrom;
* 準(zhǔn)備一張已格式化的空盤(pán)插入軟驅(qū);
* 在目錄c:\Tornado\host\bin下執(zhí)行命令 mkboot a: bootrom ;
* 啟動(dòng)盤(pán)制作完成
5、使用步驟
使用Tornado集成環(huán)境一般需要經(jīng)過(guò)以下步驟:
焈 運(yùn)行TCP/IP端口管理器Portmapper(portmap.exe)
焈 運(yùn)行注冊(cè)器Tornado Registry(wtxregd.exe)。如果使用的是試用版,注意是否注冊(cè)成功,是否修改了日期
焈 運(yùn)行并配置Ftp Server(wtfpd32.exe)。點(diǎn)擊菜單命令Security | Users | rights彈出配置窗口,點(diǎn)擊New User,在New User彈出窗
口加入需要加入的用戶名(注意:要與目標(biāo)機(jī)bootrom或啟動(dòng)軟盤(pán)設(shè)置一致),在改變密碼彈出窗口設(shè)置該用戶的密碼(注意:要與目標(biāo)
機(jī)bootrom或啟動(dòng)軟盤(pán)設(shè)置一致),在Home Directory中設(shè)置相應(yīng)的目錄,MCP750為c:\tornado\target\config\mcp750,MCPN750為
c:\tornado\target \config\mcpn750,X86為c:\tornado\target\config\pc486 ,配置結(jié)束。
焈 目標(biāo)板上電或復(fù)位
焈 在控制臺(tái)(MCP750/MCPN750為超級(jí)終端,X86為目標(biāo)機(jī)顯示器)上可以看到啟動(dòng)信息。如果需要修改,在等待用戶配置時(shí),按c鍵,
進(jìn)行相應(yīng)修改。(注意:配置信息要與主機(jī)配置、Ftp服務(wù)器配置一致),修改結(jié)束后,按@鍵重新啟動(dòng)目標(biāo)機(jī)。
焈 運(yùn)行Tornado(tornado.exe)
焈 執(zhí)行菜單命令Tools | Target Server | Configure,彈出目標(biāo)服務(wù)器設(shè)置對(duì)話框,點(diǎn)擊New產(chǎn)生一個(gè)新的配置。設(shè)置Description域
(可以任意設(shè)置);設(shè)置Target Server域(可以任意設(shè)置);在Change Property域選取Back End項(xiàng)(該項(xiàng)設(shè)置主機(jī)與目標(biāo)機(jī)如何連接,
缺省為網(wǎng)口連接,如果使用串口連接,需要修改configall.h文件,重新編譯鏈接VxWorks映象),如果使用網(wǎng)口調(diào)試,選擇wdbrpc,
在目標(biāo)IP名或地址域中給出目標(biāo)機(jī)的IP名或地址(建議給出IP名,因?yàn)檫@樣會(huì)快得多),如果給出的是IP名,需要在HOSTS文件中給
出IP名與IP地址的對(duì)應(yīng)關(guān)系,如果用串口調(diào)試,選擇wdbserial,選擇相應(yīng)的串口和波特率(注意:此處的串口是指主機(jī)的串口不是
目標(biāo)機(jī)的串口);在Change Property域選取Core File and Symbols項(xiàng),選中File項(xiàng)輸入相應(yīng)的文件
(MCP750c:\tornado\target\config\mcp750\vxWorks,MCPN750為c:\tornado\target \config\mcpn750\vxWorks,在X86平臺(tái)上
為c:\tornado\target\config\pc486\vxWorks),點(diǎn)擊Launch,運(yùn)行目標(biāo)服務(wù)器。
焈 執(zhí)行菜單命令File | New 創(chuàng)建一個(gè)新的文件,并打開(kāi)編輯器Editor(該編輯器功能不是很強(qiáng)大,可以使用其它編輯器
如Source Insight)。
焈 單獨(dú)編譯生成的源文件,生成目標(biāo)文件(.o),編譯連接過(guò)程的詳細(xì)介紹請(qǐng)見(jiàn)后面。
焈 選取相應(yīng)的目標(biāo)服務(wù)器。
焈 執(zhí)行菜單命令Tools | Debugger運(yùn)行調(diào)試器。
焈 執(zhí)行菜單命令Debug | Download下載要調(diào)試的目標(biāo)文件(.o)
焈 在Editor窗口設(shè)置斷點(diǎn)。
焈 執(zhí)行菜單命令Debug | Run彈出對(duì)話框,要求輸入調(diào)試入口函數(shù),輸入要調(diào)試的函數(shù)。
焈 進(jìn)行源碼級(jí)調(diào)試
焈 執(zhí)行菜單命令Tools | Shell運(yùn)行Shell??梢栽赟hell窗口查看/修改全局變量、內(nèi)存,查看任務(wù)列表、各模塊使用內(nèi)存的情況、
對(duì)象(如任務(wù)、隊(duì)列、信號(hào)量、定時(shí)器、內(nèi)存分區(qū))等信息。
焈 執(zhí)行菜單命令Tools | Browser運(yùn)行Browser。在Browser中可以查看任務(wù)列表、各模塊使用內(nèi)存的情況、對(duì)象(如任務(wù)、隊(duì)列、
信號(hào)量、定時(shí)器、內(nèi)存分區(qū))等信息。
6、編譯鏈接
VxWorks的開(kāi)發(fā)調(diào)試環(huán)境可以把VxWorks內(nèi)核和應(yīng)用分開(kāi),分別加載。 VxWorks內(nèi)核在目標(biāo)機(jī)啟動(dòng)過(guò)程中通過(guò)ftp協(xié)議加載到目標(biāo)機(jī)中
運(yùn)行,應(yīng)用模塊在調(diào)試中動(dòng)態(tài)下載,目標(biāo)代理把下載的應(yīng)用模塊動(dòng)態(tài)鏈接到系統(tǒng)中,應(yīng)用模塊的調(diào)試是通過(guò)在用戶執(zhí)行運(yùn)行命令時(shí)提
供入口函數(shù)實(shí)現(xiàn)的。這樣做的好處是需要調(diào)試哪個(gè)模塊就下載那個(gè)模塊調(diào)試,不需下載其它模塊,前期調(diào)試一般使用這種編譯方式。
VxWorks的開(kāi)發(fā)調(diào)試環(huán)境也提供把應(yīng)用模塊與系統(tǒng)內(nèi)核鏈接在一起,通過(guò)ftp協(xié)議加載執(zhí)行。這需要經(jīng)過(guò)兩個(gè)步驟:把應(yīng)用模塊的入口
代碼加到usrConfig.c文件中的usrRoot函數(shù)的尾部;把應(yīng)用模塊編譯鏈接到VxWorks內(nèi)核中,這種編譯鏈接方式一般用于后期調(diào)試。
下面分類對(duì)編譯鏈接進(jìn)行介紹
6.1 單個(gè)應(yīng)用模塊的編譯
單個(gè)應(yīng)用模塊的編譯可以通過(guò)使用菜單命令Project | Make Current Source File進(jìn)行編譯,要編譯的源文件必須已經(jīng)用Editor打開(kāi)
并且為當(dāng)前窗口。如果要編譯的源文件所在目錄沒(méi)有makefile文件,系統(tǒng)會(huì)提示創(chuàng)建一個(gè)新的makefile文件,確定。在彈出的創(chuàng)建缺
省makefile窗口的CPU域選擇相應(yīng)的項(xiàng)(MCP750/MCPN750選擇PPC604,X86選擇I80486),在ADDED_FLAGS域輸入-g,確定。系統(tǒng)對(duì)源文
件進(jìn)行編譯,生成目標(biāo)文件(.o)。生成的目標(biāo)文件在Debugger環(huán)境中動(dòng)態(tài)加載,與內(nèi)核動(dòng)態(tài)鏈接到一起。
6.2 系統(tǒng)內(nèi)核vxWorks的編譯鏈接
系統(tǒng)內(nèi)核vxWorks是調(diào)試中使用最多的內(nèi)核映象。它被通過(guò)Ftp協(xié)議從主機(jī)加載到目標(biāo)機(jī)中。它的作用通常是進(jìn)行軟硬件初始化,等待
加載應(yīng)用模塊,進(jìn)行程序調(diào)試。
在Project菜單下,選擇相應(yīng)硬件平臺(tái)的生成vxWorks的命令,進(jìn)行編譯鏈接。在編譯鏈接之前先使用clean命令刪除以前生成的文件。
6.3 應(yīng)用模塊與系統(tǒng)內(nèi)核一起編譯鏈接
VxWorks的開(kāi)發(fā)調(diào)試環(huán)境也提供把應(yīng)用模塊與系統(tǒng)內(nèi)核鏈接在一起,通過(guò)Ftp協(xié)議加載,vxWorks內(nèi)核自動(dòng)執(zhí)行應(yīng)用模塊。這需要經(jīng)過(guò)兩
個(gè)步驟:把應(yīng)用模塊的入口代碼加到usrConfig.c文件中的usrRoot函數(shù)的尾部;在makefile中把待生成的應(yīng)用模塊的目標(biāo)文件名加到宏
定義MACH_EXTRA中,再把相應(yīng)的編譯規(guī)則加到makefile中。編譯鏈接生成vxWorks映象。
6.4 Project菜單下其它編譯鏈接命令介紹
* vxWorks_rom :可以寫(xiě)到ROM的、沒(méi)有帶符號(hào)表和Shell的、沒(méi)有壓縮的vxWorks。
* vxWorks.st :帶有符號(hào)表的vxWorks。
* vxWorks.st_rom:可以寫(xiě)到ROM的、帶有符號(hào)表和Shell的、壓縮的vxWorks。
* vxWorks.res_rom :可以寫(xiě)到ROM的、帶有符號(hào)表和Shell的、只有數(shù)據(jù)段拷貝到內(nèi)存的、沒(méi)有壓縮的vxWorks。
* vxWorks.res_rom_nosym:可以寫(xiě)到ROM的、只有數(shù)據(jù)段拷貝到內(nèi)存的、沒(méi)有壓縮的vxWorks。
* bootrom:壓縮的 bootrom
* bootrom_uncmp:沒(méi)有壓縮的bootrom
7、調(diào)試時(shí)的常用方法
下面是一些調(diào)試手段在調(diào)試器中的相應(yīng)命令(操作)
調(diào)試手段
相應(yīng)操作
設(shè)置斷點(diǎn)
菜單命令Debug|Toggle BreakPoint
刪除斷點(diǎn)
菜單命令Debug|Toggle BreakPoint
運(yùn)行
菜單命令Debug|Run
單步執(zhí)行(進(jìn)入函數(shù))
菜單命令Debug|Step
單步執(zhí)行(不進(jìn)入函數(shù))
菜單命令Debug|Next
繼續(xù)執(zhí)行(停下后的程序)
菜單命令Debug|Continue
執(zhí)行完當(dāng)前的函數(shù),停在調(diào)用它的函數(shù)的下一條語(yǔ)句
菜單命令Debug|Finish
查看變量的值
菜單命令Debug|Inspect
查看當(dāng)前函數(shù)的所有局部變量
菜單命令Debug|Locals
查看內(nèi)存
菜單命令Debug|Memory
查看寄存器
菜單命令Debug|Registers
修改內(nèi)存
Shell命令m
修改寄存器
Shell命令mRegs
修改變量
在Shell中直接給該變量賦值(局部變量無(wú)法用此方法修改)
卸載一個(gè)加載的模塊
Shell命令unld
刪除任務(wù)
Shell命令td
復(fù)位目標(biāo)機(jī)
Shell命令reboot
用該命令的好處:目標(biāo)服務(wù)器自動(dòng)與目標(biāo)代理重新鏈接,Shell自動(dòng)重啟
查看任務(wù)
在Browser對(duì)象信息窗口輸入待查看的任務(wù)名或ID
查看信號(hào)量
在Browser對(duì)象信息窗口輸入待查看的信號(hào)量名或ID
查看消息隊(duì)列
在Browser對(duì)象信息窗口輸入待查看的消息隊(duì)列命或ID
內(nèi)存分區(qū)
在Browser對(duì)象信息窗口輸入待查看的內(nèi)存分區(qū)ID
看門(mén)狗
在Browser對(duì)象信息窗口輸入待查看的看門(mén)狗ID
類(class)
在Browser對(duì)象信息窗口輸入待查看的類的ID
查看內(nèi)存使用(模塊使用內(nèi)存的情況)
Browser的內(nèi)存使用窗口
查看任務(wù)列表(系統(tǒng)里的所有任務(wù))
Browser的任務(wù)列表窗口
查看CPU占用率
Browser的Spy窗口
查看堆棧使用情況
Browser的堆棧檢查窗口
注:
* Shell可以通過(guò)菜單命令Debug | Shell啟動(dòng)
* Shell的原語(yǔ)可以通過(guò)在Shell中輸入help列出
* Browser可以通過(guò)菜單命令Debug | Browser啟動(dòng)
* Debugger命令窗口的命令可以通過(guò)在命令窗口輸入help列出
8、任務(wù)調(diào)試模式下的多任務(wù)調(diào)試
在任務(wù)調(diào)試模式下,在一個(gè)集成環(huán)境中,在一個(gè)任務(wù)中調(diào)試,在另一個(gè)任務(wù)中設(shè)置斷點(diǎn),設(shè)置的斷點(diǎn)不起作用。這是因?yàn)橐粋€(gè)調(diào)試器只
能處理一個(gè)TCB(任務(wù)控制塊),每個(gè)任務(wù)都有一個(gè)TCB,因此一個(gè)調(diào)試器只能調(diào)試一個(gè)任務(wù),要調(diào)試幾個(gè)任務(wù)就要啟動(dòng)幾個(gè)調(diào)試器。一
個(gè)集成環(huán)境只能啟動(dòng)一個(gè)調(diào)試器,所以要調(diào)試幾個(gè)任務(wù)就要啟動(dòng)幾個(gè)集成環(huán)境。另外,需要在被調(diào)試的任務(wù)的待調(diào)試的第一條語(yǔ)句前加
入taskSuspend(0)語(yǔ)句,掛起該任務(wù),否則任務(wù)就可能會(huì)在調(diào)試前被執(zhí)行。
下面是多任務(wù)調(diào)試的測(cè)試用例的源代碼
/* VxWorks includes */
#include "vxWorks.h"
#include "taskLib.h"
#include "stdio.h"
#include "msgQLib.h"
int g_lTaskATid;
int g_lTaskBTid;
MSG_Q_ID g_MsgQ1id;
MSG_Q_ID g_MsgQ2id;
void MultiTaskTestTaskA(void)
{
char cMsgToTaskB[100];
char cMsgFromTaskB[100];
sprintf(cMsgToTaskB,"To TaskB \n");
printf(" Hello from MultiTaskTestTaskA \n");
/*start point of debugging for MultiTaskTestTaskA*/
taskSuspend(0);
for(;;)
{
printf(" Hello from MultiTaskTestTaskA \n");
/*Send message to MultiTaskTestTaskB*/
msgQSend(g_MsgQ1id,cMsgToTaskB,sizeof(cMsgToTaskB),WAIT_FOREVER,MSG_PRI_NORMAL);
/*Receive message from MultiTaskTestTaskB*/
msgQReceive(g_MsgQ2id,cMsgFromTaskB,100,WAIT_FOREVER);
printf("%s",cMsgFromTaskB);
}
}
void MultiTaskTestTaskB(void)
{
char cMsgToTaskA[100];
char cMsgFromTaskA[100];
sprintf(cMsgToTaskA,"To TaskA \n");
printf(" Hello from MultiTaskTestTaskB \n");
/*start point of debugging for MultiTaskTestTaskA*/
taskSuspend(0);
for(;;)
{
printf(" Hello from MultiTaskTestTaskB \n");
/*Send message to MultiTaskTestTaskA*/
msgQSend(g_MsgQ2id,cMsgToTaskA,sizeof(cMsgToTaskA),WAIT_FOREVER, MSG_PRI_NORMAL);
/*Receive message from MultiTaskTestTaskA*/
msgQReceive(g_MsgQ1id,cMsgFromTaskA,100,WAIT_FOREVER);
printf("%s",cMsgFromTaskA);
}
}
/*This function spawns MultiTaskTestTaskA and MultiTaskTestTaskB , creates g_MsgQ1id and g_MsgQ2id , is entry for
debugging.*/
void MultiTaskTestInit(void)
{
printf(" Hello from MultiTaskTestInit \n");
g_MsgQ1id=msgQCreate(20,100,MSG_Q_FIFO);
if(g_MsgQ1id==NULL)
{
printf(" ERROR: create g_MsgQ1 error \n");
}
g_MsgQ2id=msgQCreate(20,100,MSG_Q_FIFO);
if(g_MsgQ1id==NULL)
{
printf(" ERROR: create g_MsgQ2 error \n");
}
printf(" Spawning a new task called MultiTaskTestTaskA \n\n");
g_lTaskATid = taskSpawn("MultiTaskTestTaskA", 100,0,10000, (FUNCPTR)MultiTaskTestTaskA, 0,0,0,0,0,0,0,0,0,0);
if(g_lTaskATid == ERROR)
{
printf(" ERROR: task did not spawn \n");
exit(1);
}
printf(" Spawning a new task called MultiTaskTestTaskB
\n");
g_lTaskBTid = taskSpawn("MultiTaskTestTaskB", 100,0,10000, (FUNCPTR)MultiTaskTestTaskB, 0,0,0,0,0,0,0,0,0,0);
if(g_lTaskBTid == ERROR)
{
printf(" ERROR: task did not spawn \n");
exit(1);
}
exit(0);
}
多任務(wù)調(diào)試步驟:
* 用-g選項(xiàng)編譯源代碼產(chǎn)生目標(biāo)文件
* 下載產(chǎn)生的目標(biāo)文件
* 在MultiTaskTestInit函數(shù)的開(kāi)始設(shè)置斷點(diǎn)
* 把MultiTaskTestInit設(shè)置為調(diào)試任務(wù)的人口函數(shù)
* 單步執(zhí)行產(chǎn)生MultiTaskTestTaskA任務(wù)的語(yǔ)句后可以在串口(超級(jí)終端)上看到字符串Hello from MultiTaskTestTaskA,用Browser
查看任務(wù),可以看到任務(wù)MultiTaskTestTaskA出于掛起態(tài)(suspended),表明程序執(zhí)行了taskSuspend(0)語(yǔ)句。
* 運(yùn)行另一個(gè)Tornado集成環(huán)境
* Attach任務(wù)MultiTaskTestTaskA,
* 在語(yǔ)句msgQReceive(g_MsgQ2id,cMsgFromTaskB,100,WAIT_FOREVER)的下一條語(yǔ)句處設(shè)置斷點(diǎn)
* 運(yùn)行任務(wù)MultiTaskTestTaskA??梢钥吹?jīng)]有執(zhí)行到斷點(diǎn)處,用Browser查看任務(wù)狀態(tài),MultiTaskTestTaskA出于阻塞態(tài)(pended),
因?yàn)樗诘却ⅰ?
* 單步執(zhí)行MultiTaskTestInit到產(chǎn)生MultiTaskTestTaskB任務(wù)的下一條語(yǔ)句,可以看到MultiTaskTestTaskB任務(wù)處于掛起態(tài)
* 再運(yùn)行另一個(gè)Tornado集成環(huán)境
* Attach任務(wù)MultiTaskTestTaskB,
* 在語(yǔ)句msgQReceive(g_MsgQ1id,cMsgFromTaskA,100,WAIT_FOREVER)下一條語(yǔ)句處設(shè)置斷點(diǎn)
* 運(yùn)行任務(wù)MultiTaskTestTaskB??梢钥吹綀?zhí)行到斷點(diǎn)處停下。這是因?yàn)镸ultiTaskTestTaskA任務(wù)已經(jīng)發(fā)送一條消息到MultiTaskTestTaskB
的接收隊(duì)列中。
* 此時(shí),可以看到MultiTaskTestTaskA任務(wù)也運(yùn)行到斷點(diǎn)處,因?yàn)闉镸ultiTaskTestTaskB任務(wù)已經(jīng)發(fā)送一條消息到MultiTaskTestTaskA的
接收隊(duì)列中。
9、系統(tǒng)調(diào)試模式下程序的調(diào)試
Tornado集成環(huán)境提供兩種調(diào)試模式:任務(wù)調(diào)試模式和系統(tǒng)調(diào)試模式。在任務(wù)調(diào)試模式下,在一個(gè)集成環(huán)境下一個(gè)時(shí)間內(nèi)只能調(diào)試一個(gè)任務(wù)。
調(diào)試只影響當(dāng)前被調(diào)試的任務(wù),其它任務(wù)正常運(yùn)行。在系統(tǒng)調(diào)試模式下,可以同時(shí)調(diào)試多個(gè)任務(wù)、中斷服務(wù)程序(ISR),調(diào)試影響整個(gè)
系統(tǒng)。
Tornado1.0集成環(huán)境下,在系統(tǒng)模式下進(jìn)行程序調(diào)試,主機(jī)與目標(biāo)機(jī)之間必須使用串口通信。Tornado2.0集成環(huán)境提供了通過(guò)網(wǎng)口進(jìn)行系
統(tǒng)模式調(diào)試的功能。
系統(tǒng)缺省使用網(wǎng)口通信,如果需要使用串口通信,需要修改文件C: \ Tornado \ target \ config
} all \ configAll.h的一些宏定義,修改為:
#define WDB_COMM_TYPE WDB_COMM_SERIAL /*使用串口通信*/
#define WDB_TTY_CHANNEL 0 /*使用第一個(gè)串口*/
#define WDB_TTY_BAUD 38400 /*波特率:38400bps*/
重新編譯鏈接vxWorks。
在啟動(dòng)目標(biāo)服務(wù)器時(shí),要選擇串口通信,并進(jìn)行相應(yīng)配置。
9.1 系統(tǒng)調(diào)試模式下多任務(wù)的調(diào)試:
調(diào)試使用的源代碼與任務(wù)調(diào)試模式中使用的代碼相同。但是,需要去掉為了能夠在任務(wù)調(diào)試模式下進(jìn)行多任務(wù)調(diào)試的MultiTaskTestTaskA
和MultiTaskTestTaskB中的語(yǔ)句taskSuspend(0);。
多任務(wù)調(diào)試步驟:
* 用-g選項(xiàng)編譯源代碼產(chǎn)生目標(biāo)文件。
* 下載產(chǎn)生的目標(biāo)文件。
* 在MultiTaskTestInit函數(shù)的開(kāi)始設(shè)置斷點(diǎn)。
* 在Debugger命令窗口輸入命令attach system進(jìn)入系統(tǒng)調(diào)試模式。
* 在Shell窗口輸入命令sp MultiTaskTestInit產(chǎn)生一個(gè)以MultiTaskTestInit為入口函數(shù)的任務(wù),因?yàn)檎麄€(gè)系統(tǒng)都停下了,新產(chǎn)生的任務(wù)
還沒(méi)有執(zhí)行,這可以通過(guò)在Debugger命令窗口輸入命令info threads顯示當(dāng)前系統(tǒng)中的任務(wù)列表看出來(lái)。
* 執(zhí)行菜單命令Debug | Continue繼續(xù)運(yùn)行程序。
* 系統(tǒng)在設(shè)置的斷點(diǎn)處停下。
* 在函數(shù)MultiTaskTestTaskA中的語(yǔ)句msgQReceive(g_MsgQ2id,cMsgFromTaskB, 100,WAIT_FOREVER)的下一條語(yǔ)句處設(shè)置斷點(diǎn)。
* 在函數(shù)MultiTaskTestTaskB中的語(yǔ)句msgQReceive(g_MsgQ1id,cMsgFromTaskA, 100,WAIT_FOREVER)的下一條語(yǔ)句處設(shè)置斷點(diǎn)。
* 執(zhí)行菜單命令Debug | Continue繼續(xù)運(yùn)行程序。
* 程序在任務(wù)MultiTaskTestTaskB中的斷點(diǎn)處停下(為什么不是在任務(wù)MultiTaskTestTaskA中停下?請(qǐng)考慮)。
* 執(zhí)行菜單命令Debug | Continue繼續(xù)運(yùn)行程序。
* 程序在任務(wù)MultiTaskTestTaskA中的斷點(diǎn)處停下。
* 執(zhí)行菜單命令Debug | Continue繼續(xù)運(yùn)行程序。
* 程序又一次在任務(wù)MultiTaskTestTaskA中的斷點(diǎn)處停下(為什么停兩次?請(qǐng)考慮)。
* 執(zhí)行菜單命令Debug | Continue繼續(xù)運(yùn)行程序。
* 程序在任務(wù)MultiTaskTestTaskB中的斷點(diǎn)處停下。
9.2 中斷服務(wù)程序的調(diào)試
中斷服務(wù)程序只能在系統(tǒng)調(diào)試模式下調(diào)試,不能在任務(wù)調(diào)試模式下調(diào)試。因?yàn)橹袛喾?wù)程序是作為系統(tǒng)的一部分運(yùn)行,不是以任務(wù)方式運(yùn)
行,因此不需要為它產(chǎn)生任務(wù)。
中斷服務(wù)程序調(diào)試步驟:
* 用-g選項(xiàng)編譯源代碼產(chǎn)生目標(biāo)文件。
* 下載產(chǎn)生的目標(biāo)文件。
* 在MultiTaskTestInit函數(shù)的開(kāi)始設(shè)置斷點(diǎn)。
* 在Debugger命令窗口輸入命令attach system進(jìn)入系統(tǒng)調(diào)試模式。
* 執(zhí)行菜單命令Debug | Continue繼續(xù)運(yùn)行程序。
* 如果產(chǎn)生相應(yīng)的中斷,程序就會(huì)在中斷服務(wù)程序的斷點(diǎn)處停下。進(jìn)行需要的調(diào)試。
------------------------全文完------------------------------
應(yīng)用示例分析(demo例子程序windDemo.c)
通過(guò)對(duì)一具體實(shí)例的分析,對(duì)任務(wù)的創(chuàng)建、任務(wù)間通信、內(nèi)存分配、消息管理等VxWorks系統(tǒng)應(yīng)用更進(jìn)一步的了解。
/* windDemo - repeatedly test various kernel function */
/*
modification history
--------------------
02c,23aug93,jcf fixed synchronization.
02b,01aug93,dvs fixed loop count printing.
02a,18mar93,dvs took out timer/benchmark information.
ansified code.
general cleanup of code to use as MicroWorks demo.
01a,12nov90,shl written.
*/
/*
DESCRIPTION
This program repeatedly exercises different kernel facilities of
the Wind kernel.
The functions involved include the use of semaphores as sychronization
and mutual exclusion primitives, the use of taskSuspend()/taskResume() for task control, the use of message queues for
communication and the
use of watchdogs for task timeouts.
To exercise these kernel facilities two tasks are used, a high priority task and a low priority task. The high priority
task executes functions with which the resources are not available. As the high priority task blocks, the low priority
task takes over and makes available the resources that the high priority task is waiting for. This may sound simple at
first but the underlying execution of this test program involves context switching, rescheduling of tasks, and shuffling
of the ready queue, pend queue, and the timer queue.
These functions are chosen because they are the most commonly used
functions in sychronization, mutual exclusion, task control, inter-task communication and timer facilities. These are
the basic building blocks of the operating system itself and also used in applications. Repeatedly execution of this
"death loop" is a good indication of how the system will perform in real-life as these functions are utiltized heavily
in every application.
The following is the thread of execution of this test program.
Higher Priority Lower Priority
Task1 Task2
=============== ==============
|
V
/----->semGive()
| semTake()
| |
| V
| semTake()
| \
| \
| \-------------> semGive()
| /
| /
| taskSuspend()<-------------/
| \
| \
| \-------------> taskResume()
| /
| /
| msgQSend()<-------------/
| msgQReceive()
| |
| V
| msgQReceive()
| \
| \
| \-------------> msgQSend()
| /
| /
| wdStart() <-------------/
| wdCancel()
\---------|
V
exit
\
\
\-------------> exit
*/
#include "vxWorks.h"
#include "semLib.h"
#include "taskLib.h"
#include "msgQLib.h"
#include "wdLib.h"
#include "logLib.h"
#include "tickLib.h"
#include "sysLib.h"
#include "stdio.h"
/* defines */
#if FALSE
#define STATUS_INFO /* define to allow printf() calls */
#endif
#define MAX_MSG 1 /* max number of messages in queue */
#define MSG_SIZE sizeof (MY_MSG) /* size of message */
#define DELAY 100 /* 100 ticks */
#define HIGH_PRI 150 /* priority of high priority task */
#define LOW_PRI 200 /* priority of low priority task */
#define TASK_HIGHPRI_TEXT "Hello from the "high priority" task"
#define TASK_LOWPRI_TEXT "Hello from the "low priority" task"
/* typedefs */
typedef struct my_msg
{
int childLoopCount; /* loop count in task sending msg */
char * buffer; /* message text */
} MY_MSG;
/* globals */
SEM_ID semId; /* semaphore ID */
MSG_Q_ID msgQId; /* message queue ID */
WDOG_ID wdId; /* watchdog ID */
int highPriId; /* task ID of high priority task */
int lowPriId; /* task ID of low priority task */
int windDemoId; /* task ID of windDemo task */
/* forward declarations */
LOCAL void taskHighPri (int iteration);
LOCAL void taskLowPri (int iteration);
/******************************************************************************
*
*
* windDemo - parent task to spawn children
*
* This task calls taskHighPri() and taskLowPri() to do the
* actual operations of the test and suspends itself.
* Task is resumed by the low priority task.
*
*/
void windDemo
(
int iteration /* number of iterations of child code */
)
{
int loopCount = 0; /* number of times through windDemo */
#ifdef STATUS_INFO
printf ("Entering windDemo\n");
#endif /* STATUS_INFO */
if (iteration == 0) /* set default to 10,000 */
iteration = 10000;
/* create objects used by the child tasks */
msgQId = msgQCreate (MAX_MSG, MSG_SIZE, MSG_Q_FIFO);
semId = semBCreate (SEM_Q_PRIORITY, SEM_FULL);
wdId = wdCreate ();
windDemoId = taskIdSelf ();
FOREVER
{
/* spawn child tasks to exercise kernel routines */
highPriId = taskSpawn ("tHighPri", HIGH_PRI, VX_SUPERVISOR_MODE, 1000,(FUNCPTR) taskHighPri, iteration,0,0,0,0,0,0,0,0,0);
lowPriId = taskSpawn ("tLowPri", LOW_PRI, VX_SUPERVISOR_MODE, 1000,(FUNCPTR) taskLowPri, iteration,0,0,0,0,0,0,0,0,0);
taskSuspend (0); /* to be waken up by taskLowPri */
#ifdef STATUS_INFO
printf ("\nParent windDemo has just completed loop number %d\n",
loopCount);
#endif /* STATUS_INFO */
loopCount++;
}
}
/******************************************************************************
*
*
* taskHighPri - high priority task
*
* This tasks exercises various kernel functions. It will block if the
* resource is not available and relingish the CPU to the next ready task.
*
*/
LOCAL void taskHighPri
(
int iteration /* number of iterations through loop */
)
{
int ix; /* loop counter */
MY_MSG msg; /* message to send */
MY_MSG newMsg; /* message to receive */
for (ix = 0; ix < iteration; ix++)
{
/* take and give a semaphore - no context switch involved */
semGive (semId);
semTake (semId, 100); /* semTake with timeout */
/*
* take semaphore - context switch will occur since semaphore
* is unavailable
*/
semTake (semId, WAIT_FOREVER); /* semaphore not available */
taskSuspend (0); /* suspend itself */
/* build message and send it */
msg.childLoopCount = ix;
msg.buffer = TASK_HIGHPRI_TEXT;
msgQSend (msgQId, (char *) &msg, MSG_SIZE, 0, MSG_PRI_NORMAL);
/*
* read message that this task just sent and print it - no context
* switch will occur since there is a message already in the queue
*/
msgQReceive (msgQId, (char *) &newMsg, MSG_SIZE, NO_WAIT);
#ifdef STATUS_INFO
printf ("%s\n Number of iterations is %d\n",
newMsg.buffer, newMsg.childLoopCount);
#endif /* STATUS_INFO */
/*
* block on message queue waiting for message from low priority task
* context switch will occur since there is no message in the queue
* when message is received, print it
*/
msgQReceive (msgQId, (char *) &newMsg, MSG_SIZE, WAIT_FOREVER);
#ifdef STATUS_INFO
printf ("%s\n Number of iterations by this task is: %d\n",
newMsg.buffer, newMsg.childLoopCount);
#endif /* STATUS_INFO */
/* test watchdog timer */
wdStart (wdId, DELAY, (FUNCPTR) tickGet, 1);
wdCancel (wdId);
}
}
/******************************************************************************
*
*
* taskLowPri - low priority task
*
* This task runs at a lower priority and is designed to make available
* the resouces that the high priority task is waiting for and *subsequently unblock the high priority task.
*
*/
LOCAL void taskLowPri
(
int iteration /* number of times through loop */
)
{
int ix; /* loop counter */
MY_MSG msg; /* message to send */
for (ix = 0; ix < iteration; ix++)
{
semGive (semId); /* unblock tHighPri */
taskResume (highPriId); /* unblock tHighPri */
/* build message and send it */
msg.childLoopCount = ix;
msg.buffer = TASK_LOWPRI_TEXT;
msgQSend (msgQId, (char *) &msg, MSG_SIZE, 0, MSG_PRI_NORMAL);
taskDelay (60);
}
taskResume (windDemoId); /* wake up the windDemo task */
}
---《完》---
聯(lián)系客服