<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > ROM版本下系統調試信息的一種顯示方法

ROM版本下系統調試信息的一種顯示方法

作者: 時(shí)間:2006-05-07 來(lái)源:網(wǎng)絡(luò ) 收藏

摘要:提出在目標系統脫離開(kāi)發(fā)系統運行時(shí),如何通過(guò)串口在Windows的超級終端軟件中顯示調試信息的一個(gè)具體方法。該方法有助于改進(jìn)調試質(zhì)量、縮短調試周期。

本文引用地址:http://dyxdggzs.com/article/241598.htm

關(guān)鍵詞:脫機調試 超級終端 可變參數函數 輸出函數

1 ROM版本目標系統的調試問(wèn)題

一般的目標系統在開(kāi)發(fā)工具環(huán)境下的調試并不困難,但最終系統必須脫離開(kāi)發(fā)工具獨立運行,即使在開(kāi)發(fā)工具環(huán)境下完全正常的系統,ROM版本也往往會(huì )出現各種問(wèn)題。原因有兩人:一是開(kāi)發(fā)工具硬件環(huán)境和最終的目標硬件環(huán)境不完全相同;二是外部因素不同,實(shí)驗室中無(wú)法模擬現場(chǎng)的很多外部條件。因此,在脫離開(kāi)發(fā)工具后的現場(chǎng)運行中,也能進(jìn)行調試,這在產(chǎn)品開(kāi)發(fā)的初期是十分重要的。對于硬件的調試,可以使用示波器等儀器;對于軟件的調試,一般方法則是顯示軟件運行中的各種信息(如變量)。

我們知道,C語(yǔ)言中的“printf()”函數是學(xué)習C語(yǔ)言的人最了解和熟悉的一個(gè)函數。很多C語(yǔ)言教材一開(kāi)始就以顯示“hello word”字符串來(lái)描述C語(yǔ)言的基本特片,其中唯一的語(yǔ)句就是調用“printf ()”函數。雖然該函數可以在屏幕上輸出信息,但一般的用戶(hù)軟件中只在調試時(shí)用它來(lái)顯示某些中間變量的結果,一旦程序調試完成,就將其刪除了,真正的應用信息(如菜單字符等)顯示往往其他的輸出函數,如puts(),cputs()等。實(shí)際上,在C語(yǔ)言編寫(xiě)的第一個(gè)軟件-UNIX操作系統中,該函數也是用于輸出調試信息或系統錯誤提示信息的。對于使用和學(xué)習C語(yǔ)言的程序員來(lái)說(shuō),printf()由于可以同時(shí)輸出不同類(lèi)型的數據,因此,它的使用是軟件調試的重要手段之一。

在TURBO C2.0編譯器中,printf()函數的實(shí)現依賴(lài)于操作系統。在系統中,往往沒(méi)有操作系統或者操作系統不提供這個(gè)功能,也可能沒(méi)有顯示輸出部件,或顯示設備的空間有限,只能用于顯示應用信息。因此,必須用其他的方法來(lái)解決調試信息的輸出問(wèn)題。最常用的方法是通過(guò)目標系統的一個(gè)串口將信息發(fā)送給PC機來(lái)顯示,PC機上可以使用Windows的“超級終端”軟件接受和顯示信息,如圖1所示。

這種系統的硬件很簡(jiǎn)單,我們只說(shuō)明軟件的實(shí)現方法。為此,我們必須設計專(zhuān)用的、可以顯示各種數據類(lèi)型的printf()函數,以達到從串口或其他途徑輸出信息的目的。在一些C開(kāi)發(fā)工具(如C51)中,系統提供了printf()庫函數,但沒(méi)有提供源代碼[1],LINUX和UNIX的源代碼中雖然也包含printf()的函數源代碼,但過(guò)于復雜[2,3]。和一般的C函數不同,printf()函數的參數數量和類(lèi)型是可變的,這是編寫(xiě)該函數的難點(diǎn)。要解決這個(gè)難是,必須先了解C函數參數傳遞的原理。

