亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

arm9中斷結構是怎樣的

發布時間:2021-12-20 10:45:09 來源:億速云 閱讀:159 作者:iii 欄目:互聯網科技

這篇文章主要講解了“arm9中斷結構是怎樣的”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“arm9中斷結構是怎樣的”吧!

S3C2440的中斷分為兩大類: 外部中斷 和 內部中斷.

一 外部中斷

arm9中斷結構是怎樣的

EXTINT[x]: 用來配置各個引腳的中斷觸發方式 (高電平觸發、低電平觸發、下降沿觸發、上升沿觸發), 注意該寄存器與中斷源的對應關系

EINTPEND[x]:  xxxPEND的寄存器都是狀態寄存器, 初始化時先清除標志, 在清除中斷的時候將寄存器的值賦值給本身即可

EINTMSK[x]: 1 屏蔽中斷; 0 未屏蔽

SRCPEND[x]: 1 申請中斷;  0 未申請中斷

EINTFLT0~EINTFLT3: 配置濾波時鐘和濾波寬度

INTMOD[x]: 1: FIQ, 0: IRQ

二 內部中斷

內部中斷分兩種: 帶子中斷的中斷 和 不帶子中斷的中斷

  1. 不帶子中斷:  發生中斷后 SRCPEND置位, 如果沒有被 INTMSK屏蔽, 那么繼續向下一步申請中斷

  2. 帶子中斷: 發生中斷之后, 先將 SUBSRCPEND 置位, 如果沒有INTSUBMSK屏蔽則向 SRCPEND申請中斷. 如果沒有被INTMSK屏蔽則進一步向下申請中斷

arm9中斷結構是怎樣的

中斷的優先級:

ARB_MODEx: 控制中斷優先級是否輪轉

ARB_SELx: 控制輪轉順序

中斷的開啟(xxxMSK):

1 外部中斷: EINT4~23先初始化EINTMSK 和 INTMSK, 如果是EINT0~3直接初始化INTMSK

2 內部中斷: 有子中斷先初始化 INTSUBMSK 再初始化 INTMSK, 如果是不帶子中斷的內部中斷直接初始化 INTMSK 

中斷的清除(xxxPEND):

1 外部中斷: 如果是EINT4~23 先清除EINTPEND 再清除 INTPEND (注意順序), 如果是 EINT0~3 直接清除SRCPEND.  (不需要清除 INTPEND???)

2 內部中斷: 帶子中斷, 先清除 SUBSRCPEND再清除SRCPEND(注意順序);   不帶子中斷直接清除SRCPEND

3 清除中斷是寫 1 清除

三 代碼解析 

@******************************************************************************
@ 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       @ 進入中斷模式
    ldr sp, =3072           @ 設置中斷模式棧指針

    msr cpsr_c, #0xd3       @ 進入管理模式, reset之后就是管理模式, 所以這里的設置和reset下的ldr sp, =4096為一個作用, 本條代碼可以省略
    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

注意: 1. 這里中斷并不是根據名字來確定的, 而是根據中斷向量的地址(0x0 / 0x4 / 0x8 / 0xc / 0x10...). IRQ正是0x18. 只需要在該位置放置一條跳轉指令即可實現中斷isr.  這是只要是IRQ都要從這一個入口進入中斷, 然后再檢查到底是哪個源申請了中斷.

芯片在各個模式之下使用的是不同的sp和lr寄存器, reset之后就是管理模式, 所以管理模式的ldr sp, =4096是等價于reset下的那條sp語句

// init.c: 初始化LED及 中斷
#include "s3c24xx.h"

// LED1,LED2,LED4對應GPF4、GPF5、GPF6
#define	GPF4_out	(1<<(4*2))
#define	GPF5_out	(1<<(5*2))
#define	GPF6_out	(1<<(6*2))

#define	GPF4_msk	(3<<(4*2))
#define	GPF5_msk	(3<<(5*2))
#define	GPF6_msk	(3<<(6*2))

/*
 * S2,S3,S4對應GPF0、GPF2、GPG3
 */
#define GPF0_eint     (0x2<<(0*2))
#define GPF2_eint     (0x2<<(2*2))
#define GPG3_eint     (0x2<<(3*2))

#define GPF0_msk    (3<<(0*2))
#define GPF2_msk    (3<<(2*2))
#define GPG3_msk    (3<<(3*2))

// 關閉WATCHDOG,否則CPU會不斷重啟
void disable_watch_dog(void)
{
    WTCON = 0;  // 關閉WATCHDOG很簡單,往這個寄存器寫0即可
}

void init_led(void)
{
    // LED1,LED2,LED4對應的3根引腳設為輸出
    GPFCON &= ~(GPF4_msk | GPF5_msk | GPF6_msk);
    GPFCON |= GPF4_out | GPF5_out | GPF6_out;
}

/* 初始化GPIO引腳為外部中斷
 * GPIO引腳用作外部中斷時,默認為低電平觸發、IRQ方式(不用設置INTMOD)
 */
void init_irq( )
{
    // S2,S3對應的2根引腳設為中斷引腳 EINT0,ENT2
    GPFCON &= ~(GPF0_msk | GPF2_msk);
    GPFCON |= GPF0_eint | GPF2_eint;

    // S4對應的引腳設為中斷引腳EINT11
    GPGCON &= ~GPG3_msk;
    GPGCON |= GPG3_eint;

    // 對于EINT11,需要在EINTMASK寄存器中使能它
    EINTMASK &= ~(1<<11);

    /*
     * 設定優先級:
     * ARB_SEL0 = 00b, ARB_MODE0 = 0: REQ1 > REQ3,即EINT0 > EINT2
     * 仲裁器1、6無需設置
     * 最終:
     * EINT0 > EINT2 > EINT11即K2 > K3 > K4
     */
    PRIORITY &= ((((~0x01) | (0x3<<7))) | (0x0 << 7)) ;

    // EINT0、EINT2、EINT8_23使能
    INTMSK   &= (~(1<<0)) & (~(1<<2)) & (~(1<<5));
}

中斷初始化步驟:

(1) 設置好 IRQ 和 FIQ 的棧

(2) 準備中斷處理函數

    1. 異常向量中設置好跳轉函數

    2. 中斷服務程序(ISR)

    3. 清除中斷

    4. 保護現場, 恢復現場

(3) 根據中斷源設置相關外設

  1. 外部中斷: 設置引腳為"外部中斷", 設置中斷觸發方式, 開啟對應的屏蔽寄存器, EINTMSK

  2. 內部中斷: 將INTSUBMSK開啟

(4)確定中斷的使用方式: IRQ 或 FIQ

  1. FIQ: 在 INTMOD 設置相應的bit為1

  2. IRQ: 在PRIORITY寄存器中設置優先級, 將 INTMSK中設置為0 (FIQ不受INTMSK影響)

(5) 置位 CPSR中的 I-bit(IRQ) 或 F-bit(FIQ)

#include "s3c24xx.h"

void EINT_Handle()
{
    unsigned long oft = INTOFFSET;//INTPND[X]為1,則INTOFFSET為x 
    unsigned long val;
    
    switch( oft )
    {
        // S2被按下
        case 0: 
        {   
            GPFDAT |= (0x7<<4);   // 所有LED熄滅
            GPFDAT &= ~(1<<4);      // LED1點亮
            break;
        }
        
        // S3被按下
        case 2:
        {   
            GPFDAT |= (0x7<<4);   // 所有LED熄滅
            GPFDAT &= ~(1<<5);      // LED2點亮
            break;
        }

        // K4被按下
        case 5:
        {   
            GPFDAT |= (0x7<<4);   // 所有LED熄滅
            GPFDAT &= ~(1<<6);      // LED4點亮                
            break;
        }
        
        //K1 或 K2 被按下, 假設K1 k2 接在EINT8~23, 查詢INTPEND[5]之后還要查詢EINTPEND[x]來確定EINT8~EINT23
        case 5:
        {
            GPBDAT |= (0x0f << 5);//所有LED熄滅
            
            //需要進一步判斷是k1 還是 k2, 或是 同時按下
            val = EINTPEND;
            if (val & (1 << 11))
            {
                GPBDAT &= ~(1 << 6);//K2
            }
            if (val & (1 << 19))
            {
                GPBDAT &= ~(1 << 5);//K1
            }
            break;
        }

        default:
            break;
    }

    //清中斷
    if( oft == 5 )  //如果是外部中斷則要多清除EINTPEND這個寄存器 
        EINTPEND = (1<<11);   // EINT8_23合用IRQ5,SRCPND[5], INTPND[5]
        
    SRCPND = 1<<oft;
    INTPND = 1<<oft;
}

這里oft表示INTOFFSET寄存器的值, INTPND[x]為1, oft就是x. 該值為5表示 EINT8-23的中斷源, 這時再查看 EINTPEND來確定到底是哪個引腳.

感謝各位的閱讀,以上就是“arm9中斷結構是怎樣的”的內容了,經過本文的學習后,相信大家對arm9中斷結構是怎樣的這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

arm
AI

胶南市| 通辽市| 中宁县| 鄂尔多斯市| 广丰县| 锡林浩特市| 繁峙县| 长子县| 安国市| 凤台县| 资讯| 阿坝| 萝北县| 大渡口区| 平潭县| 平南县| 江孜县| 正定县| 长泰县| 金乡县| 鲁甸县| 曲麻莱县| 阳泉市| 稷山县| 新营市| 策勒县| 疏附县| 九龙坡区| 安溪县| 正蓝旗| 潼关县| 社旗县| 高阳县| 博罗县| 武清区| 和平县| 天长市| 册亨县| 北票市| 肥东县| 澄江县|