<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è) > 設計應用 > 如何調試復雜的實(shí)時(shí)嵌入式系統?

如何調試復雜的實(shí)時(shí)嵌入式系統?

——
作者:ADI公司 時(shí)間:2007-12-04 來(lái)源:電子產(chǎn)品世界 收藏

ADI公司

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

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

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

  也可能發(fā)生這樣的情況:處理器的工作速度是如此之快,以至于LED的亮滅速度會(huì )快到人眼無(wú)法察覺(jué)。另外現代的嵌入式系統通常支持斷點(diǎn)的設定,但是伴隨這些處理器所運行的代碼數量,使得這種類(lèi)型的斷點(diǎn)調試難以駕馭。中斷和多線(xiàn)程系統在代碼的任何一點(diǎn)上設置一個(gè)斷點(diǎn),可能都無(wú)法指示系統的正確狀態(tài)。由于斷點(diǎn)設置在物理內存的某個(gè)地址上,索引不必了解線(xiàn)程的狀態(tài)。如果使用寄存器顯示方法,那么局部變量窗口和內存窗口都將有助于隔離出所載入的不恰當的量值,但是,由于這些是靜態(tài)化的工具,不能給出有意義的運行中的調試信息,其適用性也常常很有限。

軟件最常見(jiàn)的調試問(wèn)題可以大致劃分為如下幾類(lèi):

  1. 同步問(wèn)題
  2. 內存和寄存器訛誤(corruption)
  3. 與中斷相關(guān)的問(wèn)題
  4. 硬件配置問(wèn)題
  5. 異常情況

同步問(wèn)題
  在任何系統中,只要有多串序線(xiàn)程或者進(jìn)程都在運行,而且是異步共享數據,則系統必然存在同步問(wèn)題。對于共享數據的全部操作必須是原子化的,也就是說(shuō),只有在一個(gè)線(xiàn)程或者進(jìn)程完成對數據的操作后,其它的線(xiàn)程才能對數據進(jìn)行操作。
  以圖1為例,線(xiàn)程A和線(xiàn)程B對共享變量“counter”進(jìn)行操作,A讓counter 增加,而B(niǎo)則讓counter減少。下方示出了線(xiàn)程A的counter++和線(xiàn)程B counter—的匯編代碼。假設線(xiàn)程B的優(yōu)先級要高于線(xiàn)程A,而線(xiàn)程A目前正在運行,則線(xiàn)程B將被阻止。

 

  舉例來(lái)說(shuō),假設初始的計數值是2,而線(xiàn)程A是執行線(xiàn)程。則線(xiàn)程A讀入計數值,并送入一個(gè)寄存器,在使其增加一個(gè)增量后,再將其寫(xiě)回計數器變量上。

  在可搶先的多線(xiàn)程系統中,高優(yōu)先級的線(xiàn)程的執行可以搶先于低優(yōu)先級的線(xiàn)程。例如,假定線(xiàn)程A執行Reg1 = Reg1+1指令后,一個(gè)事件喚醒線(xiàn)程B。此時(shí),Reg1儲存量值3?,F在線(xiàn)程B被喚醒(正如藍線(xiàn)所標示的那樣),并讀入計數器的量值2(它尚未被線(xiàn)程A刷新)并將其量值減小到1。正如棕色的線(xiàn)所顯示的那樣,經(jīng)過(guò)一段時(shí)間,線(xiàn)程A恢復運行,將Reg1寫(xiě)入計數器中,而該計數器的儲存量值為3。 在這個(gè)過(guò)程中,線(xiàn)程B的減量操作結果被丟棄。計數器存儲的量值變?yōu)?,即線(xiàn)程A進(jìn)行一次增量后,線(xiàn)程B又進(jìn)行了一次減量操作。被竄改的鏈接表則是另一個(gè)例子。如果數據被一個(gè)線(xiàn)程和中斷例程共享,則也會(huì )出現上面的問(wèn)題,因為中斷的執行與線(xiàn)程的執行之間是異步關(guān)系。

