您的位置:首页 > 其它

MTK调试入门之一 --- TRACE使用的技巧

2010-02-05 10:56 337 查看
MTK的调试一般来说可以分为仿真调试与手机调试.这两种调试对于研发新功能,修改BUG,研究算法都是十分重要的.当然,这两种调试也有差异,有时会出现在模拟器运行正常,在手机却运行失败,或者相反,这就突出了软件模拟环境与硬件手机环境的差别.原因可能是各种各样的,比如可能是有些硬件软件没有办法模拟,有些新功能对硬件依赖强,不能模拟,新软件的有些函数只能在手机上运行,没有写相应的模拟器代码.等等原因都会导致两者差异.这里不一一赘述,大家知道模拟器和手机有差异就行了.

模拟器调试具有直观,快速,追踪方便能优点,受到很多MMI开发者的喜欢.而有关模拟器的调试,其他也就是VC调试功能的使用.由于国内软件教育重编程,算法,轻调试,所以很少有系统的调试方书的书.在开发过程中,我也见过许多人压根就不使用模拟器,他们认为模拟器也就是在没有手机的时候使用.详细讲解模拟器的调试就放到以后,因为模拟器断点,内存,堆栈,变量各个方面的调试,详细写来都可以成一篇文章.这里先讲一个手机调试的TRACE使用.以前曾写过一篇DUMP调试的文章.通过出错的DUMP信息查找错误.有兴趣的朋友可以参考. http://www.52rd.com/Blog/Detail_RD.Blog_blogercn_19169.html

1.在MTK平台,我们最常使用的TRACE函数是kal_prompt_trace函数,这个函数是系统提供给我们的用于在catcher里调试错误的.在这个函数不能使用的场合,有时我们会使用函数system_print或者dbg_printf,这两个函数可以不使用catcher的情况,使用WIN自带的工具超级终端来调试程序.有时驱动的朋友会自己用函数PutUARTBytes写自已TRACE函数,这些函数可以使用超级终端调试,如下,就是别人写的一个TRACE函数.打印某一块数据的内容,常常TRACE内存数据,指定地址,指定大小

void perun_dump(void *buf, prn_int16 size)

{

#ifdef PRN_TRACE_OPEN

#ifdef MMI_ON_HARDWARE_P

char str[2048];

char *ptr = (char*)str;

char *ptr1 = buf;

int i = 0;

memset(str, 0, sizeof(str));

strcpy(ptr, "[Perun_dump]: ");

ptr += strlen("[Perun_dump]: ");

while (i < size)

{

sprintf(ptr, " %02x", *ptr1);

ptr += 3;

++ptr1;

++i;

}

sprintf(ptr, "/r/n");

PutUARTBytes(0, (kal_uint8 *)str, (kal_uint16)strlen(str));

#endif

#endif

}

也可以写一个像MTK自带的一样的函数来TRACE,如下,该函数也是可以运行在终端中:

Void perun_trace(char *fmt, ...)

{

#ifdef PRN_TRACE_OPEN

#ifdef MMI_ON_HARDWARE_P

va_list list;

char buf[2048];

char *ptr = (char*)buf;

memset(buf, 0, sizeof(buf));

strcpy(ptr, "[Perun_trace]: ");

ptr += strlen("[Perun_trace]: ");

va_start(list, fmt);

vsprintf(ptr, fmt, list);

va_end(list);

strcat(buf, "/r/n");

buf[2047] = 0;

PutUARTBytes(0, (kal_uint8 *)buf, strlen(buf));

#endif

#endif

}

2.TRACE语句的编写是十分重要的.如何写出的TRACE既能在仿真下使用,也能在手机中使用,我一般会使用如下的格式:

#ifdef WIN32

#define MYTRACE printf

#else

#define MYTRACE(...) kal_prompt_trace(MOD_WAP, __VA_ARGS__)

#endif

经过如下的封装,MYTRACE就可以既能在手机上运行,也能在电脑中运行, 并且我已经消除了MTK自带的函数与printf在调用上的不同.顺便说一下,模拟器调用函数MYTRACE时,会在控制制输出该函数的打印信息.手机调用MYTRACE时,会在filiter为MOD_WAP时输出信息.

