MTK调试入门之一-TRACE使用的技巧
52RD上曾有朋友讓我寫一些調試技巧方面的文章.調試對于軟件是十分重要的,但卻不是一篇二篇文章能講清楚的.有很多調試技巧都是零零碎碎的東西,用的時候能很容易使用,但要寫出來時,卻還是比較麻煩的.
MTK的調試一般來說可以分為仿真調試與手機調試.這兩種調試對于研發新功能,修改BUG,研究算法都是十分重要的.當然,這兩種調試也有差異,有時會出現在模擬器運行正常,在手機卻運行失敗,或者相反,這就突出了軟件模擬環境與硬件手機環境的差別.原因可能是各種各樣的,比如可能是有些硬件軟件沒有辦法模擬,有些新功能對硬件依賴強,不能模擬,新軟件的有些函數只能在手機上運行,沒有寫相應的模擬器代碼.等等原因都會導致兩者差異.這里不一一贅述,大家知道模擬器和手機有差異就行了.
模擬器調試具有直觀,快速,追蹤方便能優點,受到很多MMI開發者的喜歡.而有關模擬器的調試,其他也就是VC調試功能的使用.由于國內軟件教育重編程,算法,輕調試,所以很少有系統的調試方書的書.在開發過程中,我也見過許多人壓根就不使用模擬器,他們認為模擬器也就是在沒有手機的時候使用.詳細講解模擬器的調試就放到以后,因為模擬器斷點,內存,堆棧,變量各個方面的調試,詳細寫來都可以成一篇文章.這里先講一個手機調試的TRACE使用.以前曾寫過一篇DUMP調試的文章.通過出錯的DUMP信息查找錯誤.有興趣的朋友可以參考.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_listlist;??? 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 /\/#endif5.有關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 Tracemmi_msg_handle_new_msg_ind isstart XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");if (*(tempstr + 1) == 0x00){UnicodeNToAnsii((S8*)tempascstr,(S8*)tempstr,len);kal_prompt_trace(MOD_MMI, "jone trace, thestring = %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 Tracestring isend XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");return 0; }轉載于:https://www.cnblogs.com/harisucici/archive/2011/11/30/2268859.html
總結
以上是生活随笔為你收集整理的MTK调试入门之一-TRACE使用的技巧的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学习C++的五十条忠告
- 下一篇: php 之fsockopen(转)