1. 程式人生 > >ARM基本介面之外部中斷實驗

ARM基本介面之外部中斷實驗

實驗名稱ARM基本介面之外部中斷實驗

實驗目的

1. 瞭解中斷的作用;

2. 掌握嵌入式系統中斷的處理流程;

3. 掌握ARM外部中斷程式設計。

實驗內容(含步驟)

1. 總體步驟:先編譯,啟動目標機,待顯示2440後,進行建立連結,下載,執行,觀察是否顯示HELLOO,按下EXINT2按鈕看led燈是否變換顯示效果

2. 實驗過程:在實驗過程中,始終顯示硬體連線失敗,組員認為是目標機與電腦連線問題,拔了插過,但仍然不行,後來多次更換電腦連線,花費了大量時間,終於解決問題,然後在緊迫的時間內修改程式碼,編譯,連結,下載,執行,終於成功顯示效果。理解原理後,通過在主程式中執行數碼管顯示程式碼,使得宿主機能正確顯示

HELLOO字樣,然後通過按下EXINT2按鈕請求中斷,執行中斷服務程式,使得led燈能變換顯示

3.程式碼如下:

/****************************************************************************/

/*實驗現象: 共陽數碼管顯示HELLOO,觸發外部中斷後,led燈由奇數管亮(滅)轉變為偶數管亮(滅)*/

/****************************************************************************/

 

#define U8 unsigned char

/*HELLOO的字元編碼*/

unsigned char hello[6] = {

0x89, 0x86, 0xc7, 0xc7, 0xc0, 0xc0,

};

/*六個數碼管只亮一個的狀態編碼*/

unsigned char con[6] = {

0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe

};

 

void myDelay(int time);

Void Delay(int time);

 

/********************************************************************

// Function name	: Isr_Init

// Description	    : 中斷初始化功能

// Return type	: void

// Argument         : void

*********************************************************************/

void Isr_Init(void)

{

    pISR_UNDEF  = (unsigned)HaltUndef;

    pISR_SWI    = (unsigned)HaltSwi;

    pISR_PABORT = (unsigned)HaltPabort;

    pISR_DABORT = (unsigned)HaltDabort;

 

    rINTMOD     = 0x0;                     //中斷模式設定為IRQ

    rINTMSK     = BIT_ALLMSK;              //All interrupt is masked.

    rINTSUBMSK  = BIT_SUB_ALLMSK;          //All sub-interrupt is masked.

}

 

/********************************************************************

// Function name	: Isr_Request

// Description	    : 註冊中斷函式(中斷請求)

// Return type	: void

// Argument         : int irq_no

//                    #define IRQ_EINT0     1

//                    #define IRQ_EINT1     2

//                    #define IRQ_EINT2     3

//                    #define IRQ_EINT3     4 //**

//                    #define IRQ_EINT4_7   5

//                    #define IRQ_EINT8_23  6

//                    #define IRQ_NOTUSED6  7

//                    #define IRQ_BAT_FLT   8

//                    #define IRQ_TICK      9

//                    #define IRQ_WDT       10

//                    #define IRQ_TIMER0    11

//                    #define IRQ_TIMER1    12

//                    #define IRQ_TIMER2    13

//                    #define IRQ_TIMER3    14

//                    #define IRQ_TIMER4    15

//                    #define IRQ_UART2     16

//                    #define IRQ_LCD       17

//                    #define IRQ_DMA0      18

//                    #define IRQ_DMA1      19

//                    #define IRQ_DMA2      20

//                    #define IRQ_DMA3      21

//                    #define IRQ_SDI       22

//                    #define IRQ_SPI0      23

//                    #define IRQ_UART1     24

//                    #define IRQ_NOTUSED24 25

//                    #define IRQ_USBD      26

//                    #define IRQ_USBH      27

//                    #define IRQ_IIC       28

//                    #define IRQ_UART0     29

//                    #define IRQ_SPI1      30

//                    #define IRQ_RTC       31

//                    #define IRQ_ADC       32

// Argument         : void* irq_routine

*********************************************************************/

//第一個引數表示中斷請求源, 第二個引數為該中斷請求源定義的中斷服務函式

void Irq_Request(int irq_no, void* irq_routine)

{

if(irq_no >= IRQ_MIN && irq_no <= IRQ_MAX)

*(unsigned int*)((irq_no - 1) * sizeof(unsigned int) + (unsigned int)(_ISR_STARTADDRESS+0x20)) = (unsigned int)irq_routine;

// _ISR_STARTADDRESS+0x20 就是跳過前面的異常向量,進入IRQ中斷向量的入口

// 三級跳到指定地址,即從flash中跳到了RAM的中斷入口,然後又從中斷入口跳到中斷//分發例程入口

}

 

/********************************************************************

// Function name	: Irq_Enable

// Description	    : 開中斷

// Return type	: void

// Argument         : int irq_no

*********************************************************************/

//引數表示中斷請求源,該函式使能某中斷

void Irq_Enable(int irq_no)

