Выбрать главу

Debug Zones

Debug messages are particularly useful tools to analyze multi-threaded processes, especially thread synchronization and other timing issues that are difficult to detect by stepping through the code. However, the number of debug messages generated on a target device can be overwhelming if you heavily use debugging macros in your code. To control the amount of information generated, debugging macros enable you to specify a conditional expression. For example, the following code outputs an error message if the dwCurrentIteration value is greater than the maximum possible value.

ERRORMSG(dwCurrentIteration > dwMaxIteration,

 (TEXT("Iteration error: the counter reached %u, when max allowed is %u\r\n"),

 dwCurrentIteration, dwMaxIteration));

In the example above, ERRORMSG outputs debugging information whenever dwCurrentIteration is greater than dwMaxIteration. You can also control debugging messages by using debug zones in the conditional statement. This is particularly useful if you want to use the DEBUGMSG macro to examine code execution in a module (that is, an executable file or a DLL) at varying levels without changing and recompiling the source code each time. First, you must enable debug zones in your executable file or DLL, and register a global DBGPARAM variable with the Debug Message service to specify which zones are active. You can then specify the current default zone programmatically or through registry settings on the development workstation or the target device. It is also possible to control debug zones dynamically for a module in Platform Builder via CE Debug Zones on the Target menu or in the Target Control window.

TIP
Bypassing debug zones

You can bypass debug zones in drivers and applications if you pass a Boolean variable to the DEBUGMSG and RETAILMSG macros that you can set to TRUE or FALSE when you rebuild the run-time image.

Zones Registration

To use debug zones, you must define a global DBGPARAM variable with three fields that specify the module name, the names of the debug zones you want to register, and a field for the current zone mask, as summarized in Table 4-2.

Table 4-2 DBGPARAM elements

Field Description Example
lpszName Defines the name of the module with a maximum length of 32 characters. TEXT("ModuleName")
rglpszZones Defines an array of 16 names for the debug zones. Each name can be up to 32 characters long. Platform Builder displays this information to the user when selecting the active zones in the module. { TEXT("Init"), TEXT("Deinit"), TEXT("On"), TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"), TEXT("Failure"), TEXT("Warning"), TEXT("Error") }
ulZoneMask The current zone mask used in the DEBUGZONE macro to determine the currently selected debug zone. MASK_INIT | MASK_ON | MASK_ERROR
NOTE
Debug zones

Windows Embedded CE supports a total of 16 named debug zones, yet not all have to be defined if the module doesn’t require them. Each module uses a separate set of zone names that should clearly reflect the purpose of each implemented zone.

The Dbgapi.h header file defines the DBGPARAM structure and debugging macros. Because these macros use a predefined DBGPARAM variable named dpCurSettings, it is important that you use the same name in your source code as well, as illustrated in the following code snippet.

#include <DBGAPI.H>

// A macro to increase the readability of zone mask definitions

#define DEBUGMASK(n) (0x00000001<<n)

// Definition of zone masks supported in this module

#define MASK_INIT    DEBUGMASK(0)

#define MASK_DEINIT  DEBUGMASK(1)

#define MASK_ON      DEBUGMASK(2)

#define MASK_FAILURE DEBUGMASK(13)

#define MASK_WARNING DEBUGMASK(14)

#define MASK_ERROR   DEBUGMASK(15)

// Definition dpCurSettings variable with the initial debug zone state

// set to Failure, Warning, and Error.

DBGPARAM dpCurSettings = {

 TEXT("ModuleName"), // Specify the actual module name for clarity!

 {

  TEXT("Init"), TEXT("Deinit"), TEXT("On"), TEXT("Undefined"),

  TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"),

  TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"),

  TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"),

  TEXT("Failure"), TEXT("Warning"), TEXT("Error")

 },

 MASK_INIT | MASK_ON | MASK_ERROR

};

// Main entry point into DLL

BOOL APIENTRY DllMain( HANDLE hModule,

 DWORD ul_reason_for_call, LPVOID lpReserved) {

 if (ul_reason_for_call == DLL_PROCESS_ATTACH) {

  // Register with the Debug Message service each time

  // the DLL is loaded into the address space of a process.

  DEBUGREGISTER((HMODULE)hModule);