2 C函數的參數傳遞原理

在大部分情況下,C語(yǔ)言是通過(guò)堆棧存儲器來(lái)傳遞參數(也有例外,C51的小模式則通過(guò)寄存器傳遞參數)。對于非指針類(lèi)型,傳遞的不是原來(lái)類(lèi)型的數據,而是對參數進(jìn)行了類(lèi)型轉換,如字符類(lèi)型(char)變成整型(int)拷貝到堆棧中、浮點(diǎn)類(lèi)型(float)變成雙精度類(lèi)型(double),如表1所列。表1中未列出的,則沒(méi)有轉換[4]。

表1

調用類(lèi)型轉換類(lèi)型字節數
charint2
floatdouble4
struct完全拷貝sizeof(struct...)

對于像字符數組之類(lèi)的指針參數,是將指針拷貝到堆棧中,而不是將數組中的所有內容傳送到堆棧中。比如,對函數fun(char *str,int i,float a)的調用:

char str[10]=“welcome”;

int i=100; float a=1.14;

……

fun(str,i,a);

各個(gè)參烽str,i在堆棧中按先右后左的次序存放,表2所列為調用函數fun( )開(kāi)始時(shí)堆棧中的參數存放情況。此時(shí)函數fun()的代碼上尚未執行,函數中的局部變量也是在堆棧中,所以在函數執行結束后,局部變量將消失。

表2 函數調用時(shí)的參數在堆棧中的存儲情況(X86環(huán)境)

堆棧指針(大模式)內 容 字節數
大模式小模式



…………
sp+10a42
sp+8i22
sp+4str42
sp返回主函數的偏移地址42
sp-?函數fun的局部變量

表2說(shuō)明了兩個(gè)問(wèn)題:第一個(gè)問(wèn)題是,每個(gè)參數在堆棧中的存儲長(cháng)度和參數的類(lèi)型有關(guān)。對于指針類(lèi)型參數,參數長(cháng)度和編譯模式有關(guān):大模式下,地址包括段地址和偏移地址,共4字節;而小模式下,地址只有段內偏移,占2字節。第二個(gè)問(wèn)題是,如果知道其中的一個(gè)參數地址和參數的類(lèi)型,則可以得到任意參數的數值,并不需要知道參數的名稱(chēng)。比如在函數fun()中,可用以下代碼顯示各個(gè)參數的內容:

void fun(char *str,int i,float *a)

{

void *p

p=str;

printf(str=%s,str); p=(char **)p+1;

printf(i=%d ((int*)p));p=(int *)p+1;

printf(i=%d *((float *)p));

}

上面語(yǔ)句定義了一個(gè)無(wú)法型指針p來(lái)指向堆棧地址,這樣,就可以得到堆棧中的各個(gè)參數。p被初始化為指向第一個(gè)參數str。因為str也是一個(gè)指針,所以需要將p轉換為一個(gè)二重指針后再加1,以使指針移向下一個(gè)參數i。這樣,沒(méi)有使用參數i和a,也可以顯示這兩個(gè)變量的數值。

3 PC機上的printf()函數的設計實(shí)現

現在,可以編寫(xiě)自己的printf()函數了。以下給出TC20編譯環(huán)境下的具體實(shí)現代碼,在其他環(huán)境下,可以根據該原理進(jìn)行移植。該函數除了可以顯示十進(jìn)制、字符串、十六進(jìn)制等格式數值外,也可以按位顯示二進(jìn)制數。對于其他類(lèi)型,讀者可以根據需要增刪。

在實(shí)際應用中,可以修改其中的putchar()函數,將字符發(fā)到串口,就可以達到上述目的了。這里我們編寫(xiě)的函數還增加了數字的二進(jìn)制顯示,這對于很多位域應用是很有用處的。

/*printf()函數的實(shí)現代碼,為和庫函數區別,特在各函數前增加前綴“my”*/

