在WinCE的開(kāi)發(fā)環(huán)境中支持Debug Zones功能,通常也被稱(chēng)為調(diào)試域,通過(guò)它可以控制打印信息。當(dāng)某個(gè)調(diào)試域被打開(kāi)以后,在這個(gè)域中的打印信息就會(huì)被打印出來(lái),如果某個(gè)調(diào)試域被關(guān)閉了,那么這個(gè)域中的打印信息就會(huì)被關(guān)閉。調(diào)試域是基于模塊的,也就是說(shuō)一個(gè)模塊,可能是在一個(gè)驅(qū)動(dòng)或者一個(gè)應(yīng)用中都可以定義一個(gè)調(diào)試域,用來(lái)調(diào)試該模塊。一個(gè)調(diào)試域最多可以包括16個(gè)域,一般在每一個(gè)模塊中都會(huì)有一個(gè)全局變量dpCurSettings,該變量用于描述調(diào)試域的相關(guān)信息,它由一個(gè)模塊名字,16個(gè)域的名字和一個(gè)掩碼組成。下面具個(gè)例子:
DBGPARAM dpCurSettings =
{
TEXT("PCIBUS"), {
TEXT("Errors"),TEXT("Warnings"),TEXT("Functions"),TEXT("Initialization"),
TEXT("Enumeration"),TEXT("Load Order"),TEXT("Resource"),TEXT("Undefined"),
TEXT("Undefined"),TEXT("Undefined"),TEXT("Undefined"),TEXT("Undefined"),
TEXT("Undefined"),TEXT("Undefined"),TEXT("Undefined"),TEXT("Undefined") },
0x20
};
先來(lái)解釋一下DBGPARAM結(jié)構(gòu),該結(jié)構(gòu)在Dbgapi.h中定義,所以在定義dpCurSettings的時(shí)候還需要包含這個(gè)頭文件,該結(jié)構(gòu)定義如下:
typedef struct _DBGPARAM {
WCHAR lpszName[32]; //模塊的名字
WCHAR rglpszZones[16][32]; //調(diào)試域的名字
ULONG ulZoneMask; //調(diào)試域的掩碼
}DBGPARAM, *LPDBGPARAM;
在上面的例子中可以看到,第一個(gè)是模塊的名字,叫PCIBUS。而后定義了16個(gè)域的名字,其中只用到了7個(gè)域,剩下的都定義為Undefined了。最后一個(gè)數(shù)字為域的掩碼,表示當(dāng)前哪個(gè)域是被激活的,0x20表示只有第6個(gè)域是被激活的。從上面的例子還可以看出,前7個(gè)域是有意義的,而且按照順序分別對(duì)應(yīng)1到7。下面針對(duì)這些域需要定義相應(yīng)Debug調(diào)試的宏定義:
#define DBGZONE_ERROR 1
#define DBGZONE_WARNING 2
#define DBGZONE_FUNCTION 3
#define DBGZONE_INIT 4
#define DBGZONE_ENUM 5
#define DBGZONE_LOADORDER 6
#define DBGZONE_RESOURCE 7
上述宏定義對(duì)應(yīng)在dpCurSettings中的7個(gè)域,然后就可以在打印信息的時(shí)候,通過(guò)這些宏定義來(lái)對(duì)應(yīng)相應(yīng)的調(diào)試域了。例如:
- while(1)
- {
- if (dwFlag)
- {
- DEBUGMSG(DBGZONE_ERROR, (L"Error found: %d\r\n", NumDevKeys));
- break;
- }
- else
- {
- DEBUGMSG(DBGZONE_WARNING, (L"Warning found\r\n"));
- }
-
- DEBUGMSG(DBGZONE_LOADORDER, (L"load in a while loop\r\n"));
- Sleep(100);
- }
-
從這段代碼可以看出,如果dpCurSettings中的掩碼定義為0x20,那么在DEBUGMSG的打印中,只有條件為DBGZONE_LOADORDER才會(huì)被打印,循環(huán)中的前兩個(gè)打印信息是不會(huì)被打印的。如果想讓上面的代碼中的所有DEBUGMSG都能打印必須設(shè)置掩碼如下:
dpCurSettings.ulZoneMask = DBGZONE_ERROR | DBGZONE_WARNING | DBGZONE_LOADORDER;
在一個(gè)模塊中定義了調(diào)試域,如果想在系統(tǒng)中去使用還必須注冊(cè)該調(diào)試域,需要用到的函數(shù)叫DEBUGREGISTER(..),其中要把該調(diào)試模塊的句柄作為參數(shù)傳給它。例如:
DllMain(..)
{
switch(op)
{
case DLL_PROCESS_ATTACH:
DEBUGREGISTER(hPCIBUS);
break;
….
}
}
完成了上述工作以后,就可以重新編譯調(diào)試的模塊,然后運(yùn)行系統(tǒng)來(lái)調(diào)試了。調(diào)試域的一個(gè)好處就是在Debug的過(guò)程中,不需要終止系統(tǒng)可以動(dòng)態(tài)的改變調(diào)試域,方便我們分析問(wèn)題。首先,我們可以基于Platform. Builder中的CE Debug Zones來(lái)調(diào)試,在VS2005的菜單中選擇Target,然后選擇CE Debug Zones,如圖:

