1.浮點運算指令
浮點運算指令用于FPU單元的單精度浮點運算。浮點運算指令都是用V開頭的匯編指令。
只有在FPU開啟的狀態下,才能運行這些指令。
如果在FPU沒有開啟的狀態下,執行了浮點運算指令,系統會產生一個硬fault異常。
2.為什么FPU需要Lazy Stacking
當Cortex-M系列的芯片多了對浮點運算的支持之后,在中斷響應和退出時會增加對FPU擴展寄存器的保護。
入棧浮點寄存器組所帶來的影響有如下幾方面:
a.增加stack frame所占的存儲區域;
b.增加中斷響應延遲;
c.在OS環境下,增加上下文切換時間;
為了減少中斷響應延遲和OS環境下的上下文切換時間,引入了FPU的Lazy Stacking機制。
3.FPU Lazy Stacking簡述
Lazy Stacking機制在下面的情況下,會跳過對浮點寄存器組的入棧操作(僅預留浮點寄存器組S0~S15和FPSCR的存儲空間),以避免中斷延遲的增加:
a.中斷處理函數不使用FPU;
b.被中斷的程序未曾用到FPU;
被中斷函數使用了FPU,如果在執行中斷處理函數時也用到了FPU,在執行到中斷函數的第一條浮點指令時,內核會暫停,然后硬件自動將先前的浮點寄存器內容(S0~S15,FPSCR)壓入預留的存儲空間中。
Lazy Stacking是可以通過軟件使能和關閉的,如下述操作:
a.使能Lazy Stacking必須同時置位FPCCR寄存器的LSPEN位和ASPEN位;
b.清除FPCCR寄存器的LSPEN位可以關閉Lazy Stacking;
關于FPCCR寄存器的LSPEN位和ASPEN位的組合情況有如下說明:
FPCCR.ASPEN | FPCCR.LSPEN | 說明 |
---|---|---|
0 | 0 |
取消自動狀態保存。中斷響應時不入棧FPU寄存器。 應用場景: 1. 應用中沒有用到OS或者多任務調度,如果沒有任何中斷異常用到FPU。 2. 在應用程序代碼中只有一個中斷用到FPU。如果有多個中斷用到FPU,那么中斷嵌套必須被禁止。可以通過把所有的中斷優先級設置位相同優先級實現。 |
1 | 0 |
關閉Lazy Stacking,僅打開自動狀態保存。 如果用到FPU,CONTROL.FPCA位自動置1。中斷響應時,硬件自動入棧S0~S15和FPSCR寄存器。 |
1 | 1 |
打開Lazy Stacking,打開自動狀態保存。 如果用到FPU,CONTROL.FPCA位自動置1。如果響應中斷時,CONTROL.FPCA為1,處理器在堆棧中預留FPU寄存器的空間,同時將FPCCR.LSPACT位置1。但是PFU寄存器并沒有馬上入棧,直到在中斷處理函數中用到FPU時再入棧。 |
0 | 1 | 非法配置 |
4.FPU Lazy Stacking用到的幾個重要標志
浮點寄存器入棧和出棧過程中用到的標志位:
標志位 | 說明 |
---|---|
CONTROL.FPCA |
0 = 當前上下文中沒有用到FPU 1 = 當前上下文中用到FPU 這里的上下文,即表示普通的任務上下文,也表示中斷上下文。 |
FPCCR.LSPACT |
0 = 退出Lazy狀態(實際入棧后被硬件清零或者中斷返回時硬件清零) 1 = 進入Lazy狀態(棧幀中預留了FPU寄存器的空間,但沒有實際入棧) |
EXC_RETURN[4] |
0 = 棧幀中包括了FPU寄存器空間 1 = 棧幀中不包括FPU寄存器空間 |
5.FPU Lazy Stacking使用實例
下面的例子都是在使能了FPU的Lazy Stacking機制下進行說明的。
(1).被中斷的程序和中斷程序中都沒有使用到FPU,其示意圖如下所示:
Snipaste_2020-04-10_11-46-40
(2).被中斷的程序用到了FPU,中斷程序中沒有使用到FPU,其示意圖如下所示:
Snipaste_2020-04-10_12-38-54
(3).被中斷的程序和中斷程序中都用到了FPU,其示意圖如下所示:
Snipaste_2020-04-10_14-05-19
6.RTOS使用Lazy Stacking
首先肯定是要使能FPU的Lazy Stacking,然后在PendSV切換任務的時候做下面的處理:
(1).上文保存階段:檢測 EXC_RETURN 的 bit4(通過LR訪問),如果該位為零,就入棧剩下的S16-S31 即可;如果該位為 1,則無需保存 FPU 寄存器,因為該任務未曾使用過 FPU。當然了這里有一個標志數據,表示當前任務是否使用了FPU,便于下次任務恢復時,確定是否需要從堆棧彈出內容到S16-S31。標志數據也壓入當前任務的堆棧進行保存。
(2).下文恢復階段:從堆棧中彈出標志數據,判斷待恢復的任務是否使用了FPU,如果使用了FPU,那么從堆棧中彈出內容到S16-S31;如果沒有使用FPU,則不需要恢復FPU寄存器。接下來需要修改當前LR寄存器的內容,如果使用了FPU,LR(EXC_RETURN)的bit4需要清零,來保證在退出PendSV時將先前壓入該任務堆棧的S0-S15和FPSCR寄存器出棧;如果沒有使用FPU,LR(EXC_RETURN)的bit4需要置1,來告訴CPU該任務棧幀中不包括FPU寄存器內容,不需要進行出棧操作。
對于S0-S15和FPSCR寄存器,如果任務使用了FPU,在進入到PendSV之前,就在任務堆棧中預留了存儲空間,當執行上文保存階段的S16-S31的入棧操作時,會首先將S0-S15和FPSCR寄存器壓入先前堆棧預留的存儲空間中,接著再將S16-S31壓入堆棧。
審核編輯:劉清
-
寄存器
+關注
關注
31文章
5336瀏覽量
120232 -
SCR
+關注
關注
2文章
150瀏覽量
44183 -
中斷處理
+關注
關注
0文章
94瀏覽量
10967 -
FPU
+關注
關注
0文章
42瀏覽量
21311 -
Cortex-M
+關注
關注
2文章
229瀏覽量
29752
原文標題:Cortex-M FPU的Lazy Stacking機制
文章出處:【微信號:嵌入式那些事,微信公眾號:嵌入式那些事】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論