2016-07-27 65 views
3

我正在爲Cortex M4F編寫線程代碼。一切正常,我正在研究通過延遲堆棧使FPU上下文切換更高效。Cortex-M4F惰性FPU堆棧

我讀過ARM的AN298,我實現了基於禁用FPU和處理UsageFault的替代方法,但較低的(S0-S15)寄存器沒有被硬件正確保存/恢復。我認爲問題在於圖11:

Figure 11 Context switching

根據這一點,當PendSV的運行FPCAR應該指向任務A的堆棧保留的空間。但就我所見,由於CONTROL.FPCA在任務C中很高,因此在進入PendSV時,FPCAR將更新爲指向任務C的堆棧。如果是這樣,S0-S15FPSCR將被保存到任務C的堆棧而不是任務A,這當然是不正確的。

我在這裏錯過了什麼,或者是appnote錯誤?

一個側面說明,我檢查了一些開源RTOS。 FreeRTOS和mbed RTOS總是在上下文切換期間堆疊S16-S31,導致自動堆棧,即它們僅使用延遲堆棧來減少中斷延遲,但是對任務進行全狀態保存(如在appnote中概述的第一種方法)。用於M4F的TNKernel端口使用UsageFault方法,但通過軟件完全保存/恢復S0-S31,有效地繞過FPCAR(以48個加載/存儲而不是32個,16個硬件在恢復時被覆蓋爲代價)的任何問題。似乎沒有人使用UsageFault方法,只保留S16-S31

(順便說一句,這也張貼在ARM Community,但很多問題似乎置之不理那裏。如果我得到一個答案,我會在這裏複製它,太)

+0

從應用程序注意:「FPCAR寄存器指向當前堆棧中的一部分堆棧空間......」因此它應該指向被搶佔任務的堆棧。 –

+0

@Drueger正確。但是圖紙意味着當任務C被PendSV搶佔時,它仍指向任務A的框架。這就是爲什麼我很困惑,我不知道我是否誤解了它,或者如果appnote中的某些內容是錯誤的。 –

+0

我認爲這表明當FPU被禁用時FPCAR不會被更新。這就是爲什麼它繼續指向任務A的堆棧,直到啓用了FPU的任務C被搶佔爲止。然後保存FPU上下文,直到另一個任務實際需要FPU。 –

回答

0

花了雖然,但最終我發現如何儘可能有效地做到這一點。

首先,該appnote是錯誤的。我在FPCAR更新路上的初步解釋是正確的。請注意,即使禁用FPU,也會更新FPCAR。另外,通過測試,我確定FPCAR確實總是指向中斷的堆棧。

我的第一個方法是操縱FPCAR,LSPACTEXC_RETURN以及UsageFault掛起的PendSV。當然,要做到這一點,從惰性堆棧的角度來看,操作並不算作FPU操作。當文檔缺乏,我們只能破解的答案了CPU的...

LDR R2, =0xE000EF38 
LDR R3, =0xDEADBEEF 
STR R3, [R2] 
VSTM R1, {S16-S31} 
UDF 

FPCAR0xE000EF38VSTM是上下文保存例程的一部分。這個想法是,如果FPCAR操作是FPU操作,懶惰堆棧將暫停FPCAR存儲並且將成功,因爲FPCAR仍然有效。這將在UDF上發生故障。否則,在VSTM上會發生延遲堆棧,並且損壞的FPCAR會導致總線故障。

事實上,我遇到了一個公交故障。好極了!我用一個有效的地址重複了測試:沒有錯,完美地工作。所以保存很簡單。恢復需要待處理的PendSV,並在其內部操作FPCAR,LSPACTEXC_RETURN以導致S0-S15在異常返回時恢復當前線程。這裏的問題是,你不能保持棧上當前線程的狀態,因爲它將被彈出。複製效率不高,所以最好的辦法是將FPCAR指向持久的TCB狀態,而不是保存CPU生成的狀態。

這變得相當複雜,它需要在UsageFault之後執行PendSV,並且它有相當多的角落案例和比賽。有一個更好的方法。

我最終使用的方法完全在UsageFault內運行,並繞過硬件堆棧,而不會損失效率。在啓用FPU並確定需要FPU上下文切換後,I:

  1. LSPACT設置爲零;
  2. 保存/恢復TCB的完整S0-S31狀態;
  3. LSPACT設爲1。

這樣一來,我可以對整個S0-S31工作狀態不懶堆疊得到的道路上,這是因爲CPU認爲它已經堆積的背景下,因爲LSPACT爲零。這當然依賴於UsageFault處理程序在保存/恢復之外不使用FPU操作並且不會被FPU使用的ISR搶佔,鑑於它是手動編碼的ASM,並且故障處理程序不能被ISR搶佔,這些假設是非常簡單的假設。我也嘗試通過ASPEN/LSPEN禁用懶惰堆棧,而不是在LSPACT上工作,但似乎不起作用(它仍會觸發懶惰堆疊,通過設置無效的FPCAR進行驗證)。

效率方面,這與硬件堆棧一樣高效。如果我想挑逗,它會節省一個週期,因爲我不需要回寫遞增的指針。

順便說一句,我包括第一種方法,即使我沒有最終使用它,因爲我認爲它有一些有用的信息,如果有其他人來找這個。