然后會(huì)出現(xiàn)一個(gè)Debug Zones的窗口,在窗口彈出以后,它可能會(huì)花一點(diǎn)時(shí)間來(lái)收集當(dāng)前支持Debug Zone的模塊,如下圖:

該圖只是一個(gè)例子,左邊顯示了可調(diào)試的模塊,選擇serial_SMDK2410.dll這個(gè)模塊,就是S3C2410的串口驅(qū)動(dòng)模塊。在右側(cè)可以看到各個(gè)調(diào)試域及名字,用戶可以根據(jù)需要來(lái)選擇打開(kāi)和關(guān)閉相應(yīng)的調(diào)試域,最后點(diǎn)擊Apply和OK就可以了。
當(dāng)然,還有其他的方法來(lái)修改調(diào)試域,一種方法是使用Target Control中的zo命令來(lái)修改,Target Control將在以后介紹。還有一種方法就是通過(guò)SetDbgZone(..)函數(shù)來(lái)修改。定義如下:
BOOL SetDbgZone(DWORDdwProcid, LPVOIDlpvMod, LPVOIDbaseptr, DWORDzone, LPDBGPARAMlpdbgTgt)
dwProcid: 進(jìn)程的句柄
lpvMod: 調(diào)試模塊的句柄
baseptr: 設(shè)置為NULL
zone: 新的調(diào)試域掩碼
lpdbgTgt: 返回新的DBGPARAM結(jié)構(gòu)
上面對(duì)Debug Zone的定義,使用以及調(diào)試作了大致的介紹,按照上面的步驟可以給一個(gè)模塊添加調(diào)試域,注冊(cè)調(diào)試域并在系統(tǒng)運(yùn)行以后隨時(shí)更改調(diào)試域,其根本目的無(wú)非是幫助我們來(lái)調(diào)試模塊和分析問(wèn)題。一般情況下,調(diào)試域只在Debug模式下使用,但是也可以在Release模式下使用。但是有些地方需要修改,首先前面已經(jīng)介紹過(guò)Debug模式下的打印用DEBUGMSG,而Release模式下的打印應(yīng)該使用RETAILMSG函數(shù)。所以在Release模式下,打印函數(shù)應(yīng)該改為RETAILMSG函數(shù)。還有在注冊(cè)調(diào)試域的時(shí)候,不能再使用DEBUGREGISTER(..)函數(shù),而是應(yīng)該改用RETAILREGISTERZONES(..)函數(shù)。