{{分頁(yè)}}

  同步化方面的問(wèn)題常常是很難進(jìn)行調試的,因為它們取決于時(shí)序,是隨著(zhù)軟件對數據的操作而隨機出現的。幸運的是,這些問(wèn)題可以通過(guò)恰當地保護任何共享數據來(lái)避免。大多數的實(shí)時(shí)操作系統可以提供同步化原語(yǔ)。開(kāi)發(fā)商 可以使用最適當的機制來(lái)保護共享數據,而不至于影響系統的性能。如果數據在多個(gè)線(xiàn)程之間共享,則開(kāi)發(fā)商將有如下的選擇:

     a. 關(guān)閉調度器以便當前的線(xiàn)程永遠不會(huì )被其它線(xiàn)程搶先。(無(wú)調度區)
     b. 使用信號兩(Semaphore)或者互斥信號量(Mutex)來(lái)保護共享數據。
     c. 利用關(guān)鍵區域來(lái)進(jìn)行保護,即屏蔽所有的中斷。


 

  開(kāi)發(fā)商必須從性能出發(fā)來(lái)選擇恰當的技術(shù)選項。關(guān)閉調度器,將防止任何一種環(huán)境的切換,從而使得現在的線(xiàn)程能繼續執行,直到調度器重新打開(kāi)為止。這種方法有一個(gè)負面的影響:它將阻止任何準備好運行的高優(yōu)先級的線(xiàn)程。這一現象被稱(chēng)為優(yōu)先級倒置。將中斷關(guān)閉是最安全的方法,對于執行時(shí)間短的情形來(lái)說(shuō)是理想選擇。于是,最差情況的中斷延遲就是所有未發(fā)生中斷的持續時(shí)間的總和。在硬實(shí)時(shí)系統中,一般來(lái)說(shuō),一個(gè)中斷功能可以被關(guān)閉的時(shí)間存在上限。

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

  在多線(xiàn)程的系統中,高優(yōu)先級的線(xiàn)程可以搶在低優(yōu)先級的線(xiàn)程之前執行。因此,如果數據在多個(gè)線(xiàn)程間共享的話(huà),則必須采用某種恰當的機制來(lái)保護被共享的數據。

  另外一個(gè)同步化問(wèn)題則與線(xiàn)程優(yōu)先級的不恰當的分配有關(guān)。應當確保系統的初始化線(xiàn)程在引導時(shí)間內就啟動(dòng),并在生成其它的優(yōu)先級更高的線(xiàn)程之前,完成整個(gè)系統的初始化。例如,如果一個(gè)用于配置一個(gè)器件的低優(yōu)先級現場(chǎng)被一個(gè)使用該設備的高優(yōu)先級的線(xiàn)程搶先后,配置可能會(huì )完成,并可能會(huì )造成設備的故障。為了避免這種情形,開(kāi)發(fā)商應當使用操作系統所支持的信號量或者其它同步化的原語(yǔ)。

內存和寄存器的數據訛誤
  大多數的嵌入式系統都采用了平面化的內存模式,也并沒(méi)有內存管理單元(MMU),于是沒(méi)有硬件支持的內存保護機制。即使采用能提供這種功能的處理器,也需要由開(kāi)發(fā)商來(lái)實(shí)現對某些內存區域的保護。進(jìn)程和線(xiàn)程將對其它進(jìn)程和線(xiàn)程的內存空間有完全的訪(fǎng)問(wèn)權限。這可能會(huì )造成下面所描述的、各種類(lèi)型的內存訛誤問(wèn)題。
 
堆棧溢出

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

 

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

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


  開(kāi)發(fā)商可以采用的一個(gè)技巧是,如果你擔心堆棧的溢出,你就應當考慮把它放在有效的內存的邊界上。這樣,當堆棧溢出時(shí),設備將報告硬件異常,而不是造成其它內存空間的訛誤。