{

if(irq_no >= IRQ_MIN && irq_no <= IRQ_MAX)

rINTMSK &= ~(1 << (irq_no - 1));//全部置零,使能中斷

}

 

/********************************************************************

// Function name	: Irq_Disable

// Description	    : 關中斷

// Return type	: void

// Argument         : int irq_no

*********************************************************************/

//引數表示中斷請求源,該函式禁止某中斷

void Irq_Disable(int irq_no)

{

if(irq_no >= IRQ_MIN && irq_no <= IRQ_MAX)

rINTMSK |= (1 << (irq_no - 1));//置1,禁止中斷

}

 

/********************************************************************

// Function name	: Irq_Clear

// Description	    : 清除中斷

// Return type	: void

// Argument         : int irq_no

*********************************************************************/

//引數表示中斷請求源,該函式清除某中斷請求

void Irq_Clear(int irq_no)

{

    rSRCPND = (1 << (irq_no - 1));//置1,將該暫存器的相應位清零

    rINTPND = (1 << (irq_no - 1));//置1,將該暫存器的相應位清零

    rINTPND;

}

 

/*****************************************************************************

// Function name	: eint2_isr

// Description	    : 主函式

// Return type	: void

// Argument         : void

*****************************************************************************/

void Main(void)

{

/* 配置系統時鐘 */

    ChangeClockDivider(2,1);

    U32 mpll_val = 0 ;

    mpll_val = (92<<12)|(1<<4)|(1);

    ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3);

 

/* 中斷初始化 */

    Isr_Init();

    /* 初始化埠 */

    Port_Init();

 

    /* 初始化串列埠 */

    Uart_Init(0,115200);

    Uart_Select(0);

 

    /* 列印提示資訊 */

PRINTF("\n---外部中斷測試程式---\n");

PRINTF("\n請將UART0與PC串列埠進行連線,然後啟動超級終端程式(115200, 8, N, 1)\n");

PRINTF("\n外部中斷測試開始\n");

 

/* 請求中斷 */

Irq_Request(IRQ_EINT3, eint3_isr);

 

    /* 使能中斷 */

    Irq_Enable(IRQ_EINT3);

 

    dither_count2 = 0;

    dither_count3 = 0;

 

    while(1){

    	int i, j;

        int flag = 1;

 

        for(j=0; ; j++)	{

            *((U8*) 0x20007000) = 0x80;

            /* 數碼管從0到F依次將字元顯示出來 */

            for(i=0;i<6;i++){

                /* 查表並輸出資料 */

                *((U8*) 0x20007000) = con[i] ;

                *((U8*) 0x20006000) = hello[i];

                myDelay(1);

            }

            dither_count3++;

         }

    }

}

 

/*****************************************************************************

// Function name	: eint3_isr

// Description	    : EINT3中斷處理程式

// Return type	: int

// Argument      : void

*****************************************************************************/

void eint3_isr(void)

{

Irq_Clear(IRQ_EINT3);//清除中斷

 

    if(dither_count3 > 10)//如果count大於10,變換led顯示

    {

   	dither_count3 = 0;//清零

Led_Display(nLed);//led顯示

nLed = ~nLed;

}

}

實驗總結

lg:在計算機組成原理和作業系統中都接觸過中斷,有個大概瞭解,但都是理論上的,通過這次外部中斷實驗,有種理論聯絡實際的感覺,想起了組成原理說過的MASK。實驗中知道了註冊中斷,開中斷,清除中斷對中斷暫存器INTMSK,SRCPND,INTPND的寫操作,和中斷執行的三級跳,對中斷有了更深入的理解

zhy:這次的實驗,我們組花了很多時間在裝置的連線上,實際修改程式碼,操作比較少,所以就有了更多的時間去看程式碼。在程式碼中具體實現了中斷的整個過程,用了兩個重要的暫存器:中斷掛起暫存器(INTPND),中斷遮蔽暫存器(INTMSK),什麼時候置0還是置1都是有依據的。這次的外部中斷是外部通過按按鈕來進行中斷,並讓

led燈實現奇偶間斷燈亮起,很有中斷的感覺。

wq:以前學過的中斷都是比較表面的,理解的也比較淺,通過這次的中斷實驗,進入到硬體底層,我們對機器內的中斷過程有了更加深入的瞭解。以及註冊中斷、開中斷、清除中斷的具體函式實現。這次的外部中斷是通過按鍵來中斷的現行程式,使得LED燈可以變換顯示。但是非常遺憾這次實驗由於我們組連線機器時間過長,導致實驗時間極短,並沒有學得盡興。

yy:這次實驗的課題是ARM基本介面之外部中斷,中斷的典型步驟是:儲存現場,模式切換,獲取中斷源,處理中斷,中斷返回。不得不說這次的實驗較以往難度更高,程式碼讀起來也更加晦澀難懂,也涉及到了更多關於底層的知識,但實驗完成之後確實感覺對中斷有了進一步的瞭解

cxy:這次實驗的內容是中斷。以前經常在作業系統和計算機組成原理上聽到中斷的介紹,但是一直沒有真正瞭解過中斷的具體實現。這次實驗讓我瞭解中斷的具體。