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

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 復雜的實時嵌入式系統(tǒng)的調(diào)試

          復雜的實時嵌入式系統(tǒng)的調(diào)試

          作者:ADI公司供稿 時間:2008-04-15 來源:電子產(chǎn)品世界 收藏

            隨著的復雜程度不斷提高,低效率的方法的成本日益增加。鑒于當前嵌入式應用的復雜性還有繼續(xù)上升的趨勢,對這些系統(tǒng)的將成為加速產(chǎn)品上市和提供魯棒性最終產(chǎn)品的關(guān)鍵因素。隨著應用對多線程和中斷嵌套的使用,開發(fā)商的大部分時間目前都花在上。應用的屬性使得將伴隨同時發(fā)生多個事件的故障問題孤立起來變得更為困難。本文將討論常見的調(diào)試問題以及預防和檢查這些故障問題的一些方法。

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

            從歷史角度上來看,嵌入式應用代碼的調(diào)試流程可以分為兩類。第一類調(diào)試流程是回答 “我的代碼現(xiàn)在執(zhí)行到哪里?” 的問題。當開發(fā)商依靠打印語句或者LED的閃爍來指示應用程序執(zhí)行到某個節(jié)點的調(diào)試方法時,往往就屬于這種情形。如果開發(fā)工具支持這種調(diào)試方法,可以沿著應用程序執(zhí)行的路徑插入斷點。第二類調(diào)試流程是幫助回答“我看到的數(shù)據(jù)是從哪里來的?”這一問題。在這種情況下,人們往往依靠寄存器顯示窗口觀察變量信息、處理器內(nèi)存的內(nèi)容。人們還可以嘗試單步執(zhí)行,并且觀察所有這些數(shù)據(jù)窗口以了解某個寄存器狀態(tài)何時出現(xiàn)錯誤,內(nèi)存位置何時得到錯誤的數(shù)據(jù),抑或指針何時出現(xiàn)了誤用。

            當開發(fā)商寫完全部代碼后,如果無需了解網(wǎng)絡基礎(chǔ)設施,也沒有操作系統(tǒng)的任務調(diào)度需要考慮,那么就可以利用這些調(diào)試方法使一個應用程序運行起來。然而,現(xiàn)在的情況并非如此。嵌入式處理器以超過600 MHz的速度運行,并且擁有可支持Ethernet和USB等協(xié)議的嵌入式外設,支持功能齊備的操作系統(tǒng),例如mClinux,而且這些操作系統(tǒng)所調(diào)度的各種應用程序是由數(shù)千行代碼構(gòu)成。使用打印語句和利用LED來調(diào)試是不現(xiàn)實的,因為現(xiàn)在常常有如此之多的功能在執(zhí)行是不可能的,或者它們會影響標準I/O口,從而造成處理器性能大幅度下降。

            軟件最常見的調(diào)試問題可以大致劃分為如下幾類:

            1. 同步問題;

            2. 內(nèi)存和寄存器訛誤;

            3. 與中斷相關(guān)的問題;

            4. 編譯器問題;

            5. 異常情況。

            下文對上述問題作簡要介紹。

            同步問題

            在任何系統(tǒng)中,只要有多串序線程或者進程運行,而且是異步共享數(shù)據(jù),則系統(tǒng)必然存在同步問題。對于共享數(shù)據(jù)的全部操作必須是順序化的,也就是說,只有在一個線程或者進程完成對數(shù)據(jù)的操作后,其它的線程才能對數(shù)據(jù)進行操作。

            以圖1為例,線程A和線程B對共享變量“counter”進行操作,A讓counter 增加,而B則讓counter減少。下方示出了線程A的counter++和線程B counter—的匯編代碼。假設線程B的優(yōu)先級要高于線程A,而線程A目前正在運行,則線程B將被阻止。

            舉例來說,假設初始的計數(shù)值是2,而線程A是執(zhí)行線程。則線程A讀入計數(shù)值,并送入一個寄存器,在使其增加一個增量后,再將其寫回計數(shù)器變量上。

            在可搶先的多線程系統(tǒng)中,高優(yōu)先級的線程的執(zhí)行可以搶先于低優(yōu)先級的線程。如果數(shù)據(jù)被一個線程和中斷例程共享,也會出現(xiàn)上面的問題,因為中斷的執(zhí)行與線程的執(zhí)行之間是異步關(guān)系。

            同步化方面的問題常常是很難進行調(diào)試的,因為它們?nèi)Q于時序,是隨著軟件對數(shù)據(jù)的操作而隨機出現(xiàn)的。幸運的是,大多數(shù)的實時操作系統(tǒng)可以提供同步化原語。開發(fā)商 可以使用最適當?shù)臋C制來保護共享數(shù)據(jù),而不至于影響系統(tǒng)的性能。如果數(shù)據(jù)在多個線程之間共享,則開發(fā)商將有如下的選擇:

            a. 關(guān)閉調(diào)度器以便當前的線程永遠不會被其它線程搶先;(無調(diào)度區(qū))

            b. 使用信號量(Semaphore)或者互斥信號量(Mutex)來保護共享數(shù)據(jù);

            c. 利用關(guān)鍵區(qū)域來進行保護,即屏蔽所有的中斷。

            調(diào)試的一個小竅門就是,如果共享的數(shù)據(jù)被破壞,則編程者就應當首先檢查出任何一種多個線程或者中斷對共享數(shù)據(jù)同時進行的操作。如果線程和中斷共享了數(shù)據(jù),那么在線程代碼中必須將中斷關(guān)閉。如果數(shù)據(jù)在多個中斷例程之間共享的話,則中斷也應當被關(guān)閉,因為高優(yōu)先級的中斷可以搶先于低優(yōu)先級的中斷。



            另外一個同步化問題則與線程優(yōu)先級的不恰當?shù)姆峙溆嘘P(guān)。應當確保系統(tǒng)的初始化線程在引導時間內(nèi)就啟動,并在生成其它的優(yōu)先級更高的線程之前,完成整個系統(tǒng)的初始化。

            內(nèi)存和寄存器的數(shù)據(jù)訛誤

            大多數(shù)的都采用了平面化的內(nèi)存模式,也沒有內(nèi)存管理單元(MMU),因而沒有硬件支持的內(nèi)存保護機制。即使采用能提供這種功能的處理器,也需要由開發(fā)商來實現(xiàn)對某些內(nèi)存區(qū)域的保護。進程和線程將對其它進程和線程的內(nèi)存空間有完全的訪問權(quán)限。這可能會造成下面所描述的、各種類型的內(nèi)存訛誤問題。

            堆棧溢出運行時堆棧是在函數(shù)調(diào)用進程中所使用的一種暫存空間,用于存儲局部變量。硬件寄存器指針(SP)將跟蹤堆棧指針的地址。如果你在高級的語言中編程,如C語音,則編譯器所生成的代碼將使用與C語言運行時間模型相一致的堆棧。運行時間模式定義了變量是如何存儲在堆棧中的以及編譯器將如何使用堆棧。局部的變量被放置在當前的堆棧中。圖2給出的例子描述在堆棧上采用的某些關(guān)鍵性的內(nèi)存。



            當堆棧指針超出了所指定的邊界時,就會出現(xiàn)堆棧溢出。這將造成內(nèi)存的訛誤,并最終造成系統(tǒng)的失效。在上述的實例中,如果總的堆棧內(nèi)存區(qū)不足以容納所有的局部變量,堆棧溢出就會發(fā)生。

            調(diào)試的一個技巧就是,如果你擔心溢出,一個好的辦法就是將堆棧安排在內(nèi)存邊界上,這樣,如果在調(diào)試過程中出現(xiàn)了溢出,則仿真器將觸發(fā)一個硬件異常提示。

            有些實時操作系統(tǒng)可能會提供調(diào)試功能,例如保護位可以形成對堆棧溢出的防護。這些操作系統(tǒng)要么記錄關(guān)于堆棧溢出的錯誤信息,要么提交一個異常報告,以便動態(tài)地增加堆棧。最起碼當前的大多數(shù)實時操作系統(tǒng)都能報告堆棧以及已經(jīng)被線程和進程所采用的堆棧的情況。
          在任何中斷驅(qū)動的系統(tǒng)中,堆棧的分配方式都必須考慮到中斷服務例程所采用的空間。如果中斷例程的設計目標是使用當前的執(zhí)行對象棧,則在這種情況下,每一個線程或進程所擁有的最小的堆棧尺寸都應大于或者等于執(zhí)行對象所要求的堆棧尺寸加上所有中斷例程累積起來所需要的最大的堆棧尺寸。

            嵌入式系統(tǒng)開發(fā)商必須掌握各種應用鏈接庫。例如,第三方的庫可能會認定堆棧上為其提供了空間。

            與中斷相關(guān)的問題

            在嵌入式系統(tǒng)中,一般情況下,出于性能方面的考慮,中斷服務例程是以匯編形式編寫的。中斷本質(zhì)上是異步的,在應用執(zhí)行中的任何時刻都有可能出現(xiàn)。匯編層次上的中斷例程最常見的問題,是寄存器的訛誤。在中斷服務例程中所采用的寄存器所存儲的數(shù)據(jù),在寄存器被使用之前都必須被保存,而在從中斷服務例程返回之前,這些數(shù)據(jù)將被恢復。開發(fā)商必須了解狀態(tài)寄存器的情況,而任何一種ALU的操作都會改變其狀態(tài)。在這種情形下,ISR應該保存其狀態(tài)并進行恢復,仿佛它是一個已被使用的寄存器一般。

            如果中斷例程是用C語言編寫 的,它們的開發(fā)也是為了使用當前的堆棧,則開發(fā)商就應該針對堆棧溢出情況進行防護,即每個線程都應該擁有足夠多的堆棧,來滿足中斷或者嵌套的中斷堆棧的要求。最好的做法,就是讓中斷例程的規(guī)模盡可能小,推遲處理過程,交給一個線程或者優(yōu)先級較低的中斷。在開發(fā)過程中,開發(fā)商可以在中斷的開始和結(jié)束部分添加診斷功能,對基礎(chǔ)的架構(gòu)中的寄存器的狀態(tài)進行比較。

            中斷嵌套可以讓一個高優(yōu)先級的中斷搶先于低優(yōu)先級的中斷例程執(zhí)行。開發(fā)商應該考慮到堆棧要求的峰值,并為其分配充足的空間(考慮最差的情況,即系統(tǒng)中的每一個中斷都被一個優(yōu)先級更高的中斷所搶先)。

            有時,某些函數(shù)是以匯編語言編寫的,將被C函數(shù)所調(diào)用。如果匯編代碼并未按照C函數(shù)運行時間調(diào)用規(guī)范來編寫,即按照編譯器所要求的那樣進行,則會導致參數(shù)傳遞無效和訛誤。

            編譯器的問題

            編譯器的優(yōu)化,即使實現(xiàn)了邏輯上的正確性,有時也仍然會造成故障。采用低水平的設備驅(qū)動器時,這一問題特別關(guān)鍵。重排指令是實現(xiàn)更高性能的常用方法,因為處理器常常支持單個周期內(nèi)執(zhí)行多條指令。因此,編譯器將試圖調(diào)度指令,使得所有的指令時間片都得到充分的利用,即使這意味著在寄存器使用前很久就載入數(shù)據(jù),或者在數(shù)值被計算完畢后很久,也讓內(nèi)存保持載入的數(shù)據(jù)。

            例如,假設一個設備必須在向其發(fā)任何指令前就完成初始化。編譯器可能會移動指令位置,以便改善性能。這可能會造成設備的故障。如果設備驅(qū)動器調(diào)試后的版本是可行的,而采用經(jīng)過優(yōu)化的版本時會出現(xiàn)故障,那么你要查看設備的初始化中是否有被移動的指令。

            有時,將代碼從一個架構(gòu)移植到另一種架構(gòu)上,也會帶來某種數(shù)據(jù)類型上的問題。例如,一種架構(gòu)內(nèi)的整數(shù)是32 bit的,而其它的架構(gòu)中是48 bit或者64 bit的。這可能會導致數(shù)據(jù)的失效或者被截斷。

            異常情況所帶來的問題

            如果異常是與程序的執(zhí)行相同步的,則往往是一種不當?shù)牟僮鞯慕Y(jié)果,例如零作為除數(shù)所造成的異常,某些異常則是架構(gòu)所特有的。處理異常的最佳方法是采用缺省的異常處理器,并在出現(xiàn)異常時檢查異常出現(xiàn)的環(huán)境。異常所處的環(huán)境背景是寄存器量值的集合,包括狀態(tài)寄存器。大多數(shù)架構(gòu)將擁有一個指令地址寄存器,用來保存造成問題的指令地址。在多數(shù)情況下,要知道一個異常是如何發(fā)生的并不難,但是,是何種指令路徑可以隔離出這一失效,則是調(diào)試的難點。有些架構(gòu)支持跟蹤,可以看到程序順序執(zhí)行的指令的歷史。

            不能執(zhí)行錯誤檢驗的代碼會造成內(nèi)存的訛誤。由于性能方面的原因,開發(fā)商可能會放棄對錯誤的檢查。跳過錯誤檢查將讓內(nèi)存泄漏等事件無法為人所知,而最終導致內(nèi)存訛誤。某些處理器架構(gòu)就容許應用監(jiān)測數(shù)據(jù)總線的活動,從而能抓住相應事件。

            探尋架構(gòu)特有的功能,大多數(shù)嵌入式處理器都支持某種層次上的調(diào)試功能。內(nèi)置的跟蹤單元就是一種得到硬件支持的跟蹤機制。例如,ADI公司的Blackfin處理器系列就具有硬件跟蹤單元,當硬件跟蹤緩沖器充滿后,就會產(chǎn)生跟蹤異常。使用這種跟蹤單元后,人們可以構(gòu)建出完整的執(zhí)行路徑。免費工具可從http://www.blackfin.org/網(wǎng)站下載。

            觀察點可以讓你監(jiān)測特定的內(nèi)存位置或者內(nèi)存塊區(qū)正在被更改時出現(xiàn)的情況。觀察點可以監(jiān)測內(nèi)部的數(shù)據(jù)總線傳送,如果在觀察點寄存器中,發(fā)現(xiàn)任何匹配的對象,則讓處理器暫停。如果一個特定內(nèi)存位置不斷出現(xiàn)訛誤,則觀察點就非常有用。對內(nèi)存塊區(qū)進行觀察以查看是否有任何正在損毀存儲器數(shù)據(jù)的惡意代碼。大多數(shù)當前的調(diào)試環(huán)境都容許對內(nèi)存和寄存器的內(nèi)容進行修改。有時,修改寄存器的內(nèi)容,可以讓我們洞察何處出現(xiàn)了故障。例如,通過更改程序計數(shù)器,你可以迫使程序在特定函數(shù)出現(xiàn)時恢復執(zhí)行。

            結(jié)語

            總之,由于調(diào)試是開發(fā)過程的最后步驟,因此它將對產(chǎn)品上市時間造成直接的影響。調(diào)試本身也是難以調(diào)度的,因為所發(fā)現(xiàn)的問題在復雜性和可避免性方面都大相徑庭,上面所討論的是一些在嵌入式系統(tǒng)開發(fā)期間常見的問題。這些調(diào)試技巧和提示旨在著重強調(diào)節(jié)省時間,因此在開發(fā)復雜的嵌入式系統(tǒng)時,應用現(xiàn)代的開發(fā)工具和擁有豐富調(diào)試功能的處理器能夠改善投資收益。



          評論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁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); })();