在
WinCE
系统启动最开始,也就是
EBoot
部分,会完成一定串口的初始化,以便在后面的工作中可以在串口中显示很多信息。这也是串口打印的最开始部分。
OEMReadDebugByte
、
OEMWriteDebugByte
、
OEMWriteDebugString
在
EBoot
汇编跳转到
C
语言的
main
函数后,在
blcommon.c
中的
BootLoaderMain
是第一个
C
语言函数,这里的初始化部分包含一个
OEMDebugInit
的函数,实现在
main.c
文件中,里面调用了
OEMInitDebugSerial()
函数,实现在
\WINCEROOT\PLATFORM\BSPNAME\SRC\OAL\OALLIB\debug.c
里,就是它完成了串口的打印实现,包括
OEMReadDebugByte()
、
OEMWriteDebugByte()
、
OEMWriteDebugString()
。
EdbgOutputDebugString
、
KITLOutputDebugString
在
BootLoaderMain
实现过程中,还会经常见到两个函数
EdbgOutputDebugString()
和
KITLOutputDebugString()
,这两个函数的实现其实是一样的,在
\WINCEROOT\PUBLIC\COMMOM\OAK\INC\halether.h
文件中有如下定义
:
#define EdbgOutputDebugString KITLOutputDebugString
EdbgOutputDebugString()
的实现在文件
\WINCEROOT\PUBLIC\COMMOM\OAK\DRIVERS\ETHDBG\EDBGFRMT\format.c
中,具体的实现如下,其实和
printf
的实现很类似,这里就不做太多介绍了。
void EdbgOutputDebugString (LPCSTR sz, ...)
{
unsigned char c;
va_list vl;
va_start(vl, sz);
while (*sz) {
c = *sz++;
switch (c) {
case '%':
c = *sz++;
switch (c) {
case 'x':
pOutputNumHex(va_arg(vl, unsigned long), 0);
break;
case 'B':
pOutputNumHex(va_arg(vl, unsigned long), 2);
break;
case 'H':
pOutputNumHex(va_arg(vl, unsigned long), 4);
break;
case 'X':
pOutputNumHex(va_arg(vl, unsigned long), 8);
break;
case 'd':
{
long l;
l = va_arg(vl, long);
if (l < 0) {
pOutputByte('-');
l = - l;
}
pOutputNumDecimal((unsigned long)l);
}
break;
case 'u':
pOutputNumDecimal(va_arg(vl, unsigned long));
break;
case 's':
OutputString(va_arg(vl, char *));
break;
case '%':
pOutputByte('%');
break;
case 'c':
c = va_arg(vl, unsigned char);
pOutputByte(c);
break;
default:
pOutputByte(' ');
break;
}
break;
case '\r':
if (*sz == '\n')
sz ++;
c = '\n';
// fall through
case '\n':
pOutputByte('\r');
// fall through
default:
pOutputByte(c);
}
}
va_end(vl);
}
NKDbgPrintfW
、
OutputDebugStringW
NKDbgPrintfW()
函数同样是在文件
\WINCEROOT\PUBLIC\COMMOM\OAK\DRIVERS\ETHDBG\EDBGFRMT\format.c
中实现的,实现代码如下:
void NKDbgPrintfW(
const WCHAR *sz, ...)
{
unsigned char c;
va_list vl;
va_start(vl, sz);
while (*sz) {
c = (unsigned char)*sz++;
switch (c) {
case (unsigned char)'%':
c = (unsigned char)*sz++;
switch (c) {
case 'x':
pOutputNumHex(va_arg(vl, unsigned long), 0);
break;
case 'B':
pOutputNumHex(va_arg(vl, unsigned long), 2);
break;
case 'H':
pOutputNumHex(va_arg(vl, unsigned long), 4);
break;
case 'X':
pOutputNumHex(va_arg(vl, unsigned long), 8);
break;
case 'd': {
long l;
l = va_arg(vl, long);
if (l < 0) {
pOutputByte('-');
l = - l;
}
pOutputNumDecimal((unsigned long)l);
}
break;
case 'u':
pOutputNumDecimal(va_arg(vl, unsigned long));
break;
case 's':
OutputStringW(va_arg(vl, WCHAR *));
break;
case '%':
pOutputByte('%');
break;
case 'c':
c = va_arg(vl, unsigned char);
pOutputByte(c);
break;
default:
pOutputByte(' ');
break;
}
break;
case '\n':
pOutputByte('\r');
// fall through
default:
pOutputByte(c);
}
}
va_end(vl);
}
OutputDebugStringW()
函数其实是直接调用
NKDbgPrintfW()
实现的。
void OutputDebugStringW(LPCWSTR fmt)
{
NKDbgPrintfW(fmt);
}
RETAILMSG
、
DEBUGMSG
这两个函数是在
BSP
中最常见的了,在文件
\WINCEROOT \PUBLIC\COMMON\SDK\INC\dbgapi.h
中实现,两者的实现是一摸一样的,只是在不同的编译条件下实现的效果不同而已,都是通过上面的
NKDbgPrintfW()
函数来实现的。具体实现如下:
#define DEBUGMSG(cond,printf_exp) \
((void)((cond)?(NKDbgPrintfW printf_exp),1:0))
#define RETAILMSG(cond,printf_exp)\
((cond)?(NKDbgPrintfW printf_exp),1:0)