歡迎您光臨本站 登入註冊首頁

概述

   Vxworks作為一個實時嵌入式操作系統,通常採用中斷的方式來滿足系統實時性的要求,因此,熟悉其中斷的處理過程對於VxWorks操作系統的開發是至關重要的.本文通過……

    Vxworks作為一個實時嵌入式操作系統,通常採用中斷的方式來滿足系統實時性的要求,因此,熟悉其中斷的處理過程對於VxWorks操作系統的開發是至關重要的.本文通過編寫和調試基於AT91RM9200處理器的VxWorks嵌入式操作系統的BSP,來討論VxWorks操作系統的中斷機制。

1 VxWorks中斷處理機制及AIC
    AT91RM9200使用一個8優先順序,可單獨屏蔽中斷的中斷向量控制器AIC。在ARM體系結構中,有7種異常中斷,對應有一個異常中斷向量表。ARM體系結構要求這個異常中斷向量表從0地址處開始,對於外部中斷請求IRQ,系統又增加了一塊由中斷控制器控制的中斷向量表。

2 AT91RM9200 BSP的中斷驅動的實現
2.1 中斷驅動中定義的函數
STATUS at91rm9200LvlVecChk (int*,int*);
STATUS at91rm9200LvlVecAck(int,int);
STATUS at91rm9200LvlEnable(int);
STATUS at91rm9200LvlDisable(int);

2.2 高級中斷控制器AIC的初始化
    在usrInit()中excVecInit()函數對異常中斷向量進行初始化.整個中斷庫,以及中斷控制器的初始化都是在syslib.c中的sysHwInit2()函數中完成的.該函數在sysClkConnect()中被調用,因為系統時鐘中斷要在內核開放中斷後就要使能,因此內核在初始化為一個多任務環境后,就產生一個usrRoot()的任務,在該任務中要建立系統時鐘中斷,因此調用了sysClkConnect()函數,中斷庫以及中斷控制器的初始化也就完成了。
    高級中斷控制器必須進行初始化,其初始化是在板級支持包BSP的中斷驅動程序中。具體的實現函數是void at91rm9200IntDevInit(void)。該函數在文件syslib.c的sysHwInit2()函數中調用。
    at91rm9200IntDevInit(void)函數中主要是配置系統的鉤子函數,然後對中斷源向量寄存器和中斷模式寄存器進行配置,同時要清除並禁止AIC中所有的中斷。

2.3 中斷驅動中的回調函數
    在intEnt中,程序很快就進入了特權模式(SVC32),如果是中斷可嵌套模式,要設置該模式下的堆棧,並且將中斷深度intCnt值加1.然後跳轉到intIntRtnPreempt中,在intIntRtnPreempt中為後來調用中斷驅動中的函數開闢了32個位元組的堆棧空間,並且將程序指針拉到at91rm9200LvlVecChk函數處執行,at91rm9200LvlVecChk函數是在中斷驅動中定義的函數,是用來檢測當前掛起的中斷中,優先順序最高的中斷源。檢測出最高優先順序的中斷後,首先要禁止該中斷,因此要調用at91rm9200LvlDisable函數,該函數也在中斷驅動中定義。在禁止中斷的過程中,需要通過intLock和intUnLock函數來保護臨界代碼不被新的中斷打斷。
    at91rm9200LvlVecChk()函數是通過讀AIC_IVR寄存器來獲取當前最高優先順序的中斷,將獲得的中斷號和中斷向量賦給2個變數,並且禁止該中斷。at91rm9200LvlVecAek()函數是在中斷處理結束后,通過寫AIC_EIOC寄存器來清除剛剛處理的中斷,並將其使能。at91rm9200LvlEnable(int leve1)和at91rm9200LvlDisable(int level)來允許和禁止中斷,從而保護臨界代碼不被新的中斷所打斷。

2.4 中斷驅動程序實現的流程圖
    中斷驅動程序實現的流程圖如圖1所示。
 
圖1 中斷驅動程序實現的流程圖

3 VxWorks中斷模塊實現機制
3.1 異常中斷向量表的生成及實現
    在usrInit()函數中通過intVecBaseSet((FUNCPTR*)VEC_BASE_ADRS)函數對異常中斷向量表的基址進行設置,VEC_BASE_ADRS在configall.h中定義為程序運行空間的起始地址,但是在ARM中並沒有中斷基址寄存器,由於ARM9有重影射機制,可以將程序運行空間的起始地址影射成0地址,這也符合ARM體系結構通常都是把異常中斷向量表放在0地址處的慣例,異常中斷向量表可以從反彙編bootrom_uncmp后的0地址處看到。當有內置的外設中斷或外部中斷產生時,系統首先跳轉到異常中斷向量表的0x18處,此處是IRQ中斷向量的位置,該內存中放置的是一條跳轉指令,因為excVecInit()對中斷向量表初始化后,生成了一個exeEnterTbl,在這個表中列出了異常向量和對應入口函數的結構表,exeEnterTbl結構如圖2所示。
 