void myprintf(char *fmt,…)

{

void *p;

char ch;

p=fmt;p=(char**)p+1;/*指向堆棧中的下一個(gè)參數*/

while(1){

while((ch=*fmt++)!='%'{/*讀入格式字符串*/

if(ch= ='0')return;

putchar(ch);

};

ch=*fmt++;

switch(ch){ /*格式字符分析*/

/*因為字符參數傳遞時(shí)也轉換成整形參數傳遞,故同樣處理*/

case 'c':

case'd':

case'x':

case'0':

case'b':

if(ch= ='c')myputchar(*(int *)p));

if(ch= ='d')myprintn(*((int *)p),10);

if(ch= ='x')myprintn(*((int *)p),16);

if(ch= ='o')myprintn(*((int *)p),8);

if(ch= ='b')myprintn(*((int *)p),2);

p=(int)p+1; /*指針移動(dòng)*/

break;

case's':

myputs(*((char **)p));

p=(char **)p+1; /*指針移動(dòng)*/

break;

default;

};

}

}

void myputs(char str) /*顯示一個(gè)字符*/

{

while((*str)!='0')myputchar('str++);

}

/*顯示任意進(jìn)制的數值,b為二、八、十、十六等進(jìn)制數*/

void myprintn(int,n,int b)

{

if(b= =16){ myprintx(n); return; }

if(n0){ myputchar('-'); n=-n; };

if(n/b)

myprintn(n/b,b);

myputchar(n%b+'0');

}

void myprintx(int n) /*以十六進(jìn)制顯示1個(gè)數字*/

{

signed char i;

for(i=3;i>=0;i--)

if(((n>>i*4)0x0f)>=10)

/*當10,11…時(shí),顯示'a','b',…'f',*/

myputchar(((n>>i*4)0x0f)-10+'a');

else myputchar(((n>>i*4)0x0f)+'0');

}

/*

*在很多系統中,并不存在PC一樣的標準顯示設備,

*通過(guò)修改該函數,可以將字符“ch”發(fā)送到串口,或者目

*標系統中的LED、LCD等顯示器件。這樣,就可以在脫

*離開(kāi)發(fā)系統情況下顯示調試信息,從而調試目標系統的軟

*件或硬件。

*/

void myputchar(int ch)

{

……;/*此函數可供修改,將字符“ch”送到SBUF或其他顯示器件就可以了*/

}

4 超級終端軟件的使用

打開(kāi)Windows的“超級終端”軟件,再打開(kāi)“hypertrm”,新建一個(gè)終端會(huì )話(huà)。在該會(huì )話(huà)的“屬性u35774設置u32456終端仿真”菜單下,將終端仿真類(lèi)型設置為VT100[5];在“屬性u35774設置u32456終端設置u23383字符集”菜單下設置字符集為“ASCII”;在“屬性u36830連接到u37197配置u24120常規u26368最快速度”下設置通信波特率和目錄系統一致,并將該對話(huà)框下“僅以該速度連接打開(kāi)”設置選中;在“屬性u36830連接到u37197配置u36830連接u36830連接首選項”下設置傳送數據位數、校驗方式。完成后,連接好RS-232串口線(xiàn),就可以在超級終端窗口顯示目標系統的調試信息了。

在用超級終端顯示時(shí),唯一要求發(fā)送的數據必須以ASCII碼形式發(fā)送(上述printf()函數就是如此)。如果要求交互式雙向數據傳送,請參考VT100文檔[5]。對于字符和控制的說(shuō)明,這里不再描述。

當然,在不方便使用PC機的情況下(如某些工業(yè)現場(chǎng)),可以自制一個(gè)簡(jiǎn)單帶串口的LED或LCD的ASCII顯示終端來(lái)專(zhuān)門(mén)顯示的調試信息。

linux操作系統文章專(zhuān)題:linux操作系統詳解(linux不再難懂)


評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>