s3c24x0 中斷異常處理

 在進入正題之前,我想先把ARM920T的異常向量表(Exception Vectors)做一個簡短的介紹。:]
ARM920T 的異常向量表有兩種存放方式,一種是低端存放(從0x00000000處開始存放),另一種是高端存放(從0xfff000000處開始存放)。關於爲什 麼要分兩種方式進行存放這點我將在介紹MMU的文章中進行說明,本文采用低端模式。ARM920T能處理有8個異常,他們分別是:
Reset,Undefined instruction,Software Interrupt,Abort (prefetch),Abort (data),Reserved,IRQ,FIQ
下面是某個採用低端模式的系統源碼片段:

_start:
b Handle_Reset
b HandleUndef
b HandleSWI
b HandlePrefetchAbort
b HandleDataAbort
b HandleNotUsed
b HandleIRQ
b HandleFIQ
..

..
other codes

    上面這部分片段一般出現在一個名叫“head.s”的彙編文件裏,“b Handle_Reset”這條語句就是系統上電之後運行的第一條語句。也就是說這部分代碼的二進制碼必須位於內存的最開始部分(這正是低端存放模式), 因爲上電後CPU會從SDRAM的0x00000000處取第一條指令並執行。

Address     Instruct
0x00000000: b Handle_Reset
0x00000004: b HandleUndef
0x00000008: b HandleSWI
0x0000000C: b HandlePrefetchAbort
0x00000010: b HandleDataAbort
0x00000014: b HandleNotUsed
0x00000018: b HandleIRQ
0x0000001C: b HandleFIQ

    上面是該程序段在系統上電後加載到內存後的分佈情況,我們可以看到每條指令佔用了4個字節。
    上電後,PC指針會跳轉到Handle_Reset處開始運行。以後系統每當有異常出現,則CPU會根據異常號,從內存的0x00000000處開始查表 做相應的處理,比如系統觸發了一個IRQ異常,IRQ爲第6號異常,則CPU將把PC指向0x00000018地址 (4*6=24=0x00000018)處運行,該地址的指令是跳轉到“中斷異常服務例程”(HandleIRQ)處運行。以上就是我對異常向量表的一個 簡單介紹。現在可以進入我們文章的主題 “中斷異常處理”,s3c2410的中斷分快中斷(FIQ)和普通中斷(IRQ),我們討論的重點是普通中斷(IRQ)。
s3c2410的中斷異常處理模塊總共由以下寄存器構成
  SRCPND(SOURCE PENDING REGISTER)
  INTMOD(INTERRUPT MODE REGISTER)
  INTMSK(INTERRUPT MASK REGISTER)
  PRIORITY( PRIORITY REGISTER)
  INTPND(INTERRUPT PENDING REGISTER)
  INTOFFSET(INTERRUPT OFFSET REGISTER)
  SUBSRCPND (INTERRUPT SUB SOURCE PENDING)
  INTSUBMSK  (INTERRUPT SUB MASK REGISTER)

下面我將講解每個寄存器在一箇中斷處理流程中所扮演的角色:
    SRCPND/ SUBSRCPND這兩個寄存器在功能上是相同的,它們是中斷源引腳寄存器,在一箇中斷異常處理流程中,中斷信號傳進中斷異常處理模塊後首先遇到的就是SRCPND/ SUBSRCPND,這兩個寄存器的作用是用於標示出哪個中斷請求被觸發。SRCPND的有效位爲32,SUBSRCPND 的有效位爲11,它們中的每一位分別代表一箇中斷源。SRCPND爲主中斷源引腳寄存器,SUBSRCPND爲副中斷源引腳寄存器。