3.有时为了便于观察,我会为我的TRACE语句添加一个前缀,比如我自己的TRACE前面添加十个>或者我自己的拼音名字,我会如下修改我的MYTRACE:

#ifdef WIN32

#define MYTRACE printf

#else

#define STR(s) #s

#define MYTRACE(...) kal_prompt_trace(MOD_WAP, STR(>>>>>>>>>>)##__VA_ARGS__)

#endif

经过这样的改进,我的TRACE在输出信息时,信息头就是我的名字,我可以使用查找全部功能把我需要的TRACE全抓出来.如果你对#号的使用,有疑问,请自己查找相关资料

4.种种迹象和从理论上看来,TRACE和MMI_ASSERT是调试的好帮手,但在发布软件时,带上了这个会引来不必要的麻烦.MMI_ASSERT增加了系统重启的频率.TRACE增加了系统的ROM,RAM和CPU的开销.在工作中,我们曾经发现一款手机,由于ROM过于紧张,添加几条TRACE就会出现编译错误,去掉TRACE就编译通过了,导致出了BUG调试十分的麻烦.如何写一种使用时可以TRACE错误,不使用时又不占用系统资源的TRACE呢,我见许多人这样处理,因为NULL会被编译器优化点,后面括号变成一个表达式了.表达式对系统的开销自然小于函数了.

#ifdef DEBUG_KAL

#define MYTRACE(...) kal_prompt_trace(MOD_WAP, __VA_ARGS__)

#else

#define MYTRACE NULL

#endif

我一般这样操作.

#ifdef DEBUG_KAL

#define MYTRACE(...) kal_prompt_trace(MOD_WAP, __VA_ARGS__)

#else

#define MYTRACE //

#endif

我曾经认为这样写可以在不使用时,把宏函数变为注释符,但我的一个朋友认为这样写,并不能把我的函数变成注释符,他的道理是双斜线会被编译器外忽略掉,我认为是有道理的,后来我的朋友经过思考,写出如下的TRACE,通过一个反斜杠的连接符,哄编译器在展开宏时把两个斜杠连起来组成注释符,这个写法有些古怪,下面的单个斜杠必须顶格写,以保证经过连接合,两斜杠之间没有空格从而在被编译时与后面的代码组成注释行.但这样写的一个致命的缺陷是会让许多人看不明白.另一个缺陷时不美观

#ifdef DEBUG_KAL

#define MYTRACE printf

#else

#define MYTRACE //

/

#endif

5.有关C语言的古怪用法,据<C专家编程>的作者曾说,世界上有一个古怪的大赛叫”国际C语言混乱代码大赛”,每年举办一次.获奖的都功能齐全而代码惨不忍睹的典型.在MTK上,也曾经有一段费了我很大功夫的TRACE代码:

#define DBG_PRINTF(_x_) /

do{ /

printf("%s(%d)--:",__FILE__,__LINE__);/

printf _x_; /

}while(0);

当时怎么想都不明白为什么会有这么古怪的使用printf _x_;后来才发现使用时要加双层括号才能正常使用。

6.在手机与网络,手机与电脑的交互过程中,有时我们需要TRACE数据包的内容,特别在显示不正确或者不精确的情况下,需要研究数据包的数据是使用UTF编码,还UCS2编码,还是ASC编码,这时我们就需要TRACE数据的字节内容,从而便于分析。我一般使用下面这个自己随手写的函数来实现.

static U8 TraceUni(U8 *str, U8 len)
{
U8 *tempstr,*tempascstr;
U8 i;

tempstr = str;
kal_prompt_trace(MOD_MMI, "XXXXXXXXXXXXXXXXXXXXXXXX Trace mmi_msg_handle_new_msg_ind is start XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
if (*(tempstr + 1) == 0x00)
{
UnicodeNToAnsii((S8*)tempascstr,(S8*)tempstr,len );
kal_prompt_trace(MOD_MMI, "jone trace, the string = %s", tempascstr);
}
else
{
for (i = 0; (*tempstr != NULL) || (*(tempstr+1) != NULL) && (len-- != 0); i++)
{
kal_prompt_trace(MOD_MMI, "jone trace, the string[%d] = %x", i, *(tempstr++));
}
}
kal_prompt_trace(MOD_MMI, "XXXXXXXXXXXXXXXXXXXXXXXX Trace string is end XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: