新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 第5課:ARM的中斷

        第5課:ARM的中斷

        作者: 時間:2016-11-11 來源:網絡 收藏
        中斷分為硬件中斷和軟件中斷SWI

        而硬件中斷有內部中斷,即中斷控制器中所列出的那些中斷。而外部中斷在中斷控制器里列的是EINT。

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

        總共有60個中斷源,而在中斷控制器中列出32個,還有一些子中斷在子中斷控制器里列出。這些控制器我們都是通過寄存器的某一位來控制。

        中斷發生之后的流程:

        1把下一條指令的地址放入LR,不過PC是5級流水線,所以LR的值要減去4才是正真的下一條指令的地址。

        2把cpsr復制到中斷模式的spsr

        3pc設置到0x18的位置,這個位置是中斷向量表,他指引程序跳轉到中斷處理程序。而中斷處理程序的作用是1:保存上下文2:繼續跳轉到中斷服務程序。

        4退出的時候要恢復上下文,最重要的是把中斷的spsr復制到cpsr

        以下介紹下用到的寄存器:

        1 SRCPND 它只要發送一次中斷,該相應位就變成1。即使那個中斷源被屏蔽了,這個位還是置1.

        2 SUBSRCPND 子中斷源未決寄存器。

        3 INTMSK 中斷源屏蔽

        4 INTSUBMSK 子中斷源屏蔽

        5 INTOFFSET 讀這個寄存器 方便讀出是哪個中斷,用10進制表示。

        以下來做個例子:

        在主程序中小燈一直閃,然后串口接受到數據,產生中斷,然后回顯數據。

        這個crt0.s 是文件的入口,該程序放在0x0的位置,所以一開始進入的是中斷向量表

        .extern main
        .extern EINT_Handle
        .externinit_irq
        .text
        .global _start
        _start:
        bReset
        HandleUndef:
        bHandleUndef
        HandleSWI:
        bHandleSWI
        HandlePrefetchAbort:
        bHandlePrefetchAbort
        HandleDataAbort:
        bHandleDataAbort
        HandleNotUsed:
        bHandleNotUsed

        bHandleIRQ@0x18

        HandleFIQ:
        bHandleFIQ

        Reset:
        ldr r0, =0x53000000 @ WATCHDOG close
        mov r1, #0x0
        str r1, [r0]
        msr cpsr_c, #0xd2 @進入中斷模式
        ldr sp, =3072 @設置中斷模式的sp
        msr cpsr_c, #0xd3 @進入svc模式
        ldr sp, =4096
        bl init_irq
        msr cpsr_c, #0x53 @把svc的i位置0

        ldr lr, =halt_loop @設置返回地址
        ldr pc, =main @ 進入主程序

        HandleIRQ:@中斷處理程序
        sub lr, lr, #4
        stmdb sp!, { r0-r12,lr } @ 保存環境
        ldr lr, =int_return

        ldr pc, =ISR_Handle @進入中斷服務程序
        int_return:
        ldmia sp!, { r0-r12,pc }^ @恢復環境
        halt_loop:
        bhalt_loop
        這個是程序的主框架。

        以下是中斷服務程序int.c

        #include "addr.h"

        void init_irq()
        {
        INTMSK = ~(1<<28);
        INTMOD = 0;
        INTSUBMSK = 0xfffffffe;
        }

        void EINT_Handle()
        {
        unsigned long oft = INTOFFSET;
        if(oft == 28){
        if(SUBSRCPND & 1){
        UTXH0 = URXH0;//這里RX里面的數據一定要讀走,不然中斷有問題。不然會根據RX interpute type 選擇模式的不同有不同的效果。
        SUBSRCPND |= 1;//這里清中斷,要置1,清中斷有一定順序。從src子到src再到int
        SRCPND |= 1< INTPND |= 1<}
        }

        }

        以下是main主程序:主要初始化燈和串口,執行小燈閃

        #include"addr.h"
        #define UART_CLK 50000000
        #define UART_BAUD_RATE 115200
        #define UART_BRD (int)(UART_CLK/(UART_BAUD_RATE *16))-1
        void wait(int time)
        {
        do{
        time--;
        }
        while(time>0);
        }

        void init_uart()
        {
        GPHCON |=0xa0;
        GPHUP = 0x0c;
        ULCON0 = 0x3;
        UCON0 = 0x5+ (1<<8);
        UFCON0 = 0;
        UMCON0 = 0;
        UBRDIV0 = UART_BRD;
        }

        void init_led()
        {
        GPECON = GPE12_out|GPE13_out;
        }

        void uart_write(char *data)
        {
        while (*data !=

        主站蜘蛛池模板: 丹东市| 水富县| 宜春市| 麻江县| 遂川县| 山阳县| 应用必备| 长阳| 上杭县| 浠水县| 红原县| 安康市| 玛曲县| 桃园县| 乌鲁木齐县| 隆安县| 青神县| 乃东县| 台南市| 屯门区| 西城区| 蓬安县| 无锡市| 从江县| 湘乡市| 特克斯县| 汉寿县| 南皮县| 格尔木市| 崇义县| 石渠县| 永济市| 定远县| 乌鲁木齐县| 三台县| 米泉市| 新竹市| 华亭县| 务川| 扎兰屯市| 兴和县|