這裏列舉出SRCPND的各個位信息:
[轉]s3c2410 中斷異常處理:這篇文章把2410中斷處理過程分析的淋漓盡致 - 笨笨貓 - 我的博客
[轉]s3c2410 中斷異常處理:這篇文章把2410中斷處理過程分析的淋漓盡致 - 笨笨貓 - 我的博客
   每個位的初始值皆爲0。假設現在系統觸發了TIMER0中斷,則第10bit將被置1,代表TIMER0中斷被觸發,該中斷請求即將被處理(若該中斷沒有被屏蔽的話)。SUBSRCPND情況與SRCPND相同,這裏就不多講了。
    INTMOD寄存器有效位爲32位,每一位與SRCPND中各位相對應,它的作用是指定該位相應的中斷源處理模式(IRQ還是FIQ)。若某位爲0,則該位相對應的中斷按IRQ模式處理,爲1則以FIQ模式進行處理,該寄存器初始化值爲0x00000000,即所有中斷皆以IRQ模式進行處理。(詳細請參考s3c2410操作手冊)。
INTMSK/ INTSUBMSK 寄存器爲中斷屏蔽寄存器 ,INTMSK爲主中斷屏蔽寄存器,INTSUBMSK爲副中斷屏蔽寄存器。INTMSK有效位爲32,INTSUBMSK有效位爲11,這兩個寄存器各個位與SRCPNDSUBSRCPND分別對應。它們的作用是決定該位相應的中斷請求是否被處理。若某位被設置爲1,則該位相對應的中斷產生後將被忽略(CPU不處理該中斷請求),設置爲0則對其進行處理。這兩個寄存器初始化後的值是0xFFFFFFFF0x7FF,既默認情況下所有的中斷都是被屏蔽的。
到目前爲止我們總共講解了SRCPND,INTMOD,INTMSK,SUBSRCPND,INTSUBMSK
五個寄存器,在繼續講解PRIORITY寄存器之前我們先來看一張圖。[轉]s3c2410 中斷異常處理:這篇文章把2410中斷處理過程分析的淋漓盡致 - 笨笨貓 - 我的博客
   先弄清楚一點,現在要討論的是一箇中斷優先級的判斷問題。爲什麼會有中斷有先級的問題呢?我們知道CPU某個時刻只能對一箇中斷源進行中斷處理,如果現在 有3箇中斷同時發生了,那CPU要按什麼順序處理這個3箇中斷呢?這正是引入優先級判斷的原因所在,通過優先級判斷,CPU可以按某種順序逐個處理中斷請 求。3sc2410的優先級判斷分爲兩級。
    如上圖所示,SRCPND寄存器對應的32箇中斷源總共被分爲6個組,每個組由一個ARBITER(0~5)寄存器對其進行管理。中斷必須先由所屬組的ARBITER(0~5)進行第一次優先級判斷(第一級判斷)後再發往ARBITER6進行最終的判斷(第二級判斷)。ARBITER(0~5)這六個組的優先級已經固定,我們無法改變,也就是說由ARBITER0控制的該組中斷優先級最高(該組產生的中斷進行第一級判斷後永遠會以REQ0向ARBITER6傳遞過去)其次是ARBITER1, ARBITER2, ARBITER4, ARBITER4, ARBITER5.我們能夠控制的是某個組裏面各個中斷的優先級順序。怎麼控制?通過PRIORITY寄存器進行控制:]
