Cortex-M3 PendSV 中断 系统调用 说明
參考 Cortex-M3權威指南中文版
PendSV異常是和系統調用有些類似,cpu 需要手動將往NVIC 的PendSV 懸起寄存器中寫1,然后產生中斷, 系統調用(SVC)是cortex-M3? CPU執行 SVC指令之后產生中斷(arm中一般是SWI 指令),都是軟件的方式產生的中斷,稱其為內中斷。
PendSV 和SVC? 兩個內中斷的不同之處在于:
SVC指令執行之后,必須立即響應(保證能夠立即硬件入棧r0-r3等寄存器,這是因為SVC中斷需要傳遞參數到中斷模式,所以必須立即響應,保證寄存器中存儲的參數不被破壞,另一個原因是用戶態程序,即線程模式的程序有的時候必須得到SVC中斷響應函數的返回值才能繼續執行,否則強行繼續執行,將會出錯),SVC的中斷服務程序(ISR)立即執行,如果此時有別的ISR正在執行,且此中斷的優先級比SVC的優先級高,將會產生硬fault,
(注:SVC通常在用戶級線程模式下運行,但可以在特權級線程模式或者handler模式下運行,詳見《cortex m3 權威指南》第12章,非基級的線程模式 一節,如果在一個中斷的ISR中調用 SVC,而且此ISR的優先級比SVC的優先級高,那么會產生硬fault,這是合理的,SVC必須立即得到響應,但是響應過程中允許被其他中斷打斷? 例如在svc中斷觸發后,開始硬件入棧,但svc的ISR還沒有開始執行,此時來了個優先級比SVC優先級更高的中斷,那么優先級高的中斷將以 晚到中斷 的形式執行, 執行完畢后 SVC的ISR再以? 咬尾中斷 的形式執行)
SVC中斷 和 其他中斷還有不同之處,? 其他中斷一般都是 不需要參數和返回值的,? 所以中斷觸發之后的 硬件入棧 之后 和 執行出棧序列 之前,中斷的ISR一般是不修改 保存在棧的R0-R3、xpsr、PC? 和 LR 寄存器的,(也有特殊情況,例如 上述提到過的 《cortex m3 權威指南》第12章,非基級的線程模式 一節), 但是SVC中斷是可能需要 參數或者 返回值的,? 參數和返回值要借助? R0-R3寄存器來傳遞,? 考慮到cortex-m3的晚到中斷、咬尾中斷等硬件機制,? SVC觸發后, SVC的ISR執行過程中不能直接讀取R0-R3寄存器獲取參數,而是要到棧中讀取 保存的R0-R3寄存器的值,來獲取參數,SVC的ISR 返回? 返回值的時候,也不能直接 向R0寄存器中寫入返回值,出棧序列執行后,R0的值會被棧中保存的R0的值覆蓋,正確的做法是,修改棧中保存的R0的值,修改為要返回的值
注:這里說的 線程模式 handler模式? 特權級 用戶級的關系如下:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
SVC一般在用戶線程模式下執行。它設計的本意就是讓用戶模式完成到普通模式的切換。
PendSV中斷,一般在特權模式下 往 NVIC 的PendSV 懸起寄存器中寫1,來觸發,一般在SysTick中斷的ISR中執行,也就是Handler模式下并且,PendSV的優先級一般設置成最低,PendSV的ISR一般等到其他中斷全部響應完成后,再響應,PendSV(懸起異常)設計的理念就是可以將此異常懸起, 這樣就可以完美應用在? 上下文切換的場景中。? 上下文切換可以再SVC和SysTick的ISR中完成,這里只說SysTick(系統滴答時鐘中斷),如果SysTick發生時,程序執行在用戶級的線程模式,則沒有問題,如下圖:
? ? ? ? ? ? ? ? ? ? ? ? ??
但是如果,Systick發生時,是在其他中斷的ISR中,則系統是不允許系統調用發生的,如果允許將會產生如下效果:
? ? ? ? ? ? ? ? ? ? ? ? ?
我們可以看到,IRQ中間被中斷了,并且中斷的時間 包含上下文切換以及任務B的一個時間片,這個時間是不確定的,IRQ的沒有得到及時的響應,這在實時系統中是堅決不允許的。所以 就引入了 PendSV,如果在SYSTICK來臨的時候,檢測到有IRQ在執行,就延緩上下文切換, 在SYSTICK的ISR中 使用PendSV懸起一個異常,等之前的IRQ執行完之后,在執行上下文切換,如下圖:
? ? ? ? ? ? ? ? ? ?
事件的流水賬記錄如下:
1. 任務 A 呼叫SVC 來請求任務切換(例如,等待某些工作完成)
2. OS 接收到請求,做好上下文切換的準備,并且pend 一個PendSV 異常。
3. 當 CPU 退出SVC 后,它立即進入PendSV,從而執行上下文切換。
4. 當 PendSV 執行完畢后,將返回到任務B,同時進入線程模式。
5. 發生了一個中斷,并且中斷服務程序開始執行
6. 在 ISR 執行過程中,發生SysTick 異常,并且搶占了該ISR。
7. OS 執行必要的操作,然后pend 起PendSV 異常以作好上下文切換的準備。
8. 當 SysTick 退出后,回到先前被搶占的ISR 中,ISR 繼續執行
9. ISR 執行完畢并退出后,PendSV 服務例程開始執行,并且在里面執行上下文切換
10. 當 PendSV 執行完畢后,回到任務A,同時系統再次進入線程模式。
詳見Cortex-M3權威指南124頁。
注,這里我想說明的是根據圖7.16我的個人推論,可能是錯誤的,? 在linux中? 每一個用戶空間的進程都有自己的用戶棧,和核心棧,如果cortex-m3結合rt-thread也是用這個模式,可以印證圖7.16,當IRQ執行的過程中,Systick異常發生, IRQ的執行上下文現場被保存在任務A的核心棧中,然后執行上下文切換,上下文切換完成后,寄存器MSP和PSP分別指向了任務B的核心棧指針和用戶棧指針,然后IRQ隨著任務A被封存而封存,任務B壓根不知道任務A的 棧中還封存著一個IRQ,因為任務B及時有權限不應該去破話另一個任務的棧空間。直到任務A重新得到CPU,IRQ接著在任務A的棧空間繼續執行,可惜從中斷產生到中斷服務程序結束,已經隔了十萬八千年。
經過實際驗證,Cortex m3結合rt-thread 應該沒有使用和linux一樣的模型,? 而是所有的線程共享內核棧,即MSP 執行的棧空間所有線程共享,這里和linux-arm有個小區別,linux-arm 中斷來臨的時候,保存現場都是保存在內核棧中,這個內核棧是每一個內核線程獨有的, 而 Cortex-m3--rtthread? 是中斷來臨之前使用用戶棧(PSP寄存器所指的棧空間),保護現場就在用戶棧,中斷來臨之前使用核心棧(MSP寄存器所指),保護現場就用核心棧,但由于PendSV懸起中斷的引入,所以線程切換的都借助PendSV來完成,這就保證線程切換的PendSV來臨之前保護現場,一定在用戶棧,用戶棧是每個線程所獨有的,所以,綜上所述,? 針對線程切換所對應的中斷,? linux-arm保存現場都是在核心棧, 而cortex-rtthread都是在用戶棧,但是他們都能保證,保存現場所用 的空間是每一個內核線程獨有的。
?
總結
以上是生活随笔為你收集整理的Cortex-M3 PendSV 中断 系统调用 说明的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: chrome 打开视频网站提示需要安装
- 下一篇: 数字化转型,这5点最重要,其他都是瞎扯