傳統ARM中IRQ是作為一種系統異常出現的。對于ARM核來說,有且僅有一個稱為IRQ的系統異常。而ARM對于IRQ的處理一般通過異常向量找到IRQ的中斷處理程序。當進入IRQ中斷處理程序之后,ARM自動屏蔽IRQ,也就是說在中斷響應過程中是忽略之后到來的中斷請求的。即使使用了VIC,VIC也僅僅是懸起后來的中斷請求。也就是說,傳統ARM的中斷是不可嵌套、不可搶占的。
不過,ARM給了我們一種權利,那就是在中斷處理程序中可以手動打開IRQ,這樣在前一個IRQ響應的過程中,就可以被后來的中斷所打斷。就給我們提供了一種用軟件解決中斷嵌套的途徑。
中斷的過程我們都十分清楚:保護現場à響應中斷à恢復現場。ARM對于每一種異常都有相應的堆棧寄存器,且會自動切換,互不影響。所以自然而然地,在嵌套中,我們可以用SP_irq來保護現場和恢復現場。流程如下所示:
1. 第一次進入中斷
2. ARM自動保存CPSR到SPSR_irq
3. ARM自動保存PC到LR_irq
4. ARM自動關閉IRQ使能
5. 保存通用寄存器、LR_irq、SPSR_irq到SP_irq所指示的堆棧中
6. 打開IRQ使能位
7. 根據中斷號進行中斷服務
7.1 第二次進入中斷,開始嵌套
7.2 ARM自動保存CPSR到SPS_irq
7.3 ARM自動保存PC到LR_irq
7.4 ARM自動關閉IRQ使能
7.5 保存通用寄存器、LR_irq、SPSR_irq到SP_irq所指示的堆棧中
7.6 打開IRQ使能位
7.7 根據中斷號進行中斷服務
7.8 關閉IRQ使能位
7.9 從SP_irq堆棧中恢復通用寄存器、LR_irq、SPSR_irq
7.10通過LR_irq跳轉回到7
7.11ARM自動從SPSR_irq恢復CPSR
8. 關閉IRQ使能位
9. 從SP_irq堆棧中恢復通用寄存器、LR_irq、SPSR_irq
10. 通過LR_irq跳轉回到到任務程序
11. ARM自動從SPSR_irq恢復CPSR
這樣就實現了嵌套,而且只要堆棧夠大,可以嵌套很多層。不考慮優先級,或者把優先級教給中斷控制器管理,這樣已經不錯了吧,雖然不愿意這么說,但是問題還是來了。
在上面的流程中,有一步是根據中斷號進行中斷服務。對于不同的中斷源,我們一般都會用不同函數來寫中斷服務,這樣不僅清晰,也利于將不同功能的模塊分割開。這樣我們就需要將這步變為:根據中斷號進入服務子程序。這步中,我們會牽涉到函數調用。在函數調用過程中,一般都會先將PC保存在LR_irq中,在返回時,再將LR_irq恢復到PC。這也正是LR的作用所在。
正是這個事實,導致了問題的發生。想象這種情況:當我們進入服務子程序后,此時LR_irq正是我們程序的返回地址。這時,第二個中斷到來了,回憶一下中斷發生時ARM自動做了什么,ARM將PC保存到了LR_irq中!就這樣,LR_irq被篡改了,因為我們無法預料到中斷什么時候到來,我們也就根本無法保存這個被篡改的LR_irq。程序響應好第二個中斷后,一路返回到這個LR_irq,毫無意外的,就跑飛了。
很掃興吧,不過我們自然有辦法解決這個問題。辦法就是在進入服務子程序之前,先將系統轉換到SVC狀態,這樣,子程序被調用時返回地址就會被保存在LR_svc中,也就不會再被第二個中斷所篡改。流程如下,和第一次不同的地方都用紅色標注。
為什么要保存r0-r3, 保存lr_svc不就夠了嗎?
1. 第一次進入中斷
2. ARM自動保存CPSR到SPSR_irq
3. ARM自動保存PC到LR_irq
4. ARM自動關閉IRQ使能
5. 保存通用寄存器、LR_irq、SPSR_irq到SP_irq所指示的堆棧中
6. 更改系統狀態為SVC
7. 保存R0-R3,LR_svc到SP_svc所指示的堆棧中
8. 打開IRQ使能位
9. 根據中斷號進入中斷服務子程序
9.1 第二次進入中斷,開始嵌套
9.2 ARM自動保存CPSR到SPS_irq
9.3 ARM自動保存PC到LR_irq
9.4 ARM自動關閉IRQ使能
9.5 保存通用寄存器、LR_irq、SPSR_irq到SP_irq所指示的堆棧中
9.6 更改系統狀態為SVC
9.7 保存R0-R3,LR_svc到SP_svc所指示的堆棧中
9.8 打開IRQ使能位
9.9 根據中斷號進入中斷服務子程序
9.10關閉IRQ使能位
9.11從SP_svc所指示的堆棧中恢復R0-R3,LR_svc
9.12更改系統狀態為IRQ
9.13從SP_irq堆棧中恢復通用寄存器、LR_irq、SPSR_irq
9.14通過LR_irq跳轉回到9
9.15ARM自動從SPSR_irq恢復CPSR
10. 關閉IRQ使能位
11. 從SP_svc所指示的堆棧中恢復R0-R3,LR_svc
12. 更改系統狀態為IRQ
13. 從SP_irq堆棧中恢復通用寄存器、LR_irq、SPSR_irq
14. 通過LR_irq跳轉回到到任務程序
15. ARM自動從SPSR_irq恢復CPSR
這樣我們既可以用中斷服務子程序,也不怕LR被篡改了。我們再來看一下嵌套過程中的堆棧使用情況。在進入SVC狀態之前,使用IRQ的堆棧,保存嵌套所需的通用寄存器、LR_irq和SPSR_irq。進入SVC狀態之后,使用SVC堆棧,需要保存調用函數規定的R0-R3,LR_svc。當然在中斷服務例程中,也是使用SVC堆棧。可見兩個狀態的堆棧都被使用了。當然,因為中斷服務例程使用SVC堆棧,我們也可以考慮將嵌套所需的堆棧也放到SVC中,這樣就不需要IRQ堆棧了。流程上和前面這種方法很相似,只不過要將保存LR_irq和SPSR_irq的時間放到進入SVC態之后,方法可以是通過通用寄存器拷貝。最后也不必再返回IRQ態,可以直接通過SPSR_svc和LR_svc來推出中斷處理程序。
程序貼在下面,用的是堆棧分開的方法,只是示例。
__asm void IRQ_Handler(void){
PRESERVE8
IMPORT handler1
// STORE LR_irq & SPSR_irq
SUB LR, LR, #4
MRS R0, SPSR
STMFD SP!, {R0, LR}
// INTO SVC MODE
MRS R0, CPSR
BIC R0, #0x1f
ORR R0, #0x13
MSR CPSR_C, R0
// STORE REGISTORS OF SVC MODE
STMFD SP!, {R0-R3,LR}
// ENABLE IRQ
MRS R0, CPSR
BIC R0, #0x80
MSR CPSR_C, R0
// GO TO HANDLER
BL handler1
// RESTORE REGISTORS OF SVC MODE
LDMFD SP!, {R0-R3,LR}
// DISABLE IRQ
MRS R0, CPSR
ORR R0, #0x80
MSR CPSR_C, R0
// INTO IRQ MODE
MRS R0, CPSR
BIC R0, #0x1f
ORR R0, #0x12
MSR CPSR_C, R0
// RESTORE LR_irq & SPSR_irq
LDMFD SP!, {R0, LR}
MSR SPSR_CFX, R0
// EXIT IRQ
MOVS PC, LR
}
上一篇:mini2440裸機編程--------觸摸屏驅動
下一篇:ARM處理器架構-----異常/中斷處理
推薦閱讀
史海拾趣
在電子汽車行業初期,XYZ公司主要生產簡單的車載電子設備。為了進入歐洲市場,公司決定對其產品進行E-Mark認證。經過嚴格的測試和審核,XYZ公司的產品質量和安全性能得到了歐洲市場的認可。隨著歐洲市場的開拓,XYZ公司逐漸擴大了生產規模,提升了技術水平,最終成為了汽車電子行業的領導者。
大毅科技于1989年成立,是臺灣的一家新興企業。在公司成立的初期,大毅科技就專注于晶片電阻的研發與生產,這在當時是一個相對新興且競爭激烈的領域。創始人憑借對技術的深刻理解和敏銳的市場洞察力,帶領公司逐步在市場中站穩腳跟。通過不斷的技術創新和產品優化,大毅科技逐漸獲得了客戶的認可,并在行業中樹立了自己的品牌。
隨著技術的不斷進步,Cembre SPA不斷加大對研發的投入,推出了一系列創新產品。其中,公司的電纜接頭技術取得了重大突破,不僅提高了接頭的可靠性和安全性,還降低了安裝和維護的成本。這些技術創新使得Cembre SPA在市場中脫穎而出,成為行業的領導者。
隨著環保意識的不斷提高,ELMEC開始關注企業的環保責任。他們采用環保材料替代傳統材料,減少生產過程中的污染排放。同時,公司還積極開展綠色能源研發和應用,降低能耗和碳排放。這些措施不僅為公司贏得了良好的社會聲譽,也為推動電子行業的可持續發展做出了積極貢獻。
E-Z-HOOK公司非常重視與客戶的關系建立與維護。他們始終堅持以客戶為中心的經營理念,努力為客戶提供高質量的產品和優質的服務。為了更好地了解客戶需求和反饋,公司建立了完善的客戶服務體系,包括售前咨詢、售后服務和技術支持等。此外,公司還定期組織客戶交流會和技術研討會等活動,加強與客戶的溝通與互動。這些努力使得E-Z-HOOK公司贏得了廣大客戶的信任和支持。
BENCENT公司在成立之初,面臨著資金短缺、技術瓶頸和市場認知度低等多重挑戰。創始人帶領團隊夜以繼日地研發,通過不斷嘗試和改進,終于成功開發出了一款具有競爭力的電子產品。這款產品憑借其高性能和創新性,在市場上獲得了初步認可,為公司的后續發展奠定了基礎。
范圍包括但不限于Ethernet, IP, MPLS, TCP/UDP協議,交換機/路由器/防火墻等。 如果我不懂的會盡量幫忙找到答案。 大家共同提高:)… 查看全部問答∨ |
|
當時上大學時跟老師做實驗,我們把低頻和高頻信號加在線圈上,用他們產生的磁場作用到兔子和老鼠的頭部,大概是2個星期后,把兔子和老鼠的腦子做切片時,發現腦細胞有明顯的變化,有些已經萎縮,有些就是畸形,總是肯定是有影響的,建議遠離。… 查看全部問答∨ |
|
1.WindRiver有Wind SNMPManager開發包嗎? 2.是用net-snmp移植到vxworks6.1還是用snmp++了? 我現在需要在vxworks6.1實現管理端程序,不知道這個怎么著手?希望大家指導,謝謝。… 查看全部問答∨ |
|
比方說在一個大的無線局域網內, 1,兩臺PocketPC通過Wifi及時通訊性能怎么樣? 2,在兩個移動的車子里(當然車子一直在這個局域網內)兩臺PocketPC通過Wifi及時通訊性能怎么樣? 3,當兩臺PocketPC正在通訊時,突然有大的物體靠近時,Wifi及 ...… 查看全部問答∨ |
|
一個單選按鈕控件,我用它來做選擇的功能,想實現當用戶點擊后可以通過點擊其他按鈕將單選按鈕圈圈里的黑點取消掉,怎么實現? 對MFC的控件不是太熟悉,望大家多幫忙咯,謝謝嗯!… 查看全部問答∨ |
有哪位大俠知道 static CMOS有何特性啊?告知一聲,謝謝! The DM350 is designed in full static CMOS, so when you stop a module clock, it retains the module\'s state.… 查看全部問答∨ |
設計資源 培訓 開發板 精華推薦
- Linux系統編程篇丨迅為IMX6ULL-對應視頻講解
- 嵌入式學習丨4412開發板-uboot源碼-匯編-源碼分析(一)嵌入式學習丨4412開發板-uboot源碼-匯
- 迅為IMX6ULL開發板-主頻和時鐘配置例程(二)
- 迅為IMX6ULL開發板-主頻和時鐘配置例程
- 迅為IMX6ULL開發板安裝VMware Tool工具
- i.MX6ULL終結者Debian文件系統的構建i.MX6ULL 移植Debian文件系統
- 迅為i.MX6ULL開發板按鍵例程編譯及運行
- 迅為-i.MX6開發板手冊更新-非設備樹uboot-修改默認環境變量
- 迅為-IMX6ULL-QT應用_在開發板上移植ssh
- 迅為-i.MX6ULL開發板-QT實戰項目DHT11&網絡編程實戰練習(一)