{{分頁(yè)}}

  在獨立運行的應用中,運行時(shí)間堆??赡芫鸵呀?jīng)夠用。然而,在使用任何一種實(shí)時(shí)操作系統時(shí),每個(gè)線(xiàn)程和過(guò)程都將有自己的堆棧??紤]到性能方面的原因,大多數嵌入式實(shí)時(shí)操作系統的堆棧尺寸都是事先確定的,無(wú)法在運行中動(dòng)態(tài)擴展。這意味著(zhù),如果針對特定的線(xiàn)程/進(jìn)程所選用的堆棧尺寸不恰當的話(huà),堆棧溢出就會(huì )發(fā)生。

  如果應用大量使用局部變量(如陣列和大的結構),則將不得不按比例為其分配堆棧的空間。人們可以利用malloc() 來(lái)分配內存,或者將其設置為靜態(tài)的全局變量,具體是何種方法,則取決于實(shí)際應用。


  有些實(shí)時(shí)操作系統可能會(huì )提供調試功能,例如保護位,以形成對堆棧溢出的防護。這些操作系統要么記錄關(guān)于堆棧溢出的錯誤信息,要么提交一個(gè)異常報告,以便動(dòng)態(tài)地增加堆棧。最起碼當前的大多數實(shí)時(shí)操作系統都能報告堆棧以及已經(jīng)被線(xiàn)程和進(jìn)程所采用的堆棧的情況。

  在任何中斷驅動(dòng)的系統中,堆棧的分配方式都必須考慮到中斷服務(wù)例程所采用的空間。如果中斷例程的設計目標是使用當前的執行對象棧,則在這種情況下,每一個(gè)線(xiàn)程或進(jìn)程所擁有的最小的堆棧尺寸都應大于或者等于執行對象所要求的堆棧尺寸加上所有中斷例程累積起來(lái)所需要的最大的堆棧尺寸。

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

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

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

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

  而操作內存映射寄存器(MMR)時(shí),人們常常采用在線(xiàn)匯編以改善性能。例如,你在屏蔽中斷時(shí),可能希望直接設定中斷屏蔽寄存器(IMASK)而不是執行RTOS所提供的應用軟件編程接口(API)。例如原子增加或減少操作常常是用匯編語(yǔ)言編寫(xiě)的。在C函數中,這些宏匯編可能會(huì )被調用,在這種情況下,編譯器可能不了解在宏匯編中所使用的寄存器。因此這會(huì )導致寄存器的訛誤。有些編譯器具有匯編的擴展版,可以將關(guān)于這些函數的更多的信息傳遞給編譯器,例如已被使用的寄存器、代碼在內存中的位置等等。這將使得編譯器可以生成恰當的代碼。

  有時(shí),某些函數是以匯編語(yǔ)言編寫(xiě)的,將被C函數所調用。如果匯編代碼并未按照C函數運行時(shí)間調用規范來(lái)編寫(xiě),即按照編譯器所要求的那樣進(jìn)行,則會(huì )導致參數傳遞(argument passing)無(wú)效和訛誤。例如,C函數運行時(shí)間模型可以規定前兩個(gè)參量必須通過(guò)寄存器R0和R1來(lái)傳遞,則匯編的實(shí)現方式就必須按照這種語(yǔ)法來(lái)編寫(xiě)。在另一種情況下,運行時(shí)間模型可能需要存儲堆棧上的函數的返回地址。如果匯編的實(shí)現方法并不符合運行時(shí)間模型,則它可能會(huì )攪亂某些 寄存器,并帶來(lái)系統的故障。如果開(kāi)發(fā)商使用混合模式的語(yǔ)言來(lái)避免這種類(lèi)型的問(wèn)題的話(huà),開(kāi)發(fā)商就必須清楚運行時(shí)間模型。

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

 

  例如,假設一個(gè)設備必須在向其發(fā)任何指令前就完成初始化。編譯器可能會(huì )移動(dòng)指令位置,以便改善性能。這可能會(huì )造成設備的故障。如果你的設備驅動(dòng)器調試后的版本是可行的,而采用經(jīng)過(guò)優(yōu)化的版本時(shí)會(huì )出現故障,那么你會(huì )想查看設備的初始化中是否有被移動(dòng)的指令。你可能不得不采用恰當的編譯器指南以便指導編譯器不去對每條基本函數執行這樣的優(yōu)化,而不至于損失性能。

{{分頁(yè)}}

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

