<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í)嵌入式系統軟件調試常見(jiàn)問(wèn)題分析

實(shí)時(shí)嵌入式系統軟件調試常見(jiàn)問(wèn)題分析

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

內存和寄存器的數據訛誤

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

  大多數的都采用了平面化的內存模式,也并沒(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í),設備將報告硬件異常,而不是造成其它內存空間的訛誤。

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

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

  

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>