<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          S3C2440外部中斷詳解

          作者: 時(shí)間:2016-12-02 來源:網(wǎng)絡(luò) 收藏
          要想正確地執(zhí)行2440的外部中斷,一般需要完成兩個(gè)部分內(nèi)容:中斷初始化和中斷處理函數(shù)。
          在具體執(zhí)行中斷之前,要初始化好要用的中斷。2440的外部中斷引腳EINT與通用IO引腳F和G復(fù)用,要想使用中斷功能,就要把相應(yīng)的引腳配置成中斷模式,如我們想把端口F0設(shè)置成外部中斷,而其他引腳功能不變,則GPFCON=(GPFCON & ~0x3) | 0x2。配置完引腳后,還需要配置具體的中斷功能。我們要打開某一中斷的屏蔽,這樣才能響應(yīng)該中斷,相對(duì)應(yīng)的寄存器為INTMSK;還要設(shè)置外部中斷的觸發(fā)方式,如低電平、高電平、上升沿、下降沿等,相對(duì)應(yīng)的寄存器為EXTINTn。另外由于EINT4到EINT7共用一個(gè)中斷向量,EINT8到EINT23也共用一個(gè)中斷向量,而INTMSK只負(fù)責(zé)總的中斷向量的屏蔽,要具體打開某一具體的中斷屏蔽,還需要設(shè)置EINTMASK。上面介紹的是最基本的初始化,當(dāng)然還有一些其他的配置,如當(dāng)需要用到快速中斷時(shí),要使用INTMOD,當(dāng)需要配置中斷優(yōu)先級(jí)時(shí),要使用PRIORITY等。
          中斷處理函數(shù)負(fù)責(zé)執(zhí)行具體的中斷指令,除此以外還需要把SRCPND和INTPND中的相應(yīng)的位清零(通過置1來清零),因?yàn)楫?dāng)中斷發(fā)生時(shí),2440會(huì)自動(dòng)把這兩個(gè)寄存器中相對(duì)應(yīng)的位置1,以表示某一中斷發(fā)生,如果不在中斷處理函數(shù)內(nèi)把它們清零,系統(tǒng)會(huì)一直執(zhí)行該中斷函數(shù)。另外還是由于前面介紹過的,有一些中斷是共用一個(gè)中斷向量的,而一個(gè)中斷向量只能有一個(gè)中斷執(zhí)行函數(shù),因此具體是哪個(gè)外部中斷,還需要EINTPEND來判斷,并同樣還要通過置1的方式把相應(yīng)的位清零。一般來說,使用__irq這個(gè)關(guān)鍵詞來定義中斷處理函數(shù),這樣系統(tǒng)會(huì)為我們自動(dòng)保存一些必要的變量,并能夠在中斷處理函數(shù)執(zhí)行完后正確地返回。還需要注意的是,中斷處理函數(shù)不能有返回值,也不能傳遞任何參數(shù)。
          為了把這個(gè)中斷處理函數(shù)與在2440啟動(dòng)文件中定義的中斷向量表相對(duì)應(yīng)上,需要先定義中斷入口地址變量,該中斷入口地址必須與中斷向量表中的地址一致,然后把該中斷處理函數(shù)的首地址傳遞給該變量,即中斷入口地址。
          下面就是一個(gè)外部中斷的實(shí)例。開發(fā)板上一共有四個(gè)按鍵,分別連到了EINT0,EINT1,EINT2和EINT4,我們讓這四個(gè)按鍵分別控制連接在B5~B8引腳上的四個(gè)LED:按一下鍵則LED亮,再按一下則滅:
          #define _ISR_STARTADDRESS 0x33ffff00
          #define U32 unsigned int
          #define pISR_EINT0 (*(unsigned *)(_ISR_STARTADDRESS+0x20))
          #define pISR_EINT1 (*(unsigned *)(_ISR_STARTADDRESS+0x24))
          #define pISR_EINT2 (*(unsigned *)(_ISR_STARTADDRESS+0x28))
          #define pISR_EINT4_7 (*(unsigned *)(_ISR_STARTADDRESS+0x30))
          #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 rGPBCON (*(volatile unsigned *)0x56000010) //Port B control
          #define rGPBDAT (*(volatile unsigned *)0x56000014) //Port B data
          #define rGPBUP (*(volatile unsigned *)0x56000018) //Pull-up control B
          #define rGPFCON (*(volatile unsigned *)0x56000050) //Port F control
          #define rEXTINT0 (*(volatile unsigned *)0x56000088) //External interrupt control register 0
          #define rEINTMASK (*(volatile unsigned *)0x560000a4) //External interrupt mask
          #define rEINTPEND (*(volatile unsigned *)0x560000a8) //External interrupt pending
          static void __irq Key1_ISR(void) //EINT1
          {
          int led;
          rSRCPND = rSRCPND | (0x1<<1);
          rINTPND = rINTPND | (0x1<<1);
          led = rGPBDAT & (0x1<<5);
          if (led ==0)
          rGPBDAT = rGPBDAT | (0x1<<5);
          else
          rGPBDAT = rGPBDAT & ~(0x1<<5);
          }
          static void __irq Key2_ISR(void) //EINT4
          {
          int led;
          rSRCPND = rSRCPND | (0x1<<4);
          rINTPND = rINTPND | (0x1<<4);
          if(rEINTPEND&(1<<4))
          {
          rEINTPEND = rEINTPEND | (0x1<<4);
          led = rGPBDAT & (0x1<<6);
          if (led ==0)
          rGPBDAT = rGPBDAT | (0x1<<6);
          else
          rGPBDAT = rGPBDAT & ~(0x1<<6);
          }
          }
          static void __irq Key3_ISR(void) //EINT2
          {
          int led;
          rSRCPND = rSRCPND | (0x1<<2);
          rINTPND = rINTPND | (0x1<<2);
          led = rGPBDAT & (0x1<<7);
          if (led ==0)
          rGPBDAT = rGPBDAT | (0x1<<7);
          else
          rGPBDAT = rGPBDAT & ~(0x1<<7);
          }
          void __irq Key4_ISR(void) //EINT0
          {
          int led;
          rSRCPND = rSRCPND | 0x1;
          rINTPND = rINTPND | 0x1;
          led = rGPBDAT & (0x1<<8);
          if (led ==0)
          rGPBDAT = rGPBDAT | (0x1<<8);
          else
          rGPBDAT = rGPBDAT & ~(0x1<<8);
          }
          void Main(void)
          {
          int light;
          rGPBCON = 0x015550;
          rGPBUP = 0x7ff;
          rGPFCON = 0xaaaa;
          rSRCPND = 0x17;
          rINTMSK = ~0x17;
          rINTPND =0x17;
          rEINTPEND = (1<<4);
          rEINTMASK = ~(1<<4);
          rEXTINT0 = 0x20222;
          light = 0x0;
          rGPBDAT = ~light;
          pISR_EINT0 = (U32)Key4_ISR;
          pISR_EINT1 = (U32)Key1_ISR;
          pISR_EINT2 = (U32)Key3_ISR;
          pISR_EINT4_7 = (U32)Key2_ISR;
          while(1)
          ;
          }
          /******************************************************************************************************************************************************************************************************/

          1.中斷分兩大類:內(nèi)部中斷和外部中斷。

          本文引用地址:http://www.ex-cimer.com/article/201612/325056.htm

          2.外部中斷。24個(gè)外部中斷占用GPF0-GPF7(EINT0-EINT7),GPG0-GPG15(EINT8-EINT23)。用這些腳做中斷輸入,則必須配置引腳為中斷,并且不要上拉。具體參考datesheet數(shù)據(jù)手冊(cè)。

          寄存器:EXTINT0-EXTINT2:三個(gè)寄存器設(shè)定EINT0-EINT23的觸發(fā)方式。

          EINTFLT0-EINTFLT3:控制濾波時(shí)鐘和濾波寬度。

          EINTPEND:這個(gè)是中斷掛起寄存器,清除時(shí)要寫1,后面還有幾個(gè)是寫1清除。當(dāng)一個(gè)外部中斷(EINT4-EINT23)發(fā)生后,那么相應(yīng)的位會(huì)被置1。為什么沒有EINT0-EINT3,呵呵,看看SRCPND就知道了,里面沒有EINT4-EINT23的位子(SRCPND第[3]位為EINT4-7組,第[4]位為EINT8-23組),所以有了EINTPENDx用以細(xì)化補(bǔ)充SRCPND。

          EINTMASK:這個(gè)簡(jiǎn)單,是屏蔽中斷用的,也就是說位為1時(shí),此次中斷無效。

          3.內(nèi)部中斷。內(nèi)部中斷有8個(gè)寄存器,下面逐一來看。

          寄存器:SUBSRCPND:當(dāng)一個(gè)中斷發(fā)生后,那么相應(yīng)的位會(huì)被置1,表示一個(gè)中斷發(fā)生了。

          INTSUBMSK:與上一個(gè)是一伙的,中斷屏蔽寄存器,具體屏蔽什么,自己看手冊(cè)去吧。

          INTMOD:中斷的方式。一個(gè)中斷可以是普通中斷,也可以是快中斷,在這里設(shè)置,但只能有一個(gè)快中斷。

          PRIORITY:優(yōu)先級(jí)寄存器,不說了。

          SRCPND:當(dāng)一個(gè)中斷發(fā)生后,那么相應(yīng)的位會(huì)被置1,表示一個(gè)或一類中斷發(fā)生了。

          INTMSK:中斷屏蔽寄存器。

          INTPND:中斷發(fā)生后,SRCPND中會(huì)有位置1,可能好幾個(gè)(因?yàn)橥瑫r(shí)可能發(fā)生幾個(gè)中斷),這些中斷會(huì)由優(yōu)先級(jí)仲裁器選出一個(gè)最緊迫的,然后把INTPND中相應(yīng)位置1,所以同一時(shí)間只有一位是1。也就是說前面的寄存器置1是表示發(fā)生了,只有INTPND置1,CPU才會(huì)處理。

          INTOFFSET:用來表示INTPND中哪一位置1了,好讓你查詢,普通中斷跳轉(zhuǎn)時(shí)查詢用。清除INTPND、SRCPND時(shí)自動(dòng)清除。

          4.各寄存器關(guān)系:

          下面看圖說明:

          5.中斷過程。

          a如果是不帶子中斷的內(nèi)部中斷:發(fā)生后SRCPND相應(yīng)位置1,如果沒有被INTMSK屏蔽,那么等待進(jìn)一步處理。

          b如果是帶子中斷的內(nèi)部中斷:發(fā)生后SUBSRCPND相應(yīng)位置1,如果沒有被INTSUBMSK屏蔽,那么SRCPND相應(yīng)位置1,等待進(jìn)一步處理,幾個(gè)SUBSRCPND可能對(duì)應(yīng)同一個(gè)SRCPND,對(duì)應(yīng)表如下:

          SRCPND SUBSRCPND
          INT_UART0 INT_RXD0,INT_TXD0,INT_ERR0
          INT_UART1 INT_RXD1,INT_TXD1,INT_ERR1
          INT_UART2 INT_RXD2,INT_TXD2,INT_ERR2
          INT_ADC INT_ADC_S, INT_TC
          INT_CAM INT_CAM_C, INT_CAM_P
          INT_WDT_AC97 INT_WDT, INT_AC97

          c如果是外部中斷:EINT0-EINT3發(fā)生后SRCPND相應(yīng)位置1,如果沒有被INTMSK屏蔽,那么等待進(jìn)一步處理。EINT4-EINT23發(fā)生后EINTPEND相應(yīng)位置1,如果沒有被EINTMASK屏蔽,那么SRCPND相應(yīng)位EINT4-7或EINT8-23置1,如果沒有被INTMSK屏蔽,等待進(jìn)一步處理。幾個(gè)EINTPEND對(duì)應(yīng)同一個(gè)SRCPND,對(duì)應(yīng)表如下:

          SRCPND EINTPEND

          EINT0 EINT0

          EINT1 EINT1

          EINT2 EINT2

          EINT3 EINT3

          EINT4-7 EINT4 EINT5EINT6EINT7

          EINT8-23 EINT8 EINT9EINT10EINT11……EINT23

          三種中斷都等待進(jìn)一步處理了。接下來從SRCPND往下看,看INTMSK。如果中斷被屏蔽了,就不用說了。如果沒有被屏蔽,那么會(huì)進(jìn)一步到INTMOD。如果是快中斷,那么直接出來,進(jìn)入FIQ(即CPU進(jìn)入快中斷模式處理)。如果是普通中斷,那么SRCPND可以有多位為置1(FIQ只能有一個(gè)),這時(shí)就會(huì)經(jīng)過PRIORITY選出一個(gè)優(yōu)先級(jí)高的,然后把根據(jù)選出的中斷把INTPND相應(yīng)位置1(注意:只能選出一個(gè)),進(jìn)入IRQ,讓CPU處理。

          6.中斷的開啟。

          a.如果是不帶子中斷的內(nèi)部中斷,只需設(shè)置INTMSK,讓它不屏蔽中斷就可以了。

          b如果是帶子中斷的內(nèi)部中斷,需設(shè)置INTSUBMSK和INTMSK,讓它們不屏蔽中斷就可以了。

          c如果是外部中斷,對(duì)于EINT8-23需要設(shè)置EINTMASK和INTMSK。對(duì)于EINT0-EINT3只需設(shè)置INTMSK。

          7.中斷的清除。

          a.如果是不帶子中斷的內(nèi)部中斷,只需清除SRCPND,注意清除需位置1。

          b如果是帶子中斷的內(nèi)部中斷,需清除SRCPND和SUBSRCPND,注意先清除SUBSRCPND,再清除SRCPND。因?yàn)?,如果你先清除SRCPND的話,然后在清除SUBSRCPND的過程中,SRCPND會(huì)以為又有中斷發(fā)生,又會(huì)置1。也就是說一次中斷會(huì)響應(yīng)兩次。所以必須先掐斷源頭。

          c如果是外部中斷,對(duì)于EINT8-23需要清除EINTPEND和SRCPND(同樣注意順序)。對(duì)于EINT0-EINT3只需清除SRCPND。

          本文詳細(xì)分析了S3C2440的中斷寄存器,對(duì)arm初學(xué)者有一定的幫助。




          關(guān)鍵詞: S3C2440外部中

          評(píng)論


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

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();