2016-04-13 25 views
0

我知道很多問題都與此有關,但我仍然沒有完全找到我的答案。我從C/C++程序員的角度思考,他沒有完全意識到在機器級別發生的事情。ARM中斷服務程序vs函數調用程序

當函數被調用時,我知道調用函數的返回地址被壓入堆棧(或鏈接寄存器自動獲取返回地址)以及調用函數使用的所有寄存器,並且程序計數器獲取該函數入口點的地址。

我的主要問題是,所有這些保存在硬件中自動完成的上下文還是在軟件中完成,因此編譯器爲此生成彙編代碼?被調用函數的局部變量如何也保存在堆棧中?

當發生中斷時,我相信這個過程非常類似以便進入中斷服務程序,除了ISR沒有參數或返回任何東西,但主要的區別是什麼?中斷是否被自動禁用或者由編譯器生成代碼來禁止進入ISR的中斷?

非常感謝提前。

+1

儲蓄函數調用是在軟件,並根據調用約定。你可以看看編譯器生成的代碼。對於中斷,ARM具有存儲寄存器,因此如果發生模式切換,某些寄存器會被硬件保留。 – Jester

+0

您需要教程或書籍。還有不同的ARM內核具有非常不同的中斷處理。 – Olaf

+1

我的問題得到-1。似乎我們現在不能在沒有批評的情況下在這裏提出任何問題。人們應該如何學習? – Engineer999

回答

-2

在ARM中,這是由硬件完成的。它是自動的,你不必擔心。 在ISR的情況下,核心不阻止你從其他嵌套IRQ,但我認爲在某些目標中,你可以有高優先級的IRQ,不能被進一步中斷

+0

所以一切都是自動的。在函數調用中自動完成將寄存器推入堆棧?如果我們真的希望中斷ISR而中斷會自動禁用,那麼在ISR期間呢? – Engineer999

+0

「上下文」寄存器(程序計數器,鏈接寄存器...)由硬件自動保存。函數參數必須從調用者傳遞到堆棧 – simpego81

+0

它在所有ARM內核中都不是自動的。取決於版本。 RTFM。 – Olaf

0

在asm術語中,沒有「局部變量」。它只有固定數量的架構寄存器。如果變量比regs多,那麼實現該函數的代碼就必須將一些變量泄漏到堆棧中。

在具有權限分離和內存保護的多任務操作系統中,ISR根本不使用用戶空間堆棧。他們使用內核堆棧,否則用戶空間進程的其他線程可能會干擾內核的ISR!

我假設ARM與其他體系結構相似,如x86,其中硬件保存中斷返回地址,但保留體系結構狀態(包括寄存器)的其餘部分取決於軟件。一個不需要所有寄存器的小型ISR甚至不需要全部保存它們。噢,實際上Jester的評論提醒我,ARM有一套獨立的regs,它們對於ISR是有效的,所以是的,硬件確實負責保存大多數regs。 (這只是對這部分問題的部分回答,我主要是指出它只是需要存儲的寄存器,即固定大小的東西。)

+0

但函數如何訪問局部變量數據?它不使用棧幀指針的偏移量嗎? – Engineer999

+0

@ Engineer999:是的。對於一個簡單的例子,[看看'gcc -O0'爲'void foo(void){int i = 13; }'](https://godbolt.org/g/h4ceAc),因爲它總是分配棧存儲,而不是將變量保存在寄存器中,基本上與優化相反。所以任何不在寄存器中的狀態都已經在堆棧中。因此ISR只需要保存寄存器。 –

0

這取決於你是哪種臂架構談論和哪些指示。分支鏈路(BL)和分支鏈路交換(BLX)指令具有鏈接寄存器r14,使得返回地址的pc被寫入那裏。

返回指令bx lr,mov pc,lr,軟件選擇lr作爲返回,並不像其他指令集那樣硬連線。

程序員或編譯器可以自由使用bl指令並可以使用堆棧,但只按照預期使用這些指令會更有意義。

只要中斷和局部變量和保存狀態的函數調用。軟件必須在一個函數上保存狀態,調用硬件不會爲你做。保存狀態取決於體系結構。對於傳統的32位分支你有/註冊了註冊表,當你切換模式時,你的一些或許多註冊表被切換到另一個分支,例如有多個r13寄存器,一個用於用戶模式,一個用於irq等等這樣,你就不必使用不同的指令來使用你所使用的寄存器,因此在這種情況下,當你從用戶或服務模式切換到irq模式時,通過切換yo從基本保護或保存狀態銀行登記冊,你想要拯救你的任何其他狀態需要做你自己。

現在,cortex-m微控制器有點不同,當發生中斷時,硬件會爲您保存狀態,所有寄存器,寄存器沒有存儲區,只是將它們推入堆棧並使用位模式爲返回地址表明這是一箇中斷並恢復寄存器/狀態。

所有這些東西都記錄在臂架構的體系結構參考手冊或特定內核的技術參考手冊中。這兩套文件都可以在infocenter.arm.com上找到。

arm的核心是如何處理中斷的,傳統上你有單獨的irq和fiq線路進來.ARM使核心不是芯片,所以它取決於芯片供應商實施其餘的中斷設計,並且其差異很大。一般來說,雖然你(軟件)有一些責任去外設,並告訴它從它的末端取消中斷。它如何鎖定在外圍設備和核心之間是可以改變的東西的一部分。基本上你希望在離開服務程序之前使信號無效。皮質毫秒和更新的全尺寸內核可以有數十到數百個單獨的中斷,支持使軟件工作更容易,性能更好,你不必花時間在一個通用的ISR中找出誰造成了它然後分支給各種處理程序,他們把它到每個外設的另一個極端,甚至比它可以擁有自己的isr更細粒度。

一些內核中的更多中斷管理位於核心,您可以看到arm文檔,其餘中斷管理特定於該芯片,您需要芯片供應商提供的文檔以獲取該信息,絕不是普通的中斷如何工作的答案。

2

ARM擁有先發制人的上下文切換功能。

對於皮質拱

在內部具有兩個堆棧指針,主堆棧指針(MSP)和處理堆棧指針(PSP)。

當您執行上下文切換時,ARM硬件會按硬件推送一些(但不是所有註冊表和PC)硬件彈出另一個上下文。 通常R4-R12和LR和PC將被推送到堆棧

這個功能由KERNEL /用戶空間模型使用,並且對中斷沒有用處。這是爲什麼:

通過硬件,中斷是跳轉(C gotos),到一箇中斷向量的固定地址。這個地址然後可以調用一個函數(你的中斷處理程序)

由於你可能有多箇中斷級別,所以在執行此函數調用時,不能依賴上下文切換,並且需要將寄存器保存在堆棧中與任何其他框架,但這次在主要堆棧)。


經典ARM

你有多種模式,每種模式有它自己的堆棧,以及不同的中斷被映射到不同的模式。

您沒有多箇中斷級別,所以您可能完全依賴硬件在上下文切換時推送XPSR,PC,R0,R1,R2,R3,R12和LR。


來源:寄存器http://www.design-reuse.com/articles/25768/cortex-m-and-classical-series-arm-architecture-comparisons.html

+0

取決於arm核心/體系結構,沒有一個通用的答案,有三個主要的arm架構不計算這個問題,傳統arm,cortex-m和aarch64的橡子天數有所不同... –

+0

@dwelch謝謝,增加了皮質和經典之間的差異 – xvan

+0

謝謝。從C/C++的角度來看。它在做什麼以及如何訪問這個級別的「局部變量」? – Engineer999