新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > S3C2440中斷體系結構

        S3C2440中斷體系結構

        作者: 時間:2016-11-13 來源:網絡 收藏
        一、S3C2440中斷體系結構

        1)ARM體系CPU的7種工作模式

        本文引用地址:http://www.104case.com/article/201611/316269.htm

        用戶模式(usr):ARM處理器正常的程序執行狀態

        快速中斷模式(fiq):用于高速數據傳輸或通道處理

        中斷模式(irq):用于通用的中斷處理

        管理模式(svc):操作系統使用的保護模式

        數據訪問終止模式(abt):當數據或指令預取終止時進入該模式,可用于虛擬存儲及存儲保護

        系統模式(sys):運行具有特權的操作系統任務

        未定義指令中止模式(und):當未定義的指令執行時進入該模式,可用于支持硬件協處理器的軟件仿真

        除用戶模式外,其他6種工作模式都屬于特權模式,大多數程序運行于用戶模式,進入特權模式是為了處理中斷、異常,或者訪問被保護的系統資源。

        ARM體系的CPU有以下兩個工作狀態

        ARM狀態:此時處理器執行32位的字對齊的ARM指令

        Thumb狀態:此時處理器執行16位的、半字對齊的Thumb指令

        ARM920T有31個通用的32位寄存器和6個程序狀態寄存器。這37個寄存器分為7組,如下圖所示:

        圖中R0-R15可以直接訪問,這些寄存器除了R15外都是通用寄存器,既可以保存地址也可以保存數據。

        R13稱為棧指針寄存器,通常用于保存棧指針

        R14稱為程序連接寄存器(LR),當執行BL子程序調用指令時,R14得到R15(程序計數器PC)的備份。

        而當發生中斷或異常時,對應的R14_svc,R14_irq,R14_abt或R14_und中保存R15的返回值

        R15是程序計數器

        快 速中斷模式有7個備份寄存器R8_fiq-R14_fiq,這使得進入快速中斷模式執行很大部分程序時(不改變R0-R7),不需要保存任何寄存器。用戶 模式、管理模式、數據訪問終止模式和未定義指令中止模式都含有兩個獨占的寄存器副本R13、R14,這樣令每個模式擁有自己的棧指針寄存器和連接寄存器。

        每種工作模式還有寄存器CPSR(當前程序狀態寄存器),它被用于標識各種狀態和當前處于哪種工作模式,如下圖所示:


        當一個異常發生時,將切換進入相應的工作模式,這是ARM920T CPU將自動完成如下工作:

        ①在異常工作模式的連接寄存器R14中保存前一個工作模式的下一條即將執行的指令地址。對于ARM狀態,這個值是當前PC值加4或加8

        ②將CPSR的值復制到異常模式的SPSR

        ③將CPSR的工作模式位設為這個異常對應的工作模式

        ④令PC值等于這個異常模式在異常向量表中的地址,即跳轉去執行異常向量表中的相應指令

        從異常工作模式回到之前的工作模式時,需要通過軟件完成如下事情:

        ①前面進入異常工作模式時,連接寄存器中保存了前一工作模式的一個指令地址,將它減去適當的值后賦值給PC寄存器

        ②將SPSR的復制回CPSR

        異常模式退出異常模式時PC的計算方法進入異常模式時R14中保存的值
        管理模式(SWI指令進入)MOVS PC, R14PC+4(1)
        未定義指令終止模式MOVS PC, R14PC+4(1)
        快速中斷模式SUBS PC, R14, #4PC+4(2)
        中斷模式SUBS PC, R14, #4PC+4(2)
        數據訪問終止模式

        異常原因:指令預取終止

        SUBS PC, R14, #4

        PC+4(1)

        異常原因:數據訪問終止

        SUBS PC, R14, #8

        PC+8(3)

        注:

        (1)PC為這些指令的地址:SWI、未定義的指令、在預取指時就失敗的指令

        (2)PC為這些指令的地址:進入快速中斷模式、中斷模式前,被打斷而未執行的指令

        (3)PC為這些指令的地址:導致數據訪問終止的加載/存儲指令(LDR、STR、LDM和STM)

        二、S3C2440中斷控制器

        當某事件發生時,硬件會設置某個寄存器,CPU在執行完一個指令時,通過硬件查看這個寄存器,如果發現所關注的事件發生了,則中斷當前程序流程,跳轉到一個固定的地址處理這個事件,最后返回繼續執行被中斷的程序。

        中斷處理的過程:

        ①中斷控制器匯集各類外設發出的中斷信號,告訴CPU

        ②CPU保存當前程序的運行環境,調用中斷服務程序(ISR)來處理這些中斷

        ③在ISR中通過讀取中斷控制器、外設的相關寄存器來識別時哪個中斷,并進行相應處理

        ④清除中斷:通過讀寫中斷控制器和外設的相關寄存器來實現

        ⑤最后恢復被中斷程序的運行環境(恢復寄存器),繼續執行

        s3c2440的中斷控制器結構如上圖所示:

        ①request sources(without sub-register)中的中斷源被觸發后,SRCPND寄存器中相應位被置1,如果此中斷沒有被INTMSK寄存器屏蔽或者快速中斷的話,它將被進一步處理。

        ② 對于request sources(with sub-register)中的中斷源被觸發后,SUBSRCPEND寄存器中的相應位被置1,如果此中斷沒有被INTSUBMSK寄存器屏蔽的話,它在 SRCPND寄存器中的相應位也被置1,以后的處理過程就和①步驟類似。

        ③如果被觸發的中斷中有快速中斷,INTMOD寄存器中為1的位對應的中斷是FIQ,則CPU進入快速中斷模式進行處理

        ④ 對于一般的中斷IRQ,可能同時有幾個中斷被觸發,未被INTMSK寄存器屏蔽的中斷經過比較后,選出優先級最高的中斷,此中斷在INTPND寄存器中的 相應位被置1,然后CPU進入中斷模式進行處理。中斷服務程序通過讀取INTPND或者INTOFFSET來確定中斷源

        三、中斷控制寄存器

        1)SUBSRCPND寄存器

        它用來表示INT_RXD0、INT_TXD0等中斷是否發生,每位對應一個中斷,當這些中斷發生并且沒有被INTSUBMSK寄存器屏蔽,則它們中的若干位將匯集出現在SRCPND寄存器的某一位上。要清除中斷,往此寄存器中某位寫1

        2)INTSUBMSK寄存器

        它用來屏蔽SUBSRCPND寄存器所標識的中斷,INTSUBMSK寄存器中某位設置1時,對應的中斷被屏蔽

        3)SRCPND寄存器

        它每一位被用來表示一個或一類中斷是否發生,要清除某一位,往此位寫1,具體參考數據手冊

        4)INTMSK寄存器

        用來屏蔽SRCPND寄存器所標識的中斷。INTMSK寄存器中某位被設為1時,對應的中斷被屏蔽,它只能屏蔽IRQ中斷,不能屏蔽FIQ

        5)INTMOD寄存器

        它某位被設為1時,對應的中斷被設為FIQ,同一時間,INTMOD只能有一位被設為1

        6)PRIORITY寄存器

        當有多個IRQ同時發生時,中斷控制器選出最高優先級的中斷,首先處理它。中斷優先級通過7個仲裁器來完成,結構圖如下所示:

        每個仲裁器基于一個位仲裁器模式控制(ARB_MODE)和選擇控制信號(ARB_SEL)的兩位來處理 6個中斷請求。

        如果ARB_SEL位是 00b,優先級是REQ0,REQ1,REQ2,REQ3,REQ4,和REQ5.

        如果ARB_SEL位是 01b,優先級是REQ0,REQ2,REQ3,REQ4,REQ1,和REQ5.

        如果ARB_SEL位是 10b,優先級是REQ0,REQ3,REQ4,REQ1,REQ2,和REQ5.

        如果ARB_SEL位是 11b,優先級是REQ0,REQ4,REQ1,REQ2,REQ3,和REQ5.

        注 意仲裁器的 REQ0 總是有最高優先級,REQ5 總是有最低優先級。此外通過改變ARB_SEL 位,我們可以翻轉 REQ1 到 REQ4 的優先級。如果ARB_MODE位置0,ARB_SEL位不會自動改變,使得仲裁器在一個固定優先級的模式下操作(注意在此模式下,我們通過手工改變 ARB_SEL 位來配置優先級)。另外,如果 ARB_MODE 位是 1,ARB_SEL 位以翻轉的方式改變。例如如果 REQ1 被服務,則ARB_SEL位自動的變為01b,把REQ1放到最低的優先級。ARB_SEL變化的詳細規則如下:

        如果REQ0 或REQ5 被服務,ARB_SEL位完全不會變化。

        如果REQ1 被服務,ARB_SEL位變為 01b。

        如果REQ2 被服務,ARB_SEL位變為 10b。

        如果REQ3 被服務,ARB_SEL位變為 11b。

        如果REQ4 被服務,ARB_SEL位變為 00b。

        7)INTPND寄存器

        經過中斷優先級選出優先級最高的中斷后,這個中斷在INTPND寄存器中的相應位被置1,隨后CPU進入中斷模式處理它

        同一時間,此寄存器只有一位被置1,在ISR中,可以根據這個位確定是哪個中斷,清除中斷時,往此位寫入1

        8)INTOFFSET寄存器

        用來表示INTPND寄存器中哪位被置1了,即INTPND寄存器中位[x]為1時,INTOFFSET寄存器的值為x(x為0-31)

        清除SRCPND、INTPND寄存器時,INTOFFSET寄存器被自動清除

        四、中斷控制器操作實例:外部中斷

        開發板上,K1-K4四個按鍵所接的CPU引腳可以設為外部中斷,本程序的功能是,當按下某個按鍵時,CPU調用中斷服務程序點亮對應的LED

        @******************************************************************************

        @ File:head.S

        @ 功能:初始化,設置中斷模式、系統模式的棧,設置好中斷處理函數

        @******************************************************************************

        .extern main

        .text

        .global _start

        _start:

        @******************************************************************************

        @ 中斷向量,本程序中,除Reset和HandleIRQ外,其它異常都沒有使用

        @******************************************************************************

        b Reset

        @ 0x04: 未定義指令中止模式的向量地址

        HandleUndef:

        b HandleUndef

        @ 0x08: 管理模式的向量地址,通過SWI指令進入此模式

        HandleSWI:

        b HandleSWI

        @ 0x0c: 指令預取終止導致的異常的向量地址

        HandlePrefetchAbort:

        b HandlePrefetchAbort

        @ 0x10: 數據訪問終止導致的異常的向量地址

        HandleDataAbort:

        b HandleDataAbort

        @ 0x14: 保留

        HandleNotUsed:

        b HandleNotUsed

        @ 0x18: 中斷模式的向量地址

        b HandleIRQ

        @ 0x1c: 快中斷模式的向量地址

        HandleFIQ:

        b HandleFIQ

        Reset:

        ldr sp, =4096 @ 設置棧指針,以下都是C函數,調用前需要設好棧

        bl disable_watch_dog @ 關閉WATCHDOG,否則CPU會不斷重啟

        msr cpsr_c, #0xd2 @ 進入中斷模式,cpsr_c表示cpsr[7:0],0xd2=0b1101 0010

        ldr sp, =3072 @ 設置中斷模式棧指針

        msr cpsr_c, #0xdf @ 進入系統模式

        ldr sp, =4096 @ 設置系統模式棧指針,

        @ 其實復位之后,CPU就處于系統模式,

        @ 前面的“ldr sp, =4096”完成同樣的功能,此句可省略

        bl init_led @ 初始化LED的GPIO管腳

        bl init_irq @ 調用中斷初始化函數,在init.c中

        msr cpsr_c, #0x5f @ 設置I-bit=0,開IRQ中斷

        ldr lr, =halt_loop @ 設置返回地址

        ldr pc, =main @ 調用main函數

        halt_loop:

        b halt_loop

        HandleIRQ:

        sub lr, lr, #4 @ 計算返回地址

        stmdb sp!, { r0-r12,lr } @ 保存使用到的寄存器

        @ 注意,此時的sp是中斷模式的sp

        @ 初始值是上面設置的3072

        ldr lr, =int_return @ 設置調用ISR即EINT_Handle函數后的返回地址

        ldr pc, =EINT_Handle @ 調用中斷服務函數,在interrupt.c中

        int_return:

        ldmia sp!, { r0-r12,pc }^ @ 中斷返回, ^表示將spsr的值復制到cpsr

        /*

        * init.c: 進行一些初始化

        */

        #include "s3c24xx.h"

        /*

        * LED1-4對應GPB5、GPB6、GPB7、GPB8

        */

        #define GPB5_out (1<<(5*2)) // LED1

        #define GPB6_out (1<<(6*2)) // LED2

        #define GPB7_out (1<<(7*2)) // LED3

        #define GPB8_out (1<<(8*2)) // LED4

        /*

        * K1-K4對應GPG0,GPG3,GPG5,GPG6

        */

        #define GPG0_eint (2<<(0*2)) // K1,EINT8

        #define GPG3_eint (2<<(3*2)) // K2,EINT11

        #define GPF5_eint (2<<(5*2)) // K3,EINT13

        #define GPF6_eint (2<<(6*2)) // K4,EINT14

        /*

        * 關閉WATCHDOG,否則CPU會不斷重啟

        */

        void disable_watch_dog(void)

        {

        WTCON = 0;// 關閉WATCHDOG很簡單,往這個寄存器寫0即可

        }

        void init_led(void)

        {

        GPBCON = GPB5_out | GPB6_out | GPB7_out | GPB8_out ;

        }

        /*

        * 初始化GPIO引腳為外部中斷

        * GPIO引腳用作外部中斷時,默認為低電平觸發、IRQ方式(不用設置INTMOD)

        */

        void init_irq( )

        {

        GPGCON = GPG0_eint | GPG3_eint |GPG5_eint |GPG6_eint;

        // 對于EINT8、11、13、14,需要在EINTMASK寄存器中使能它們

        EINTMASK &= (~(1<<8)) & (~(1<<11)) & (~(1<<13)) & (~(1<<14));

        /*

        * 設定優先級:

        * ARB_SEL0 = 00b, ARB_MODE0 = 0: REQ1 > REQ3,即EINT0 > EINT2

        * 仲裁器1、6無需設置

        * 最終:

        * EINT0 > EINT2 > EINT11,EINT19,即K4 > K3 > K1,K2

        * EINT11和EINT19的優先級相同

        */

        PRIORITY = (PRIORITY & ((~0x01) | (0x3<<7))) | (0x0 << 7) ;

        //開啟EINT8_23

        INTMSK &= ~(1<<5);

        }

        interrupt.c

        #include "s3c24xx.h"

        void EINT_Handle()

        {

        unsigned long oft = INTOFFSET;

        switch( oft )

        {

        //INTOFFSET為5時,代表INTPND的位[5]為1,則EINT8-23中斷發生

        case 5:

        {

        GPBDAT |= (0x0f<<5); //LED全滅

        if (EINTPEND & (1<<8)) //EINT8發生(EINT8對應K1)

        GPBDAT &= ~(1<<5);

        if (EINTPEND & (1<<11)) //EINT11發生(EINT8對應K2)

        GPBDAT &= ~(1<<6);

        if (EINTPEND & (1<<13)) //EINT13發生(EINT8對應K3)

        GPBDAT &= ~(1<<7);

        if (EINTPEND & (1<<14)) //EINT14發生(EINT8對應K4)

        GPBDAT &= ~(1<<8);

        break;

        }

        default:

        break;

        }

        //清除中斷

        if(oft == 5)

        EINTPEND = (1<<8) | (1<<11) | (1<<13) | (1<<14);

        SRCPND = 1<

        INTPND = 1<

        }

        main.c

        int main()

        {

        while(1);

        return 0;

        }

        Makefile
        objs := head.o init.o interrupt.o main.o
        int.bin: $(objs)
        arm-linux-ld -Ttext 0x00000000 -o int_elf $^
        arm-linux-objcopy -O binary -S int_elf $@
        arm-linux-objdump -D -m arm int_elf > int.dis
        %.o:%.c
        arm-linux-gcc -Wall -O2 -c -o $@ $<
        %.o:%.S
        arm-linux-gcc -Wall -O2 -c -o $@ $<
        clean:
        rm -f int.bin int_elf int.dis *.o



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 肇庆市| 阆中市| 启东市| 内黄县| 台前县| 兰州市| 苍山县| 勐海县| 宽甸| 三原县| 含山县| 临颍县| 曲水县| 白朗县| 定安县| 平阴县| 汶上县| 西乌珠穆沁旗| 得荣县| 桐柏县| 偏关县| 台南县| 西林县| 桦南县| 合作市| 汝州市| 高雄县| 桂东县| 房产| 江陵县| 西贡区| 万年县| 彭州市| 探索| 潜山县| 乐山市| 台东市| 延边| 疏附县| 新疆| 许昌市|