以下是PRIORITY寄存器各個位的參數表
[轉]s3c2410 中斷異常處理:這篇文章把2410中斷處理過程分析的淋漓盡致 - 笨笨貓 - 我的博客
   從表上我們可以知道PRIORITY寄存器內部各個位被分爲兩種類型,一種是ARB_MODE,另一種爲ARB_SEL, ARB_MODE類型有5組對應ARBITER(2~6)(PS:此處應更正爲ARB_MODE類型有7組對應ARBITER(0~6),在datasheet中上表還有續表,爲ARB_MODE1-0),ARB_SEL類型有7組對應ARBITER(0~6)。現在我將以ARBITER2爲例,講解中斷組與PRIORITY寄存器中ARB_SEL, ARB_MODE之間的相互關係。
  首先我們看到ARBITER2寄存器管理的該組中斷裏包括了6箇中斷,分別是INT_TIMER0,INT_TIMER1,INT_TIMER2,INT_TIMER3,INT_TIMER4,INT_UART2,她們的默認中斷請求號分別爲REQ0,REQ1,REQ2,REQ3,REQ4,REQ5。我們先看PRIORITY寄存器中的ARB_SEL2,該參數由兩個位組成,初始值爲00。從該表可以看出00定義了一個順序 0-1-2-3-4-5 ,這個順序就是這組中斷組的優先級排列,這個順序指明瞭以中斷請求號爲0(REQ0)的INT_TIMER0具有最高的中斷優先級,其次是INT_TIMER1,INT_TIMER2…。假設現在ARB_SEL2的值被我們設置爲01。則一個新的優先級次序將被使用,01對應的優先級次序爲0-2-3-4-1-5,從中可以看出優先級最高和最低的中斷請求和之前沒有變化,但本來處於第2優先級的INT_TIMER1中斷現在變成了第5優先級。從ARB_SEL2被設置爲00,01,10,11各個值所出現的情況我們可以看出,除最高和最低的優先級不變以外,其他各個中斷的優先級其實是在做一個旋轉排列rotate)。爲了達到對各個中斷平等對待這一目標,我們可以讓優先級次序在每個中斷請求被處理完之後自動進行一次旋轉,如何自動讓它旋轉呢?我們可以通過ARB_MODE2達到這個目的,該參數只有1個 bit,置1代表開啓對應中斷組的優先級次序旋轉,0則爲關閉。事實上當該位置爲1之後,每處裏完某個組的一箇中斷後,該組的ARB_SEL便遞增在1(達到11後恢復爲00)。
    現在我們另ARB_MODE2=1,ARB_SEL2=00,則當前ARBITER2的優先級順序爲0-1-2-3-4-5,假設現在該組的1號中斷請求INT_TIMER1和2號中斷請求INT_TIMER2被同時觸發,CPU根據優先級判斷後決定先把INT_TIMER1中斷向ARBITER6進行發送(在ARBITER6做第最終優先級判斷),接着再向ARBITER6發送INT_TIMER2中斷。請注意,在INT_TIMER1被處理完畢後,該組中段的優先級次序被自動做了一次旋轉,旋轉後ARBITER2優先級順序變爲0-2-3-4-1-5。假設之後某個時刻該組的INT_TIMER1和INT_TIMER2又被同時觸發,則此時CPU優先處理的會是INT_TIMER2。若我們另ARB_MODE2=0,則改組的中斷優先級次序在任何情況下都不做任何改變,除非我們人爲地重新設置了ARB_SEL2的值。
    呼。。。好累。。。終於說完了麻煩的優先級-_-…繼續。。。
INTPND 寄存器可能是整個中斷處理過程中我們要特別注意的一個寄存器了,他的操作比較特別,怎麼特別?請聽我慢慢道來.:] 
先看一下該寄存器各位詳細功能列表
[轉]s3c2410 中斷異常處理:這篇文章把2410中斷處理過程分析的淋漓盡致 - 笨笨貓 - 我的博客
    正如你所見的,INTPND寄存器與SRCPND長得一模一樣,但他們在中斷異常處理中卻扮演着不同的角色,如果說SRCPND是中斷信號進入中斷處理模塊後所經過的第一個場所的話,那麼INTPND則是中斷信號在中斷處理模塊裏經歷的最後一個寄存器。它的每個位對應一箇中斷請求,若該位被置1,則表示相應的中斷請求被觸發,描述到這裏你可能會發現它不僅和SRCPND長得一模一樣,就連功能都一樣,其實不然,他們在功能上有着重大的區別。SRCPND是中斷源引腳寄存器,某個位被置1表示相應的中斷被觸發,但我們知道在同一時刻內系統可以觸發若干個中斷,只要中斷被觸發了,SRCPND的相應位便被置1,也就是說SRCPND在同一時刻可以有若干位同時被置1然而INTPND則不同,他在某一時刻只能有1個位被置1,INTPND 某個位被置1(該位對應的中斷在所有已觸發的中斷裏具有最高優先級且該中斷沒有被屏蔽),則表示CPU即將或已經在對該位相應的中斷進行處理。於是我們可以有一個總結:SRCPND說明了有什麼中斷被觸發了,INTPND說明了CPU即將或已經在對某一箇中斷進行處理。
