|
|
嵌入式系統(tǒng) <BR> 采用大容量EPROM來固化程序的專用系統(tǒng),正在智能儀器和自動(dòng)化等領(lǐng)域里 得到廣泛應(yīng)用。傳統(tǒng)設(shè)計(jì)方法用匯編語言編寫程序,這主要是從保證速度和節(jié)省存儲(chǔ) 空間考慮,但編程費(fèi)時(shí),調(diào)試和排錯(cuò)很不容易。微電子技術(shù)的飛速發(fā)展,使高性能微 處理器和大容量存儲(chǔ)器的價(jià)格變得十分便宜,速度和存儲(chǔ)容量不再是困擾設(shè)計(jì)者的主 要問題。人們將ROMBIOS和CRT顯示器等外設(shè)加進(jìn)這類專用系統(tǒng),并嘗試用 高級(jí)語言來開發(fā)其軟件,即把通用計(jì)算機(jī)上的軟件和硬件“嵌入”專用系統(tǒng),構(gòu)成所 謂的嵌入式系統(tǒng)(EmbeddedSystem)。由于C語言容易編程、代碼緊 湊、可移植性和可維護(hù)性好,因而被普遍用于嵌入式程序的設(shè)計(jì)。 <BR> 大多數(shù)嵌入式系統(tǒng)無操作系統(tǒng)支持,要由設(shè)計(jì)者提供所有低級(jí)I/O功能。系統(tǒng) I/O資源有限,程序必須固化在EPROM中,不能象在DOS下那樣從磁盤裝入 和由用戶編程。設(shè)計(jì)者要編寫一個(gè)定位程序(Locator),把EXE格式的應(yīng) 用程序轉(zhuǎn)換成可固化進(jìn)EPROM的二進(jìn)制文件(ROM圖)。還要編寫一個(gè)啟動(dòng)程 序(runtimeStartupCode),與ROM圖一起嵌入EPROM, 先由它建立數(shù)據(jù)區(qū)和對(duì)系統(tǒng)硬件作必要初始化,然后調(diào)Main函數(shù),執(zhí)行應(yīng)用程序。 若想發(fā)揮C語言之優(yōu)勢(shì),使用一些標(biāo)準(zhǔn)I/O語句,如用printf驅(qū)動(dòng)顯示器等, 則要在嵌入式程序中加進(jìn)經(jīng)過修改的庫函數(shù)?傊,C語言編程會(huì)使系統(tǒng)開發(fā)面臨一 些新問題,要求設(shè)計(jì)人員具備軟硬件方面的綜合知識(shí),才能正確進(jìn)行系統(tǒng)調(diào)試和排錯(cuò)。 <BR> 當(dāng)然,如果擁有專用的嵌入式系統(tǒng)開發(fā)工具,設(shè)計(jì)工作便要省勁些。它們通常配 有定位程序和可供設(shè)計(jì)者修改的啟動(dòng)程序樣板,有些還能通過串口或并口,在PC機(jī) 上聯(lián)機(jī)調(diào)試程序,甚至有源級(jí)代碼調(diào)試功能。利用工控機(jī)來設(shè)計(jì)系統(tǒng),事情就更簡(jiǎn)單。 不過,專用開發(fā)工具和工控機(jī)價(jià)格昂貴,因此許多人在設(shè)計(jì)嵌入式系統(tǒng)時(shí)選擇自己編 寫定位程序和啟動(dòng)程序,甚至編寫可嵌入的I/O庫函數(shù)。本文就嵌入式系統(tǒng)的程序 設(shè)計(jì)方法及設(shè)計(jì)中可能遇到的問題作些討論,供打算設(shè)計(jì)嵌入式程序的讀者參考,有關(guān)編寫定位程序和啟動(dòng)程序的具體方法將另文介紹。 </P><P> <BR> 2 嵌入式程序的定位 <BR> 2.1。牛兀盼募袷胶停模希又囟ㄎ <BR> DOS下的EXE文件是一種可重定位文件 (Re-locatableFile),它由重定位標(biāo)頭和裝入模塊組成。后者含 一段或幾段程序代碼,段數(shù)與類型取決于程序規(guī)模和編譯時(shí)所用的內(nèi)存模式,然后是 初始化與未初始化的數(shù)據(jù)及堆棧,還可能有程序排錯(cuò)信息。代碼、數(shù)據(jù)和堆棧段地址 均是參考到程序開頭的相對(duì)地址。標(biāo)頭放在裝入模塊之前,含若干定位控制信息和一 張定位表?刂菩畔ǎ牛兀盼募笮、標(biāo)頭長(zhǎng)度、需要重定位的項(xiàng)數(shù)和位置、裝 入模塊的開頭和堆棧的相對(duì)地址等。定位表是一組形式為段址:偏址的遠(yuǎn)指針,指示 裝入模塊中要重定位的那些段址相對(duì)于模塊開頭處的位置。裝進(jìn)RAM后,加載程序 建立起程序段前綴PSP,并根據(jù)系統(tǒng)當(dāng)前可用RAM地址修改這些段址,對(duì)裝入模 塊重定位,使程序中所有參考絕對(duì)地址的量正確指向模塊裝入后的起始地址,然后執(zhí) 行(圖1)。因此它可在RAM中的任何位置上執(zhí)行。圖。模希訉(duì)EXE文件的定位過程 <BR> 2.2 嵌入式程序的定位 <BR> 嵌入式系統(tǒng)有ROM和RAM兩類內(nèi)存,程序被固化進(jìn)ROM,而程序 變量和堆棧應(yīng)設(shè)在RAM中。因此,對(duì)EXE文件的重定位過程與DOS下不一樣。定位程序必須根據(jù)系統(tǒng)的ROM和RAM地址,對(duì)定位表中各遠(yuǎn)指針指向的字進(jìn)行修改。定位程序最后以一種可加載進(jìn)測(cè)試系統(tǒng)或 <BR> 可燒入EPROM的形式輸出程序,即ROM圖,它可以是二進(jìn)制或Intel的HEX格式,根據(jù)EPROM編程器、仿真器或調(diào)試程序的要求而定。 <BR> 可用兩種方法把EXE文件轉(zhuǎn)換為ROM圖: <BR> 一是使用EXE2BIN命令。若EXE文件定位表中不含有定位遠(yuǎn)指針,EXE2BIN便將它轉(zhuǎn)換成COM文件,它是可固化進(jìn)EPROM的二進(jìn)制文件,否則便放棄轉(zhuǎn)換。這僅適用于較小的單段程序。較新版本的EXE2BIN在發(fā)現(xiàn)EXE文件中含重定位項(xiàng)時(shí),會(huì)提示用戶提供一個(gè)基地址,進(jìn)行重定位。若選用適當(dāng)?shù)膬?nèi)存模式,并限制使用遠(yuǎn)指針,它也可能用一個(gè)基地址進(jìn)行定位。但對(duì)于規(guī)模較大的程序,EXE2BIN無能為力。 <BR> 二是根據(jù)標(biāo)頭和MAP文件所提供的信息進(jìn)行定位,適用于所有的EXE文件(圖2)。若在連接時(shí)進(jìn)行限定,可生成只含內(nèi)存分配段表的簡(jiǎn)單MAP文件。段表的每行描述一個(gè)段,按代碼段、數(shù)據(jù)段和堆棧段的次序排列。MicrosoftC和BorlandC的MAP文件每行長(zhǎng)度略有區(qū)別,但行上各參數(shù)(段始址、段末址、段長(zhǎng)、段名、段類)的位置是固定的。 定位程序根據(jù)第一個(gè)RAM段的段名,從MAP文件中抽取出它的起始地址,它就是數(shù)據(jù)區(qū)的相對(duì)始址。再?gòu)臉?biāo)頭內(nèi)容計(jì)算出裝入模塊大小,即要占用的ROM容量。將系統(tǒng)ROM始址加上代碼段在裝入模塊中的 <BR> 相對(duì)地址,便得到程序開始執(zhí)行的地址。然后,對(duì)定位指針進(jìn)行自小到大排序。根據(jù)各段的始末地址逐段析出段址,并從裝入模塊中讀入該段代碼或數(shù)據(jù)。接著按定位指針順序考察待定位的段址,若它落在該段范圍內(nèi),便進(jìn)行定位操作,即把此段址修改成實(shí)際的ROM或RAM地址。直到將屬于這個(gè)段的定位指針全部處理好后,便把這段內(nèi)容寫到輸出文件。對(duì)所有段都進(jìn)行定位后,便獲得ROM圖。 圖2 80x86系統(tǒng)上嵌入式程序的定位過程 </P><P> 3 啟動(dòng)程序 <BR> ROM中程序執(zhí)行前,先要在RAM中建立堆棧和數(shù)據(jù)區(qū)。串?dāng)?shù)據(jù)等常數(shù)與程序一起固化在ROM中,程序可以訪問它們,但RAM的存取速度比E-PROM高,因此也被復(fù)制進(jìn)RAM,以提高讀出速度。還需要建立C程序運(yùn)行的環(huán)境,如對(duì)段寄存器和堆棧指針初始化、對(duì)靜態(tài)變量和RAM區(qū)清零、建立堆(heap)等。程序運(yùn)行前還應(yīng)設(shè)置必要的中斷矢量,并讓各未用中斷指向一個(gè)只含RET指令的啞函數(shù),以防止錯(cuò)誤中斷引起系統(tǒng)的混亂。此外,還要對(duì)系統(tǒng)硬件進(jìn)行初始化,并根據(jù)具體的系統(tǒng),加入出錯(cuò)時(shí)中止程序或重啟動(dòng)的程序段等。這些工作都由用匯編語言編寫的啟動(dòng)程序完成。啟動(dòng)程序是嵌入式程序的開頭部分,應(yīng)與應(yīng)用程序一起固化在EPROM 中,并首先在系統(tǒng)上運(yùn)行(圖2)。它應(yīng)包含進(jìn)各模塊中可能出現(xiàn)的所有段類,并合理安排它們的次序。當(dāng)它作為第一個(gè)模塊和應(yīng)用程序等一起連接時(shí),LINK將按照該次序歸并類名相同的段。 <BR> 寫好啟動(dòng)程序是設(shè)計(jì)好嵌入式程序的關(guān)鍵。各類C編譯均提供自己的啟動(dòng)程序模塊(C0.ASM),可以此為樣板,經(jīng)簡(jiǎn)化和修改形成適用本系統(tǒng)的啟動(dòng)程序,也可以先搭一個(gè)啟動(dòng)程序骨架,再逐步完善。 <BR> 4 嵌入式程序的運(yùn)行 <BR> 嵌入式系統(tǒng)大多不能從鍵盤接受命令,而要在系統(tǒng)通電或復(fù)位時(shí),自動(dòng)執(zhí)行ROM中的程序。各系統(tǒng)的復(fù)位地址不盡相同,以工作在實(shí)模式的80x86嵌入式系統(tǒng)為例,CPU復(fù)位后將執(zhí)行F000:FFF0H處的代碼。這是系統(tǒng)ROM的高址端,僅有16字節(jié)空間,設(shè)計(jì)者可用DEBUG命令在ROM圖的這個(gè)位置上,放一條無條件遠(yuǎn)跳轉(zhuǎn)指令JMPFARPTRstart,轉(zhuǎn)到ROM開頭,從那里執(zhí)行啟動(dòng)程序(見圖2)。啟動(dòng)程序完成上述的初始化后調(diào)main函數(shù),執(zhí)行應(yīng)用程序。 80286以上的CPU復(fù)位時(shí),CS:IP初值仍是F000:FFF0H。但 <BR> A20以上地址線在CS寄存器被第一次裝進(jìn)新的內(nèi)容前,一直保持高電平,即開始地址指向最高地址端。如只要求系統(tǒng)工作在實(shí)模式,可由譯碼電路將開始的高地址反射到低端的1MB空間,復(fù)位矢量仍是F000:FFF0H。當(dāng)上述JMP指令一 執(zhí)行,CS被改寫,A20以上地址線將變低而進(jìn)入實(shí)模式。要是希望啟動(dòng)后進(jìn)入保護(hù)模式,就不需要進(jìn)行地址反射,但是相應(yīng)的復(fù)位地址上只能放一條近跳轉(zhuǎn)指令,保證不改變CS值。然后進(jìn)行必要的初始化,盡快進(jìn)入保護(hù)模式。 </P><P> <BR> 5 嵌入式程序的編譯和連接 <BR> 綜上所述,設(shè)計(jì)嵌入式系統(tǒng)時(shí)要在PC機(jī)上編寫三個(gè)程序:應(yīng)用程序MYPROG.C;定位程序LO-CATOR.C;啟動(dòng)程序STARTUP.ASM。然后按以下步驟進(jìn)行編譯和連接,生成可編程的ROM圖: <BR> ·將應(yīng)用程序編譯成MYPROG.OBJ。 <BR> ·將定位程序編譯和連接成可執(zhí)行程序LO-CATOR.EXE。 <BR> ·將啟動(dòng)程序編譯成STARTUP.OBJ。 <BR> ·對(duì)STARTUP.OBJ、MYPROG.OBJ及必要的庫函數(shù)進(jìn)行連接,生成EMBED.EXE和簡(jiǎn)化的MAP文件EMBED.MAP。STARTUP 必須是LINK行上的第一個(gè)模塊,保證它先執(zhí)行。 <BR> ·執(zhí)行LOCATOR.EXE,以EMBED.EXE、EMBED.MAP、第一個(gè)RAM段的段類名、RAM和ROM始址為輸入?yún)?shù),實(shí)現(xiàn)定位,輸出ROM圖EMBED.BIN。 <BR> ·用DEBUG命令在EMBED.BIN的F000:FFF0H位置上加進(jìn)指令JMPFARPTRstart,形成最終的ROM圖。 </P><P> <BR> 6 其它幾個(gè)問題 <BR> 6.1 系統(tǒng)內(nèi)存考慮 <BR> 為確保正確復(fù)位,設(shè)計(jì)硬件時(shí)要讓ROM地址空間覆蓋復(fù)位矢量。例如8086系統(tǒng)的最高地址為F000:FFFFH,若采用128KB的ROM,其地址范圍應(yīng)。牛埃埃埃海埃埃埃埃疲埃埃埃海疲疲疲疲取 RAM地址則應(yīng)從0開始,由于開頭1KB字節(jié)RAM要保留給中斷矢量表,通常如圖2那樣將RAM數(shù)據(jù)區(qū)設(shè)在地址0040:0000H處。 <BR> 常數(shù)先固化在ROM中,然后被復(fù)制進(jìn)RAM,因此占用的存儲(chǔ)器空間是DOS下的兩倍?稍诔绦蛟O(shè)計(jì)中設(shè)法限制要復(fù)制進(jìn)RAM的常數(shù)數(shù)量。例如,系統(tǒng)若支持CRT顯示器,可能需要在屏幕上顯示各種消息和菜單提示。這時(shí),可把所有顯示函數(shù)和有關(guān)文本串放進(jìn)一個(gè)模塊,再用指針來存取它們。比如,本來可用下面語句打印提示: <BR> 。穑颍椋睿簦妫"PressStoStart"); <BR> printf("PerssQtoQuit"); <BR> 若程序中有許多類似的語句,便可能存在較多重復(fù)串。要是對(duì)各子串都用指針訪問,編譯就會(huì)把其中重復(fù)的串(如Press,to等)合并,省下不少內(nèi)存空間。即把上面語句改為: <BR> printf("%s%s%s%s","Press","S","to","Start") ; <BR> printf("%s%s%s%s","Perss","Q","to","Quit"); </P><P> 6.2 標(biāo)準(zhǔn)I/O函數(shù)的使用 <BR> 用C語言編寫嵌入式程序的過程與DOS下一樣,只是要避免使用不能被固化到 ROM中的庫函數(shù)。在DOS下,許多低級(jí)I/O函數(shù)(如putch,getch) 均通過DOS中斷21與硬件接口,高級(jí)函數(shù)printf,scanf等也使用該中斷。若希望在無ROMBIOS的系統(tǒng)上使用這些函數(shù),應(yīng)編寫一個(gè)模仿 DOSINT21的函數(shù),這樣便能使用除磁盤I/O函之外的大多數(shù)標(biāo)準(zhǔn)I/O 函數(shù),縮短程序開發(fā)時(shí)間,并保證較好的可移植性。當(dāng)然,如果使用的是現(xiàn)成的嵌入式系統(tǒng)開發(fā)軟件包,廠商將告知哪些函數(shù)可被固化進(jìn)ROM,不必自己編寫INT21函數(shù)。 <BR> 編寫嵌入式支持函數(shù)時(shí)要防止使用與DOS有關(guān)的庫函數(shù)。比較起來,BC提供 的庫比MSC的更獨(dú)立于DOS。例如,MSC的printf函數(shù)要依賴幾個(gè)低級(jí) 的DOS函數(shù)。所以在仿真INT21的控制臺(tái)I/O函數(shù)時(shí),建議用BC的 printf函數(shù)。 <BR> 6.3 配置參數(shù)的保護(hù) <BR> 斷電時(shí),嵌入式系統(tǒng)應(yīng)能保持那些用于系統(tǒng)恢復(fù)或外設(shè)配置的數(shù)據(jù),可用電池供 電的RAM或EEPROM來存放它們。但在復(fù)位時(shí),啟動(dòng)程序要把有初值的變量復(fù) 制進(jìn)RAM,并對(duì)其余RAM區(qū)清0,結(jié)果會(huì)清除應(yīng)保持的數(shù)據(jù)。為此,可把這類數(shù)據(jù)歸入一個(gè)專門段,不包括在初始化和未初始化數(shù)據(jù)區(qū)中,不讓啟動(dòng)程序修改它們。<BR>
|
|
狀 態(tài):
離線
公司簡(jiǎn)介
產(chǎn)品目錄
|
|
公司名稱:
|
中華工控網(wǎng)
|
聯(lián) 系 人: |
客服中心
|
電 話: |
0755-26546361
|
傳 真: |
0755-26585268 |
地 址: |
深圳市南山區(qū)創(chuàng)業(yè)路現(xiàn)代城華庭1棟6A |
郵 編: |
518054 |
主 頁: |
|
|
|
|
|