1.SoC對中斷的實現機制:異常向量表
(1)異常向量表是CPU中某些特定地址的特定定義。當中斷發生的時候,中斷要想辦法通知CPU去處理中斷,怎么做到?這就要靠異常向量表。
(2)在CPU設計時,就事先定義了CPU中一些特定地址作為特定異常的入口地址(譬如定義0x00000000地址為復位異常向量地址,則發生復位異常時CPU會自動跳轉到0x00000000地址去執行指令。又譬如外部中斷對應的異常向量地址為0x30000008,則發生外部中斷后,CPU會硬件自動跳轉到0x30000008地址去執行指令。)如
(3)以上講的是CPU硬件設計時對異常向量表的支持,下來就需要軟件支持了。硬件已經決定了發生什么異常CPU自動跳轉PC到哪個地址去執行,軟件需要做的就是把處理這個異常的代碼的首地址填入這個異常向量地址。
2.異常向量表的編程處理
1、像內存一樣去訪問異常向量表
(1)S5PV210的異常向量表可以改變(在CP15協處理器中),以適應操作系統的需求。但是目前系統剛啟動時,此時DRAM尚未初始化,程序都在SRAM中運行。210在iRAM中設置了異常向量表,供暫時性使用。
(2)查210的iROM application note文檔中iRAM的地址分配,可知,iRAM中的異常向量表起始地址為0xD0037400。知道了異常向量表的起始地址后,各個異常對應的入口就很好知道了。
2、函數名的實質就是函數的首地址
(1)函數名在C語言中的理解方法和變量名其實沒區別。編譯器會把這個函數的函數體對應的代碼段和這個函數的函數名(實質是符號)對應起來,等我們在使用這個函數名符號時,編譯器會將函數的函數體實際上做替換。因為函數體都不止4字節,而函數名這個符號只能對應1個地址,所以實際對應的是函數體那一個代碼段的首地址。
(2)拿C語言中的語法來講,函數名就是這個函數的函數指針。
總結:當我們將異常處理程序的首地址和異常向量表綁定起來后,異常處理初步階段就完成了。到目前可以保證相應異常發生后,硬件自動跳轉到對應異常向量表入口去執行時,可以執行到我們事先綁定的函數。
3.匯編保存現場和恢復現場
(1)中斷處理要注意保護現場(中斷從SVC模式來,則保存SVC模式下的必要寄存器的值)和恢復現場(中斷處理完成后,準備返回SVC模式前,要將保存的SVC模式下的必要寄存器的值恢復回去,不然到了SVC模式后寄存器的值亂了,SVC模式下原來正在進行的常規任務就被你搞壞了)
(2)保存現場包括:第一:設置IRQ棧;第二,保存LR;第三,保存R0~R12
(3)為什么要保存LR寄存器?要考慮中斷返回的問題。中斷ISR執行完后如何返回SVC模式下去接著執行原來的代碼。中斷返回其實取決于我們進入中斷時如何保存現場。中斷返回時關鍵的2個寄存器就是PC和CPSR。所以我們在進入IRQ模式時,應該將SVC模式下的下一句指令的地址(中斷返回地址)和CPSR保存起來,將來恢復時才可以將中斷返回地址給PC,將保存的CPSR給CPSR。
(4)中斷返回地址就保存在LR中,而CPSR(自動)保存在(IRQ模式下的)SPSR中
(5)保護現場關鍵是保存:中斷處理程序的返回地址,r0-r12(cpsr是自動保存的)
(6)恢復現場主要是恢復:r0-r12,pc,cpsr
#define IRQ_STACK 0xd0037f80
// 在這個匯編函數中,用來做中斷模式下的現場保護和恢復,并且調用真正的中斷處理程序
IRQ_handle:
// 設置IRQ模式下的棧
ldr sp, =IRQ_STACK
// 保存LR(儲存的是pc值)
// 因為ARM有流水線,所以PC的值會比真正執行的代碼+8,
sub lr, lr, #4
// 保存r0-r12和lr到irq模式下的棧上面
stmfd sp!, {r0-r12, lr}
// 在此調用真正的isr來處理中斷
bl irq_handler
// 處理完成開始恢復現場,其實就是做中斷返回,關鍵是將r0-r12,pc,cpsr一起回復
ldmfd sp!, {r0-r12, pc}^
4.異常處理的2個階段
(1)可以將異常處理分為2個階段來理解。
第一個階段是異常向量表跳轉;
第二個階段就是進入了真正的異常處理程序irq_handler之后的部分。
(2)第一個階段之所以能夠進行,主要依賴于CPU設計時提供的異常向量表機制。第一個階段的主要任務是從異常發生到響應異常并且保存/恢復現場、跳轉到真正的異常處理程序處。
(3)第二個階段的目的是識別多個中斷源中究竟哪一個發生了中斷,然后調用相應的中斷處理程序來處理這個中斷。
5.相關寄存器
VICnINTENABLE | 負責相應的中斷的使能 |
VICnINTENCLEAR | 負責相應的中斷的禁止 |
VICnINTSELECT | 設置各個中斷的模式為irq還是fiq。一般都設置成irq |
VICnFIQSTATUS& VICnIRQSTATUS | 中斷狀態寄存器,是只讀的。當發生了中斷時,硬件會自動將該寄存器的對應位置為1,表示中斷發生了。軟件在處理中斷第二階段的第一階段,就是靠查詢這個寄存器來得到中斷編號的。 |
VICnVECTPRIORITY(0~31) | 中斷優先級設置寄存器,設置多個中斷同時發生時先處理誰后處理誰的問題。一般來說高優先級的中斷可以打斷低優先級的中斷,從而嵌套處理中斷。當然了有些硬件/軟件可以設置不支持中斷嵌套。 |
VICnVECTADDR(0~31) | VICnVECTADDR0到31這32個寄存器分別用來存放真正的各個中斷對應的isr的函數地址。相當于每一個中斷源都有一個VECTADDR寄存器,程序員在設置中斷的時候,把這個中斷的isr地址直接放入這個中斷對應的VECTADDR寄存器即可。 |
VICnADDR | VICnADDR這個寄存器是只需要讀的,它里面的內容是由硬件自動設置的。當發生了相應中斷時,硬件會自動識別中斷編號,并且會自動找到這個中斷的VECTADDR寄存器,然后將其讀出復制到VICnADDR中,供我們使用。這樣的設計避免了軟件查找中斷源和isr,節省了時間,提高了210的中斷響應速度。 |
5.整個中斷的流程梳理:
整個中斷的工作分為2部分:
第一部分是我們為中斷響應而做的預備工作:
1. 初始化中斷控制器
2. 綁定寫好的isr到中斷控制器
3. 相應中斷的所有條件使能
第二部分是當硬件產生中斷后如何自動執行isr:
1. 第一步,經過異常向量表跳轉入IRQ/FIQ的入口
2. 第二步,做中斷現場保護(在start.S中),然后跳入isr_handler
3. 第三步,在isr_handler中先去搞清楚是哪個VIC中斷了,然后直接去這個VIC的ADDR寄存器中取isr來執行即可。
4. 第四步,isr執行完,中斷現場恢復,直接返回繼續做常規任務。
中斷設置初始化流程圖
中斷相應流程
上一篇:s5pv210 fimc 之 fimc-dev.c
下一篇:X210串口配置與stdio移植
推薦閱讀最新更新時間:2025-04-17 12:15