特別注意:每當某一箇中斷被處理完之後,我們必須手動地把SRCPND/SUBSRCPND , INTPND三個寄存器中與該中斷相應的位由1設置爲0,剛纔我說INTPND的操作很特別,它的特別之處就在於對當我們要把該寄存器中某個值爲1的位設置爲0時,我們不是往該位置0,而是往該位置1。假設SRCPND=0x00000003,INTPND=0x00000001,該值說明當前0號中斷和1號中斷被觸發,但當前正在被處理的是0號中斷,處理完畢後我們應該這樣設置INTPND和SRCPND
  SRCPND="0x00000002"              //位0被置爲0
  INTPND =0x00000001             //位0被置爲0(方法是往該位寫入1
INTOFFSET寄存器的功能則很簡單,它的作用只是用於表明哪個中斷正在被處理。下面是該寄存器各位詳細功能列表
[轉]s3c2410 中斷異常處理:這篇文章把2410中斷處理過程分析的淋漓盡致 - 笨笨貓 - 我的博客
    若當前INT_TIMER0被觸發了,則該寄存器的值爲10,以此類推。
    現在我把整個中斷流程用一個圖加以說明
[轉]s3c2410 中斷異常處理:這篇文章把2410中斷處理過程分析的淋漓盡致 - 笨笨貓 - 我的博客
以上這個圖清楚地說明了一箇中斷異常處理流程。
    下面我用INT_TIMER0, INT_TIMER2和INT_UART0三個中斷完整地介紹一次中斷異常處理。首先我們得做幾個假設:
假設1:這三個中斷的屏蔽被取消。
假設2:PRIORITY寄存器中ARB_MODE2,ARB_MODE5皆爲0,既不進行優先級的自動旋轉排序,任何時候
      ARBITER2,ARBITER5控制的中斷組優先級次序分別爲0-1-2-3-4-5和1-2-3-4。
假設3:這三個中斷皆爲IRQ類型。
假設4:這三個中斷同時被觸發。
INT_TIMER0,INT_TIMER2和INT_UART0三個中斷被同時觸發,此時三個中斷信號流向SRCPND寄存器,使該寄存器中的第10位,12位,28位被置爲1,中斷信號繼續向前流經INTMASK寄存器,這三個中斷都沒有被屏蔽,於是信號進一步流經INTMODE寄存器,這三個中斷皆爲IRQ類型,故中斷信號繼續向前流向PRIORITY寄存器,經過優先級判斷,INT_TIMER0中斷信號使INTPND寄存器的第10位置1(INT_TIMER0優先級最高),此時INTOFFSET寄存器的值爲10,CPU轉向相應的中斷服務例程進行處理。處理完畢後,我們的程序將INTPNDSRCPND的第10置爲0,至此INT_TIMER0中斷處理完畢。此時SRCPND的第12位,28位仍爲1(這兩個中斷請求未被處理),故他們會繼續被CPU已剛纔描述的方式進行處理。
中斷異常處理就先講到這吧 :]
 

以上是原帖內容,再次感謝作者。。。

 

PS

在對2410的裸板進行中斷實驗的過程中,從菜鳥的角度出發,我把學到了一些東西和之前ARM體系結構的理論結合起來:

 

1、ARM處理器中,r13sp)和r14lr)分別對應6個不同狀態下的物理寄存器,其中1個是用戶、系統模式共用的,其他分別對應5種異常模式(Exception Mode)。要在後續程序中使用中斷,則應先把要用到的各種模式的堆棧設置好,如設置IRQ和系統模式的sp

msr cpsr_c, #0xd2        @進入IRQ模式,IRQ和FIQ都處於禁止狀態
ldr sp, =0x33000000

msr cpsr_c, #0xdf        @進入系統模式,IRQ和FIQ都處於禁止狀態
ldr sp, =0x34000000

bl init_irq              @初始化中斷
msr cpsr_r, #0x5f        @置控制域的I位爲0,打開irq中斷。實驗中只用到irq

2、   如果用到按鍵等中斷控制,是屬於外部中斷的(External Interrupt),就需要配置EINT相關的寄存器。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章