新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > S3C2440定時(shí)器4中斷測試程序

        S3C2440定時(shí)器4中斷測試程序

        作者: 時(shí)間:2016-11-26 來源:網(wǎng)絡(luò) 收藏
        __irq為一個(gè)標(biāo)識(shí),用來表示一個(gè)函數(shù)是否為中斷函數(shù)。對于不同的編譯器,__irq在函數(shù)名中的位置不一樣,例如:

        ADS編譯器中: void __irq IRQ_Eint0(void);
        Keil編譯器中 : void IRQ_Eint0(void) __irq;
        但是其意義一樣,它所完成的任務(wù)是標(biāo)識(shí)該函數(shù)為中斷函數(shù),在編譯器編譯是調(diào)用此函數(shù)時(shí),先保護(hù)函數(shù)入口現(xiàn)場,然后執(zhí)行中斷函數(shù),函數(shù)執(zhí)行完畢,恢復(fù)中斷現(xiàn)場,這整個(gè)過程不需要用戶重新編寫代碼來完成,由編譯器自動(dòng)完成。因而這也給不具備中斷嵌套功能的ARM系統(tǒng)帶來了問題,若使用 __irq 時(shí)有中斷嵌套產(chǎn)生,這現(xiàn)場保護(hù)就會(huì)混亂。中斷嵌套處理可以自己編寫中斷入口現(xiàn)場保護(hù)代碼,并不使用 __irq 標(biāo)識(shí)符號(hào)。(小呆:具體如何編寫可以嵌套的中斷這里暫時(shí)不做研究。
        總結(jié)如下
        1、若不想自己編寫中斷入口現(xiàn)場保護(hù)代碼,而且使用中無中斷嵌套,在中斷函數(shù)中用 __irq 來標(biāo)識(shí)我們的中斷函數(shù),否則出錯(cuò);
        2、若程序中要使用中斷嵌套,對于無中斷嵌套功能的ARM來說,一定要自己編寫中斷入口現(xiàn)場保護(hù)代碼,而且不能用 __irq 標(biāo)識(shí)我們的中斷函數(shù),否則出錯(cuò)。
        __irq關(guān)鍵字
        在ADS編譯器中,“__irq”專門用來聲明IRQ中斷服務(wù)程序,如果用“__irq”來聲明一個(gè)函數(shù),那么該函數(shù)表示一個(gè)IRQ中斷服務(wù)程序,編譯器便會(huì)自動(dòng)在該函數(shù)內(nèi)部增加中斷現(xiàn)場保護(hù)的代碼。同樣一個(gè)函數(shù),如果將關(guān)鍵字“__irq”去掉,那么編譯器便不會(huì)增加現(xiàn)場保護(hù)的代碼,而只是作為一個(gè)普通函數(shù)來處理。
        現(xiàn)在大家應(yīng)該對“__irq”關(guān)鍵字有了一定的了解,那么,是不是所有的IRQ中斷服務(wù)程序都需要使用“__irq”關(guān)鍵字聲明呢?其實(shí),這取決于獲取“中斷服務(wù)程序地址”的方法:
        如果在執(zhí)行中斷服務(wù)函數(shù)之前沒有對中斷現(xiàn)場進(jìn)行保護(hù),那么中斷服務(wù)函數(shù)必須要使用“__irq”關(guān)鍵字進(jìn)行聲明。例如,在0x0000 0018處執(zhí)行指令“LDR PC, [PC, #-0xff0]”,此時(shí)對應(yīng)的中斷服務(wù)函數(shù)必須要使用“__irq”關(guān)鍵字進(jìn)行聲明;如果在執(zhí)行中斷服務(wù)函數(shù)之前已經(jīng)對中斷現(xiàn)場進(jìn)行了保護(hù),那么中斷服務(wù)函數(shù)不能使用“__irq”關(guān)鍵字進(jìn)行聲明。

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

        //=========================================
        // NAME: main.c
        // DESC: 內(nèi)部定時(shí)器4LED燈延時(shí)
        //=========================================

        #define U32 unsigned int


        #define _ISR_STARTADDRESS 0x33ffff00

        #define pISR_TIMER4(*(unsigned *)(_ISR_STARTADDRESS+0x58))

        #define rSRCPND(*(volatile unsigned *)0x4a000000) //Interrupt request status 源掛起寄存器
        #define rINTMSK(*(volatile unsigned *)0x4a000008)//Interrupt mask control中斷屏蔽寄存器
        #define rINTPND(*(volatile unsigned *)0x4a000010) //Interrupt request status 中斷掛起寄存器

        #define rTCFG0(*(volatile unsigned *)0x51000000)//Timer 0 configuration
        #define rTCFG1(*(volatile unsigned *)0x51000004)//Timer 1 configuration
        #define rTCON(*(volatile unsigned *)0x51000008)//Timer control
        #define rTCNTB4 (*(volatile unsigned *)0x5100003c)//Timer count buffer 4

        #define rGPBCON(*(volatile unsigned *)0x56000010) //Port B control
        #define rGPBDAT(*(volatile unsigned *)0x56000014) //Port B data
        #define rGPBUP(*(volatile unsigned *)0x56000018)//Pull-up control B

        void led_init(void)
        {
        //板載LED為GPB[5:8]
        rGPBCON = (rGPBCON & ~(0xff<<10)) | (0x55<<10);//rGPBCON為01 配置為輸出
        rGPBUP= rGPBUP| (0xf<<5);//rGPBUP為1禁止上拉
        rGPBDAT = rGPBDAT | (0xf<<5);//LED燈全關(guān)
        }

        void led_display(unsigned char data)
        {
        //0x0全滅 0xf全亮 0x01 0x02 0x04 0x80 各自燈亮
        rGPBDAT = (rGPBDAT & ~(0xf<<5)) | ((~data) <<5);
        }

        void timer4_init(void)
        {
        rSRCPND = rSRCPND | (0x1<<14);//清空定時(shí)器4源請求
        rINTPND = rINTPND | (0x1<<14); //清空定時(shí)器4中斷請求
        rINTMSK =rINTMSK & ~(0x1<<14);//打開定時(shí)器4中斷
        //定時(shí)器配制寄存器0
        //定時(shí)器輸入時(shí)鐘頻率 = PCLK / {預(yù)分頻值+1} / {分頻值}
        //{預(yù)分頻值} = 0~255 {分頻值} = 2, 4, 8, 16
        //25KHz:50MHz/(250*8)=50MHz/(2000)
        rTCFG0 = (rTCFG0 & ~(0xff<<8)) | (249<<8);// prescaler1:249
        rTCFG1 = (rTCFG1 & ~(0xf<<16)) | (0x2<<16);//divider:8,0b0010

        rTCNTB4 = 25000;//讓定時(shí)器4每隔1秒中斷一次 25000=1*25000
        rTCON = (rTCON & ~(0x7<<20)) | (0x7<<20);//自動(dòng)重載、手動(dòng)更新、啟動(dòng)定時(shí)器4
        rTCON = (rTCON & ~(0x2<<20));//關(guān)閉手動(dòng)更新
        }

        void __irq timer4_ISR(void)
        {
        static int count;
        rSRCPND = rSRCPND | (0x1<<14);
        rINTPND = rINTPND | (0x1<<14);
        //每隔0.5秒LED燈亮一次
        if (count == 0)
        {
        led_display(0xf);//LED亮
        count = 1;
        }
        else if (count == 1)
        {
        led_display(0x0);//LED滅
        count = 0;
        }
        }

        void Main(void)
        {
        led_init();
        timer4_init();

        pISR_TIMER4 = (U32)timer4_ISR;
        while(1);
        }

        -------------------------------------

        pISR_UNDEF=(unsigned)HaltUndef;

        任何地址都可以看作變量的指針.pISR_UNDEF就相當(dāng)于一個(gè)指針變量.pISR_UNDEF=(unsigned)HaltUndef;等于把函數(shù)HaltUndef的地址存到這個(gè)指針變量里.也就是說_ISR_STARTADDRESS+0x4這個(gè)地址里存放著HaltUndef的地址.這段代碼的目的是給中斷函數(shù)賦值.當(dāng)發(fā)生中斷時(shí),系統(tǒng)會(huì)去pISR_UNDEF定義的地址里取出中斷函數(shù)的地址也就是HaltUndef的地址,然后執(zhí)行.就相當(dāng)于當(dāng)發(fā)生中斷時(shí),執(zhí)行HaltUndef函數(shù).



        關(guān)鍵詞: S3C2440定時(shí)器中斷測

        評(píng)論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 谷城县| 临海市| 潮安县| 青铜峡市| 白水县| 南部县| 资兴市| 屏东县| 鹿泉市| 资溪县| 金阳县| 山西省| 深州市| 庆云县| 潮州市| 中牟县| 新野县| 柘城县| 庄河市| 乌拉特中旗| 沭阳县| 关岭| 雅安市| 横山县| 资兴市| 文成县| 清涧县| 茌平县| 平罗县| 万州区| 左云县| 沾化县| 深水埗区| 定安县| 海晏县| 武川县| 东乌珠穆沁旗| 八宿县| 霍林郭勒市| 南岸区| 九龙坡区|