異常所帶來(lái)的問(wèn)題
  如果異常是與程序的執行相同步的,則這往往是一種不當的操作的結果,例如零作為除數所造成的異常。某些異常則是架構所特有的。處理異常的最佳方法是采用缺省的異常處理器,并在出現異常時(shí)檢查異常出現的環(huán)境。異常所處的環(huán)境背景是寄存器量值的集合,包括狀態(tài)寄存器。大多數架構將擁有一個(gè)指令地址寄存器,用來(lái)保存造成問(wèn)題的指令地址。在多數情況下,要知道一個(gè)異常是如何發(fā)生的并不難,但是,是何種指令路徑可以隔離出這一失效,則是調試時(shí)棘手的地方。有些架構支持跟蹤,即讓你可以看到程序順序執行的指令的歷史。這將給出造成異常的指令順序的某些細節信息。內存和寄存器訛誤則是造成異常及程序邏輯錯誤的主要原因。通過(guò)細致檢查造成異常的內存指向或者寄存器,將可以縮小問(wèn)題的范圍。


不能執行錯誤檢驗的代碼會(huì )造成內存的訛誤
  由于性能方面的原因,開(kāi)發(fā)商可能會(huì )放棄對錯誤的檢查。跳過(guò)錯誤檢查將讓內存泄漏等事件無(wú)法為人所知,而最終導致內存訛誤。例如,如果malloc()出現故障,而由于返回的值并未得到檢驗,則開(kāi)發(fā)商將開(kāi)始覆蓋在內存的地址0x0地址所寫(xiě)入的量值,在很多嵌入式系統中,這則是一個(gè)有效的內存區域。一個(gè)技巧是,讓某些地址0x0處的內存控制,以便排查出任何一種潛在的訛誤。某些處理器架構就容許應用監測數據總線(xiàn)的活動(dòng),從而能抓住相應事件。

探尋架構特有的功能:
  大多數嵌入式處理器都支持某種層次上的調試功能。內置的跟蹤單元就是一種得到硬件支持的跟蹤機制。例如,ADI公司的Blackfin處理器系列就具有硬件跟蹤單元,它可以跟蹤至少16路的時(shí)序控制器的訪(fǎng)問(wèn)。當硬件跟蹤緩沖器充滿(mǎn)后,就會(huì )產(chǎn)生跟蹤異常。使用這種跟蹤單元后,人們可以構建出完整的執行路徑。所提供的跟蹤輸出來(lái)自于一種可以免費提供的工具(http://www.blackfin.org/) ,它可以構造完整的執行路徑。

 

觀(guān)察點(diǎn):
  觀(guān)察點(diǎn)可以讓你監測特定的內存位置或者內存塊區正在被更改時(shí)出現的情況。觀(guān)察點(diǎn)可以監測內部的數據總線(xiàn)傳送,如果在觀(guān)察點(diǎn)寄存器中,發(fā)現任何匹配的對象,則讓處理器暫停。如果一個(gè)特定內存位置不斷出現訛誤,則觀(guān)察點(diǎn)就非常有用。對內存塊區進(jìn)行觀(guān)察以查看是否有任何正在損毀存儲器數據的惡意代碼。

  大多數當前的調試環(huán)境都容許對內存和寄存器的內容進(jìn)行修改。有時(shí),修改寄存器的內容,可以讓我們洞察何處出現了故障。例如,通過(guò)更改程序計數器,你可以迫使程序在特定函數出現時(shí)恢復執行。必須謹慎地對恰當的寄存器設定恰當的量值,具體方式則取決于處理器C函數的運行時(shí)間模型。另外一個(gè)有用的寄存器是IMASK,如果你正在調試任何一種實(shí)時(shí)操作系統,則調試(分步深入時(shí))進(jìn)程中任何時(shí)刻都會(huì )出現中斷。由于調試后的代碼不一定處于關(guān)鍵區,你可能幾乎時(shí)時(shí)刻刻都要訪(fǎng)問(wèn)中斷的例程。你可能無(wú)法屏蔽中斷,因為它們讓你的系統完成設定,并運行起來(lái)。例如,任何系統中的定時(shí)器的中斷都可能會(huì )被觸發(fā)。更好的方法是對IMASK寄存器進(jìn)行編輯,將所有的中斷都屏蔽掉,直到你調試完代碼為止。

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

塵埃粒子計數器相關(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>