<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 嵌入式系統(tǒng)集成開發(fā)平臺的設計與實現

          嵌入式系統(tǒng)集成開發(fā)平臺的設計與實現

          作者: 時間:2013-01-15 來源:網絡 收藏

          0引言

          本文引用地址:http://www.ex-cimer.com/article/257186.htm


          嵌入系統(tǒng)開發(fā)已經趨于規(guī)范化,但是嵌入式系統(tǒng)的開發(fā)并不像在普通PC機上進行軟件開發(fā)那樣容易,它同樣需要一個高度集成的開發(fā)平臺,來降低開發(fā)的難度。目前市場上的嵌入式系統(tǒng)集成開發(fā)平臺特點是: ( 1)多數嵌入式系統(tǒng)集成開發(fā)平臺都是以Windows為系統(tǒng)環(huán)境,很少有以Linux為系統(tǒng)環(huán)境的;( 2)部分集成開發(fā)平臺具有一定的開放性,許多功能作為插件供用戶選擇; ( 3)多數集成開發(fā)平臺通用性較差,僅支持一個或者幾個系列的微處理器; ( 4)目前嵌入式系統(tǒng)集成開發(fā)平臺產品大都價格昂貴; ( 5)很少有集成開發(fā)平臺集成有圖形模塊支持的功能。


          為了解決其它嵌入式集成開發(fā)平臺的缺點,本文研究了嵌入式系統(tǒng)可視化集成開發(fā)平臺, ( Embedded system graphical integrated development environment),其最大特點是具有圖形化人機交互功能和ARM CPU工作方式自動初始化。所謂圖形化人機交互,是指把將要裁剪和配置的系統(tǒng)級軟件(比如bootloader、kernel、通用I /O輸入、輸出等)化整為零,封裝成不同功能的形象化圖形模塊,開發(fā)者根據自己開發(fā)的系統(tǒng)需要,選擇不同圖形模塊,動態(tài)生成bootloader、kernel、I /O等系統(tǒng)級的源代碼,不需要開發(fā)者自己輸入,這大大簡化了開發(fā)步驟,減輕了程序員的負擔,減少了操作的復雜度,提高了開發(fā)效率。另一方面,ARM系列CPU應用比較廣泛,不同型號的CPU在開發(fā)時需要對使用的內部資源進行初始化。傳統(tǒng)的做法是開發(fā)者確定工作方式,確定工作方式字,然后手動編程。我們采用開發(fā)模式是:以定時器應用為例,將定時器的個數,工作方式確定,時鐘頻率的確定,是否允許中斷等編寫成對話框模式,開發(fā)者只要選中其中的方式,初始化控制字自動生成,編寫代碼自動生成,同樣大大簡化了開發(fā)步驟,減輕了程序員的負擔。


          面向對象技術是當前實現軟件模塊化、提高軟件復用性最優(yōu)的方法,現在成為計算機領域中的一種主流技術,本文提出利用面向對象的技術來設計一種IDE,對開發(fā)中的各個對象的類進行分析與設計,架構一個通用的開發(fā)模型,根據硬件配置自動產生基本的系統(tǒng)軟件方案。只需要系統(tǒng)中的每個對象類的屬性及其操作設置,自動搭建交叉編譯環(huán)境,降低操作系統(tǒng)裁減和移植的難度,產生驅動程序的基本框架。開發(fā)人員只需要配置好各個模塊的基本信息,將更多精力集中在系統(tǒng)的應用上。


          1的開發(fā)流程

          與常見的PC和服務器軟件不同,嵌入式軟件主要是對設備內部各部分的運行進行協(xié)調,并不與設備使用者發(fā)生直接接觸。PC和服務器軟件的運行環(huán)境是標準化的,而嵌入式軟件的運行環(huán)境隨電子設備的不同而改變,必須針對不同的電子產品進行專門的設計、開發(fā)和優(yōu)化。由于嵌入式Linux操作系統(tǒng)在嵌入式開發(fā)中占據了主流,因此本文圍繞針對移植有Linux操作系統(tǒng)的嵌入式開發(fā)流程進行討論。


          典型的基于嵌入式Linux操作系統(tǒng)的嵌入式軟件開發(fā)流程如下[1]:( 1)獲取硬件系統(tǒng)的信息:如選取的微處理器體系,Flash型號、網卡型號及其他外設的信息等;( 2)建立交叉編譯工具:一般的GCC工具都是針對X86體系的,為了能夠生產目標板執(zhí)行的代碼必須建立交叉編譯工具;( 3)開發(fā)Bootloader:建立啟動系統(tǒng)的主引導程序;( 4)移植Linux內核:如基于Linux2.6內核移植;( 5)開發(fā)一個根文件系統(tǒng):如rootfs的制作;( 6)開發(fā)特定硬件的驅動程序:如LCD,Keypad等;( 7)開發(fā)上層的應用程序:如QT GUI開發(fā)。


          對于開發(fā)過程的各個環(huán)節(jié),有的提供了輔助的開發(fā)工具,有的需要完全依賴經驗手工從底層開發(fā),嵌入式軟件開發(fā)依然停留在手工作坊式的方式,很難做到工程化管理。本文所設計的IDE將涵蓋整個開發(fā)的各個重要環(huán)節(jié),力求最大程度上降低開發(fā)難度,在集成化開發(fā)環(huán)境里完成主要工作。


          2 IDE面向對象的分析與設計

          對于運行嵌入式Linux操作系統(tǒng)的系統(tǒng),根據其開發(fā)流程,利用面向對象技術分析設計出6個基本的大類,并給出對象之間的協(xié)作關系圖,如圖1、圖2所示。這幾個大類貫穿了嵌入式軟件開發(fā)的重要環(huán)節(jié)。

          圖1嵌入式軟件IDE基本類

          圖2基本對象類的協(xié)作圖

          硬件系統(tǒng)信息類,承載了硬件系統(tǒng)的描述信息,比如選取何種體系的微處理器,處理器的工作頻率設置,采用何種啟動方式,是NandFlash,還是NorFlash或者EPROM等,用戶通過設定這些參數,其他對象將獲取其中的信息進行配置。


          嵌入式開發(fā)需要交叉編譯,Linux環(huán)境下一般就是采用開源Gcc系列進行配置,環(huán)境搭建類管理交叉編譯鏈的源代碼,根據體系架構的信息自動生成運行腳本,在制定目錄下生成完整的交叉編譯鏈,這是嵌入式開發(fā)的基礎。


          工程管理類,集成開發(fā)環(huán)境的主要目的就是同一組織文檔,省卻人工管理,自動編譯運行源碼,其中包含了文件操作,組織好源代碼之間的關系,利用make技術進行編譯,牽扯到大量全局環(huán)境參數的設定。


          引入控制字庫類是方便部分程序的編寫,比如Bootloader類需要對處理器初始化,基本的驅動控制器進行操作,其中包含了匯編指令級別和C語言的操作,開發(fā)人員往往需要對參考手冊熟練掌握,大大降低了開發(fā)效率??刂谱謳毂M量包含了常見的處理器系列的寄存器控制字庫,只需選擇某個具體功能,便可產生需要的指令源碼。同樣驅動程序開發(fā)中,也是頻繁利用了C語言對寄存器進行操作。


          系統(tǒng)移植類涵蓋了整個系統(tǒng)需要移植的模塊,引導程序,操作系統(tǒng)內核和文件系統(tǒng),各類封裝了大量繁雜的細節(jié)內容,盡量以最簡化形式幫助開發(fā)人員完成操作,重要的環(huán)節(jié)只需設定參數,其他交由對象自動執(zhí)行。


          面向對象最重要的特征就是“高內聚度和低耦合性”,各個對象封裝了細節(jié)操作,只需要有限的外部接口交換信息,這種柔性思想最大程度上提高了軟件的復用性。本文所設計的IDE,根據體系結構的不同,所需修改的只是個別對象的內部數據和操作,整體架構不受任何影響[2,3]。


          圖3給出了面向對象嵌入式集成開發(fā)平臺的結構。

          圖3面向對象的嵌入式集成開發(fā)平臺結構框圖

          3系統(tǒng)的具體實現

          目前可視化的面向編程語言種類比較多,從對面向對象技術的支持程度上來說,微軟最新的VC#從封裝性、類型安全性方面相當強大。重要的是,類層次清晰,編碼容易,可以根據面向對象設計的框架輕松的進行轉換,卻和C ++一樣強大。所以本文利用VC#設計了嵌入式軟件IDE,對各個類編寫詳細代碼。


          整個系統(tǒng)基本架構如圖4所示。

          圖4 IDE的系統(tǒng)架構圖

          集成開發(fā)環(huán)境運行于Windows平臺下,但需要Linux的強大命令集,在此,本文提出了Cygwin技術來模擬Linux運行環(huán)境,從而使得IDE的底層得到強大的各種命令支持,可以運行各種腳本文件。此技術屬于開源項目,安裝后需個別地方的細節(jié)修改。


          交叉編譯工具鏈模塊是IDE設計的核心,開發(fā)一個實用的編譯器,需要花費大量的人力物力和財力,其可靠性也要經受時間的考驗。幸運的是,GNU提供了免費的、功能強大的GCC工具鏈,它不僅可以編譯Linux操作系統(tǒng)下的應用程序以及Linux內核,而且還是一款交叉編譯器,支持ARM、PowerPC、x86、Intel960、M68等幾乎所有知名的CPU廠家,而且國外大多數集成開發(fā)工具都從GCC移植而來。


          本文的交叉編譯工具鏈模塊并不是單獨的針對某個體系結構,可以重定向,根據參數配置,生成某個系列的編譯工具,如圖5所示。

          圖5交叉工具鏈模塊

          軟件設計的一個重要環(huán)節(jié)就是,要組織好源代碼之間的關系,編譯連接,這就要用到工程化的手段去管理源碼。這是IDE設計中的橋梁。


          本文利用的Makefile技術對整個工程進行管理,主要就是針對驅動程序和應用程序的組織和編譯。Makefile是Linux工程管理的一項成熟的技術,有一套完整的規(guī)則,只需要按照規(guī)則去編寫Makefile文件,然后由make命令去解釋執(zhí)行。Cygwin中集成了Gnumake,因此只要編寫好Makefile文件,只需一個make命令,就可以完成所有的編譯連接工作,如圖6所示。

          圖6工程管理模塊

          大多數的IDE都有這個命令,比如: Delphi的make,Visual C + +的nmake,Linux下GNU的make.可見,makefile都成為了一種在工程方面的編譯方法。


          一個關鍵技術就是顯示信息重定向到IDE指定的輸出窗口,各種腳本運行信息都是標準控制臺輸出,因此需要將編譯中的標準信息和錯誤信息進行重定向。通常是靠管道技術來解決這個問題,但嵌入式開發(fā)中許多編譯過程長達數小時,信息往往需要進程結束才能完全顯示。本文IDE則采用了管道技術加異步式讀取技術,使得重定向和信息顯示同時進行,及時反饋編譯過程中的各種信息。


          Bootloader是嵌入式系統(tǒng)的引導加載程序,它的作用是初始化必要的硬件設備,創(chuàng)建內核需要的一些信息并將信息通過相關機制傳遞給內核,從而將系統(tǒng)的軟硬件環(huán)境帶到一個合適的狀態(tài),最終調用操作系統(tǒng)內核,真正起到引導和加載內核的作用[5]。


          Bootloader依賴于硬件實現,除了體系結構,還依賴于具體的嵌入式板級設備的配置,因此Bootloader是嵌入式開發(fā)移植最困難的部分,一般來說都是將已有的代碼進行大量的修改,本文采用的是U-Boot 1.2.0,目前來說是比較通用的Bootloader.如圖7所示,針對這部分移植,為了最大程度上幫助用戶完成代碼的修改,IDE提供不同類型的體系架構需要修改的源碼的提示信息,以及某種配置下需要修改的提示信息,需要建立一個幫助文件數據庫。通過控制字庫模塊添加需要的源碼。其實一般來說,修改都是大同小異,最主要的是修改兩個方面,何種方式啟動,是Nadflash還是Norflash,如果是Nandflash啟動,需要定義芯片配置函數,增加Nandflash拷貝數據到內存的代碼。


          還有就是為了利用tft協(xié)議燒錄內核到flash,需要針對某種網卡芯片進行修改。

          圖7 Bootloaer移植模塊

          簡單來說,內核配置無非就是生成一個配置文件,由Makefile來讀取,不同的架構,就會選擇不同架構目錄下的源碼。但是內核配置比較繁雜,一般人員很難理清源碼之間的關系,配置不好,不僅無法編譯,即使勉強編譯成功,也未必能夠正常運行。


          而且,內核不單單是配置問題,還有部分源碼根據需要必須修改,比如如果是Nandflash作為存儲器,需要建立Nandflash分區(qū)表。


          對于內核配置,本文IDE提供利用模板來進行二次配置,建立模板數據庫,根據用戶的參數設定,提供符合條件的模板,如果模板基本符合要求,就可以利用模板進行編譯,如果需要細節(jié)的修改,則調用內核配置工具來進行配置,內核配置工具利用make xconfig形式,產生圖形化界面,當然需要X系統(tǒng)的支持,需要在Cygwin中安裝、修改。


          對于內核源碼修改,則需要幫助文件數據庫,根據用戶參數設置,產生需要的源碼,添加到內核中去。如圖8所示。

          圖8內核移植模塊

          根文件系統(tǒng)是Linux /Unix系統(tǒng)啟動的一個重要組成部分,也是操作系統(tǒng)正常工作時候的必要組成部分,在啟動時候內核需要跟文件系統(tǒng)來掛載。在現代Linux操作系統(tǒng)中,內核代碼影像文件保存在根文件中,系統(tǒng)引導啟動程序會從這個根文件設備商把內核代碼加載到內存中取運行。如圖9所示。

          圖9根文件制作模塊

          嵌入式根文件系統(tǒng)有RomFS,JFFS2,NFS,EXT2,RAMDISK,Cramfs等,每個系統(tǒng)都有自己的特點,最常用的就是Cramfs文件系統(tǒng),Cygwin工具集中提供了Cramfs工具,mkcramfs.嵌入式根文件的最底層目錄中,都有其具體的用途和目的,因此必須建立最基本的根目錄。而且一些根目錄下必須有固定的文件,如/bin,/ sbin,/ usr /bin,/ usr /sbin需要放置Linux命令工具,/ etc目錄下需要系統(tǒng)配置文件,包括啟動文件。因此,本模塊要完成這么幾個功能,提供必須的根目錄,根目錄下的文件,將根目錄制作成某種跟文件系統(tǒng),本文暫時提供Cramfs文件系統(tǒng)。嵌入式Linux命令工具集由BusyBox工具提供,它包含了很多標準Linux工具的單個可執(zhí)行實現,本文的IDE提供了一個BusyBox的標準配置,只需要利用交叉工具鏈進行編譯。


          4嵌入式微處理器內部資源驅動

          嵌入式微處理器有大量的內部I /O接口資源,如定時計數器、中斷、DMA、開關量輸入輸出等,要選擇其中的接口應用,首先要進行初始化,編寫驅動程序。


          驅動程序編寫模塊和應用程序編寫模塊只要提供一個文本編輯器,利用工程管理部分去組織源碼進行編譯就可以。對于驅動程序的編寫,Linux驅動程序都有一套固定的模式,比如字符型、塊型、網絡型數據結構都有區(qū)別,但每種類型的驅動程序架構都一樣。另外驅動程序編寫中最重要的就是根據每個接口資源確定的工作方式確定控制字,即使開發(fā)人員對某個體系下的各類CPU內部資源的控制字十分熟悉,也要經常參考手冊才能準確無誤。


          本文提出了驅動程序編寫模式,一個是選擇類型,自動生成某種類型的模板,在此模板上進行添加修改;第二就是利用控制字模塊,在開發(fā)驅動程序過程中,開發(fā)人員可以選擇某個體系結構下的針對某種具體寄存器的操作,然后會自動產生必要的代碼,如圖10、圖11所示,只需要將代碼嵌入到驅動程序源碼中。


          圖10是定時器的選擇界面,開發(fā)者只要根據需求選擇相應的定時器,確定其功能,初始值,然后選擇確認按鈕,初始化代碼自動生成,如圖11包含初始化控制字,非??旖?、便利。另外,如果驅動程序要添加到內核去,重新重新配置內核即可。

          圖10定時器及其功能選擇界面

          圖11自動產生初始化代碼界面

          5結語

          本開發(fā)平臺具有友好的用戶界面、文本編輯器、工程管理工具、交叉編譯器、燒錄和下載工具、圖形化模塊支持。本集成開發(fā)平臺可以供學生、老師或者工程技術人員學習嵌入式linux的裁剪和移植,ARM系列CPU的開發(fā)和應用。


          利用本文研究的嵌入式軟件IDE,針對ARM系列的2410平臺進行了U-Boot、Linux2.6內核、根文件系統(tǒng)的配置和移植,編寫出基本的網卡驅動程序,測試取得成功。

          linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)

          c語言相關文章:c語言教程


          linux相關文章:linux教程


          塵埃粒子計數器相關文章:塵埃粒子計數器原理


          評論


          相關推薦

          技術專區(qū)

          關閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();