圖2 excEnterTbl的結構
    由於ARM9用了重影射機制,因此重影射之後,系統將LOCAL_MEM_LOCAL_ADRS影射成0地址,中斷向量表從0地址處開始。從excVecInit()的反彙編代碼可以看出,系統把指令ldr pc,[pc,#244]的反彙編代碼放在了從0x00000004開始的每個異常中斷向量地址處,也就是將excEnterTbl中每個異常處理函數的入口地址都放在了(0xF4+0x8+0x4+所對應異常相對於未定義指令異常(0x00000004)的偏移)的內存中,這樣就將異常向量和異常處理入口函數關聯起來了。

3.2 中斷向量表的結構及生成
    那麼當系統產生中斷後,VxWorks是如何設置中斷向量表,並且將中斷向量和中斷處理入口程序關聯起來的呢?和異常向量表有點類似,但是中斷向量表是VxWorks操作系統動態分配的一段連續的內存空間,這個空間的結構如圖3所示。
 
圖3 VxWorks中斷向量表的結構
    因為是動態分配,所以在這段內存空間中,操作系統只給當前中斷分配了中斷號、中斷處理函數的入口和被傳遞的參數。每個中斷源按照中斷號順序排列,在為每個中斷源分配的內存空間中頭4個位元組是中斷向量表的初始化函數的入口,該函數對於每個中斷源來說是通用的,然後順序放置的是中斷號、中斷處理函數入口和被傳遞的參數.通過intconnect()函數可以將中斷向量和中斷處理函數關聯起來,因此在系統獲知了發生中斷的中斷號時,就可以找到相應的中斷處理函數去處理該中斷。當發生IRQ異常時,系統強制把程序指針拉到0x18處,在0x18處是這樣一條指令ldrpc,[pc,#244],IRQ異常相對於未定義指令異常的偏移是0x14,所以相當於把0x114地址處的內容賦給pc,而0x114處的內容正是IRQ異常向量處理的入口函數intEnt的地址,因此程序跳轉到intent處去執行。

4 中斷處理跟蹤調試的部分反彙編代碼
   通過使用ARM Developer Site模擬器,在0x18處設置斷點后單步執行來分析中斷處理的過程。中斷處理函數的入口處代碼如下:
2070b174[0xe59fb410] ldr r11,0x2070b58c;  /*=#0x207a40c8,0x207a40c8是中斷向量表的位置*/
2070b178[0xe59dc018] ldr r12,[r13,#0x18] /*將0x207b1ce8中的內容給r12應該是中斷號!!!*/
2070b17c[0xe59bb000] ldr r11,[r11,#0] /*0x207a40c8處的內容是0x21ffbef8*/
2070b180[0xe08b318c] add r3,r11,r12,lsl #3 /*將0x21ffbef8(內存地址)給r3,0x21ffbef8的內容是向量0x207064b0,這是debug口中斷處理函數的入口*/
2070b184[0xe79ba18c] ldr r10,[r11,r12,lsl#3]
2070b188[0xe5930004] ldr r0,[r3,#4] /*相應的參數傳遞給r0*/
2070b18c[0xe1a0e00f] mov r14,pc
2070b190[0xe1a0f00a] mov pc,r10 /* r10=0x207064b0,跳轉到debug口中斷處理函數處執行*/
    0x21ffbef8(中斷向量表基址)處的情況是:
21ffbef8[0x2070b434] dcd 0x2070b434 4.p
21ffbefc[0x00000000] dcd 0x00000000....
21ffbf00[0x207064b0] dcd 0x207064b0.dp
21ffbf04[0x207a9990] dcd 0x207a9990..z
21ffbf08[0x2070b434] dcd 0x2070b434 4.p
21ffbf0c[0x00000002] dcd 0x00000002....
21ffbf10[0x2070b434] dcd 0x2070b434 4.P
21ffbf14[0x00000003] dcd 0x00000003....
21ffbf18[0x2070b434] dcd 0x2070b434 4.P
21ffbf1c[0x00000004] dcd 0x00000004....

5 結語
    Vxworks操作系統首先調用excVecInit()生成一個異常中斷向量表excEnterTbl,當有IRQ中斷髮生時,根據excEnterTbl中0x00000018處的指令ldr pc,[pc,#244]跳轉到0x00000114處,即IRQ異常中斷的入口處intEnt執行,隨後通過讀AIC_IVR寄存器得到當前優先順序最高的中斷,返回這個中斷號,並跳轉到intConnect()函數給該中斷號關聯的中斷處理程序入口去執行。在這個過程中,中斷向量表的生成是Vxworks動態分配的,在AT91RM9200中,為0到31號中斷源在中斷向量表中都分配了空間,該空間的格式固定。中斷處理結束后,通過往AIC_EIOC寄存器中寫任意值,從中斷中返回。


[admin via 研發互助社區 ] VxWorks基於AT91RM9200處理器的中斷處理已經有2051次圍觀

http://cocdig.com/docs/show-post-42229.html