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

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > ARM系統(tǒng)中斷產生流程

          ARM系統(tǒng)中斷產生流程

          作者: 時間:2016-11-20 來源:網絡 收藏

          中斷源按照硬件位置分為外部中斷源和內部中斷源,外部中斷源和內部中斷源又包含子外部中斷源和子內部中斷源,如上圖所示(畫了一整天)。
          1.子內部中斷源的產生
          以UART0接收數(shù)據產生INT_RXD0中斷為例,INT_RXD0產生后進入SUBSRCPND子中斷源暫存寄存器,設置INT_RXD0對應的中斷位,中斷信號經過INTSUBMSK子中斷屏蔽寄存器,如果INT_RXD0信號對應位沒有被置位(屏蔽掉),中斷信號繼續(xù)向前傳遞,經過子內部中斷源聚合器,將INT_RXD0聚合成對應的中斷源信號INT_UART0,設置SRCPND中斷源暫存寄存器里INT_UART0位,經過INTMSK中斷屏蔽寄存器,如果INT_UART0信號沒有被屏蔽掉,中斷信號進入INTMOD中斷模式寄存器判斷是否為快速中斷,如果被編程為快速中斷,直接打斷ARM內核,進入中斷處理,如果中斷信號為一般中斷,進入中斷優(yōu)先級仲裁器進入優(yōu)先級仲裁,如果INT_UART0信號為最高優(yōu)先級或只有INT_UART0中斷信號產生,則該中斷信號被記錄到INTPND最高優(yōu)先級中斷暫存寄存器,同時設置INTOFFSET的值為中斷號28,最終將中斷信號打斷ARM內核進行中斷處理。如果同時產生多個中斷且INT_UART0不是最高優(yōu)先級,則該中斷信號不會被處理,等最高優(yōu)先級信號處理完后,再次進行優(yōu)先級仲裁,也就是說中斷信號不消失,一直保存在SRCPND里,只到被處理為止。
          2.內部中斷源的產生
          該過程在子內部中斷處理過程中已經包含,中斷信號產生后直接進入SRCPND里,然后經歷上述子內部中斷后期處理過程。
          3.子外部中斷的產生
          外部中斷源共有24個,其中EINT0~EINT3為外部中斷源,EINT4_7,EINT8_23為復合中斷源,他們包含有子外部中斷源。
          由于外部硬件直接掛接到I/O Ports(詳見S3C2440A硬件手冊第9章)上的,我們要想讓外設硬件中斷得到處理,要先從EINT0~EINT23里選擇中斷信號,我們以EINT11為例,介紹子外部中斷處理過程。
          通常CPU內部引出引腳都是復用的,也就是說一根CPU引腳可以有多種功能,可以設置其為輸入信號線,輸出信號線或中斷信號線,要想讓硬件產生中斷,首先要對可以產生中斷的引腳進行編程,設置該引腳為中斷信號線。EINT11中斷信號對應CPU引腳為GPG3,通過設置GPGCON[7:6] = 0b10,可以設置該引腳為中斷信號線。
          表3-14 GPGCON寄存器



          設置了CPU管腳為中斷信號線之后,還要通過設置EXTINT0寄存器來指定中斷信號的觸發(fā)方式:高電平觸發(fā),低電平觸發(fā),電平上升沿,下除沿,雙沿觸發(fā)。


          圖3-9電平信號觸發(fā)示意圖
          由于按鍵按下時讓它產生中斷,也就是從高電平變?yōu)榈碗娖綍r產生(上節(jié)按鍵中斷原理),因此我們設置EINT11中斷信號的觸發(fā)方式為下降沿觸發(fā),EXTINT1[14:12] = 0b01x
          表3-15 EXTINT1寄存器



          設置完觸發(fā)方式之后,當外設中斷信號線上的電平達到觸發(fā)條件時,通過外部中斷產生器產生中斷信號,然后將子外部中斷暫存寄存器EINTPND中對應的EINT11位置1,中斷信號再進入EINTMSK子外部中斷屏蔽寄存器,如果EINT11中斷源信號沒有被屏蔽,則EINT11中斷信號進入子外部中斷聚合器,復合成EINT8_23中斷信號,然后再經歷與前面子內部中斷信號一樣的處理機制。
          (1)EINTPEND外部中斷暫存寄存器
          表3-16外部中斷暫存寄存器(EINTPEND)
          寄存器名地址是否讀寫描述復位默認值
          EINTPEND0x560000A8R/W外部中斷信號暫存寄存器
          0:沒有中斷請求信號
          1:中斷請求信號產生
          0x0000000

          EINTPEND描述初始值
          EINT23[23]0 =未產生中斷1 =產生中斷0
          EINT4[4]0 =未產生中斷1 =產生中斷0
          保留位[3:0]0000

          (2)EINTMASK外部中斷屏蔽寄存器
          表3-17外部中斷屏蔽寄存器(EINTMASK)
          寄存器名地址是否讀寫描述復位默認值
          EINTMASK0x560000A4R/W外部中斷信號屏蔽寄存器
          0:未屏蔽,中斷可用
          1:屏蔽中斷信號
          0x000FFFFF

          EINTMASK描述初始值
          EINT23[23]0 =未屏蔽1 =屏蔽中斷1
          EINT4[4]0 =未屏蔽1 =屏蔽中斷1
          保留位[3:0]1111
          4.外部中斷源的產生
          外部中斷產生過程讀者可以根據上面中斷圖自行分析。

          按鍵控制LED燈實驗





          本實驗分三個版本,分別針對三種開發(fā)板:友善之臂QQ2440,友善之臂MINI2440,天嵌TQ2440。每種開發(fā)板對應工程在:“sys_irq_開發(fā)板名”目錄下。下面實驗內容為針對MINI2440開發(fā)板。
          head.s:
          主要實現(xiàn)安裝異常向量表,處理復位異常,初始化必要硬件,中斷入口處理等功能。
          ;**********************************************************************
          ;系統(tǒng)中斷實驗(MINI2440)
          ;**********************************************************************
          GPBCONEQU0x56000010
          GPBDATEQU0x56000014
          EXPORT SYS_IRQ
          AREASYS_IRQ,CODE,READONLY
          ENTRY
          ;**********************************************************************
          ;設置中斷向量,除Reset和HandleIRQ外,其它異常都沒有使用(如果不幸發(fā)生了,
          ;將導致死機)
          ;**********************************************************************
          ; 0x00:復位Reset異常
          bReset

          ; 0x04:未定義異常(未處理)
          HandleUndef
          bHandleUndef

          ; 0x08:軟件中斷異常(未處理)
          HandleSWI
          bHandleSWI

          ; 0x0c:指令預取異常(未處理)
          HandlePrefetchAbt
          bHandlePrefetchAbt

          ; 0x10:數(shù)據訪問中止異常(未處理)
          HandleDataAbt
          bHandleDataAbt

          ; 0x14:未使用異常(未處理)
          HandleNotUsed
          bHandleNotUsed

          ; 0x18:一般中斷異常,跳往HandleIRQ
          bHandleIRQ

          ; 0x1c:快速中斷異常(未處理)
          HandleFIQ
          bHandleFIQ

          Reset;復位異常處理入口
          ;關閉看門狗
          ldrr0, = 0x53000000
          movr1, #0
          strr1, [r0]

          blinitmem

          ldrsp,=0x32000000;設置管理模式棧指針

          IMPORT uart_init
          bluart_init; UART串口初始化

          IMPORT irq_init
          blirq_init;系統(tǒng)中斷初始化

          IMPORT key_init
          blkey_init;按鍵初始化

          IMPORT led_init
          blled_init; LED燈初始化

          msrcpsr_cxsf, #0xd2;切換到中斷模式下
          ldrsp,=0x31000000;設置中斷模式棧指針

          msrcpsr_cxsf, #0x13;返回管理模式

          ldrlr,=halt_loop;設置管理模式下返回地址
          IMPORT main
          ldrpc,=main;跳入主函數(shù)main里執(zhí)行
          ;***********************************************************************
          ;中斷處理
          ;***********************************************************************
          HandleIRQ
          sublr,lr,#4;修正返回地址
          stmdbsp!,{r0-r12,lr};保存程序執(zhí)行現(xiàn)場
          ldrlr,=int_return;設置中斷處理程序返回地址
          IMPORT handle_irq
          ldrpc,=handle_irq;跳入中斷處理程序

          int_return;中斷處理返回標簽
          ldmiasp!,{r0-r12,pc}^恢復程序執(zhí)行現(xiàn)場,返回繼續(xù)執(zhí)行

          halt_loop
          bhalt_loop

          initmem
          ldrr0, =0x48000000
          ldrr1, =0x48000034
          ;ldrr2, =memdata
          adrr2, memdata
          initmemloop
          ldrr3, [r2], #4
          strr3, [r0], #4
          teqr0, r1
          bneinitmemloop
          movpc,lr

          memdata
          DCD0x22000000;BWSCON
          DCD0x00000700;BANKCON0
          DCD0x00000700;BANKCON1
          DCD0x00000700;BANKCON2
          DCD0x00000700;BANKCON3
          DCD0x00000700;BANKCON4
          DCD0x00000700;BANKCON5
          DCD0x00018005;BANKCON6
          DCD0x00018005;BANKCON7
          DCD0x008e07a3;REFRESH
          DCD0x000000b1;BANKSIZE
          DCD0x00000030;MRSRB6
          DCD0x00000030;MRSRB7

          END;代碼結束
          該程序主要設置異常向量表,除了Reset異常和中斷處理被處理以外,其它異常都未被處理,如果發(fā)生時,會產生死循環(huán),Reset異常里主要實現(xiàn)了硬件的基本初始化,如:按鍵,LED燈等,設置棧指針,用于執(zhí)行C程序,最后跳入C程序的main函數(shù)。在中斷處理異常處理中首先修正返回地址,保存用戶執(zhí)行現(xiàn)場,跳入到中斷處理例程中執(zhí)行。
          sys_init.c:
          硬件初始化文件,里面包含LED,KEY的初始化函數(shù)。
          #include "register.h"
          #include "comm_fun.h"

          #defineTXD0READY(1<<2)//發(fā)送數(shù)據狀態(tài)OK
          #defineRXD0READY(1)//接收數(shù)據狀態(tài)OK

          /* UART串口初始化*/
          void uart_init()
          {
          GPHCON |= 0xa0;//GPH2,GPH3 used as TXD0,RXD0
          GPHUP= 0x0;//GPH2,GPH3內部上拉
          ULCON0= 0x03;//8N1
          UCON0= 0x05;//查詢方式為輪詢或中斷;時鐘選擇為PCLK
          UFCON0 = 0x00;//不使用FIFO
          UMCON0 = 0x00;//不使用流控
          UBRDIV0 = 12;//波特率為57600,PCLK=12Mhz
          }

          /* UART串口單個字符打印函數(shù)*/
          extern void putc(unsigned char c)
          {
          while( ! (UTRSTAT0 & TXD0READY) );
          UTXH0 = c;
          }

          /* UART串口接受單個字符函數(shù)*/
          extern unsigned char getc(void)
          {
          while( ! (UTRSTAT0 & RXD0READY) );
          return URXH0;
          }

          /* UART串口字符串打印函數(shù)*/
          extern int printk(const char* str)
          {
          int i = 0;
          while( str[i] ){
          utc( (unsigned char) str[i++] );
          }
          return i;
          }

          /*按鍵初始化*/
          int key_init()
          {
          //設置K1,K2,K3,K4,K5,K6對應控制寄存器為中斷模式
          GPGCON = (2<<0) | (2<<6) | (2<<10) | (2<<12) | (2<<14) | (2<<22);
          /*
          01x falling edge triggered下降沿觸發(fā)
          10x Rising edge triggered上升沿觸發(fā)
          11x Both edge triggered雙沿觸發(fā)
          */
          //設置K1,K2,K3,K4,K5按鍵中斷觸發(fā)方式為上升沿觸發(fā)
          EXTINT1 = (3<<0) | (3<<12) | (3<<20) | (3<<24) | (3<<28);
          EXTINT2 = (3<<12);//設置K6按鍵中斷觸發(fā)方式為上升沿觸
          printk("按鍵初始化OK/r/n");
          return 0;
          }

          /* Led1~Led4初始化*/
          #define LED1(1<<5)//LED1 GPBDAT[5]
          #define LED2(1<<6)//LED2 GPBDAT[6]
          #define LED3(1<<7)//LED3 GPBDAT[7]
          #define LED4(1<<8)//LED4 GPBDAT[8]

          /*點亮對應num號led燈*/
          extern int led_on(int num)
          {
          switch(num)
          {
          case 1:
          GPBDAT = GPBDAT & ~LED1; break;
          case 2:
          GPBDAT = GPBDAT & ~LED2; break;
          case 3:
          GPBDAT = GPBDAT & ~LED3; break;
          case 4:
          GPBDAT = GPBDAT & ~LED4; break;
          default:
          return 0;
          }
          return num;
          }

          /*關閉num號led燈*/
          extern int led_off(int num)
          {
          switch(num)
          {
          case 1:
          GPBDAT = GPBDAT | LED1; break;
          case 2:
          GPBDAT = GPBDAT | LED2; break;
          case 3:
          GPBDAT = GPBDAT | LED3; break;
          case 4:
          GPBDAT = GPBDAT | LED4; break;
          default:
          return 0;
          }
          return num;
          }

          /*關閉全部led燈*/
          extern int all_led_off(void)
          {
          GPBDAT = GPBDAT | LED1 | LED2 | LED3 | LED4;
          return 0;
          }

          /* led燈初始化*/
          int led_init(void)
          {
          GPBCON = 0x15400;//設置GPB7為輸出口
          all_led_off();
          printk("led初始化OK/r/n");
          return 0;
          }

          /*中斷初始化*/
          void irq_init(void)
          {
          //打開KEY1~KEY6的屏蔽位
          INTMSK &= ~(1<<5);
          EINTMASK &= ~((1<<8) | (1<<11) | (1<<13) | (1<<14) | (1<<15) | (1<<19));
          printk("中斷初始化OK/r/n");
          }
          該文件是相關硬件初始化程序,主要包含了看門狗驅動,按鍵驅動,系統(tǒng)中斷驅動,LED驅動。
          handle_irq.c:
          中斷處理函數(shù),查出中斷源,中斷處理,清除中斷源。
          #include "register.h"
          #include "comm_fun.h"

          #define EINT_Key_REQUEST5// Key中斷源中斷號(6個按鍵全部使用外部子中斷)
          #define K1_EINT_BIT(1<<8)// K1外部子中斷位
          #define K2_EINT_BIT(1<<11)// K2外部子中斷位
          #define K3_EINT_BIT(1<<13)// K3外部子中斷位
          #define K4_EINT_BIT(1<<14)// K4外部子中斷位
          #define K5_EINT_BIT(1<<15)// K5外部子中斷位
          #define K6_EINT_BIT(1<<19)// K6外部子中斷位
          /*系統(tǒng)中斷處理函數(shù)*/
          void handle_irq()
          {
          unsigned long irqOffSet = INTOFFSET;//取得中斷號
          all_led_off();//關閉全部Led燈
          if(EINT_Key_REQUEST==irqOffSet){// Key中斷產生(6個按鍵使用一個總中斷號)
          if(K1_EINT_BIT & EINTPEND){
          led_on(1);//點亮Led1
          printk("Key1 pressed/r/n");
          EINTPEND &= K1_EINT_BIT;//清除外部子中斷源
          }else if(K2_EINT_BIT & EINTPEND){
          led_on(2);//點亮Led2
          printk("Key2 pressed/r/n");
          EINTPEND &= K2_EINT_BIT;//清除外部子中斷源
          }else if(K3_EINT_BIT & EINTPEND){
          led_on(3);//點亮Led3
          printk("Key3 pressed/r/n");
          EINTPEND &= K3_EINT_BIT;//清除外部子中斷源
          }else if(K4_EINT_BIT & EINTPEND){
          led_on(4);//點亮Led4
          printk("Key4 pressed/r/n");
          EINTPEND &= K4_EINT_BIT;//清除外部子中斷源
          }else if(K5_EINT_BIT & EINTPEND){
          all_led_off(1);//熄滅全部Led
          printk("Key5 pressed/r/n");
          EINTPEND &= K5_EINT_BIT;//清除外部子中斷源
          }else if(K6_EINT_BIT & EINTPEND){
          all_led_on();//點亮全部Led
          printk("Key6 pressed/r/n");
          EINTPEND &= K6_EINT_BIT;//清除外部子中斷源
          }
          }
          SRCPND &= (1<INTPND = INTPND;//清除中斷結果
          }
          main.c:
          包含主函數(shù)和延時函數(shù),主要實現(xiàn)字符串的循環(huán)打印。
          #include "register.h"
          #include "comm_fun.h"

          /*延時*/
          void delay(int msec)
          {
          int i, j;
          for(i = 1000; i > 0; i--)
          for(j = msec*10; j > 0; j--)
          /* do nothing */;
          }

          /*主函數(shù)*/
          int main()
          {
          while(1)
          {
          printk("main函數(shù)在運行.../r/n");
          delay(5);//delay
          }
          return 0;
          }



          評論


          技術專區(qū)

          關閉
          看屁屁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); })();