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

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 超詳細的2440中斷機制分析!

          超詳細的2440中斷機制分析!

          作者: 時間:2016-12-02 來源:網(wǎng)絡 收藏
          至于具體怎么跳轉的?
          首先,我們說了,HandleEINT0 開始的一段內(nèi)存里面,存放的就是中斷服務函數(shù)的函數(shù)指針,ARM的體系的話,每個指針變量就是占4個字節(jié),這里就解釋了,為什么這里為每個標號分配了4個字節(jié)的空間,里面放的就是函數(shù)指針?。。∠旅嬖倏纯丛趺刺D,繼續(xù)看 IsrIRQ 里面就實現(xiàn)了跳轉了
          str r8,[sp,#8]
          ldmfd sp!,{r8-r9,pc}
          其實最核心就是這兩句了,先查找到當前中斷服務程序的地址,將他放到 R8 里面,然后出棧,彈出給PC那么PC很自然就跳到中斷服務程序了。至于這里的堆棧問題又是一個非常棘手的,需要好好的參透ARM的中斷架構,需要了解的可以自己仔細的閱讀 《ARM體系結構與編程》里面說的很詳細。我們這里的重點是研究怎么跳轉。
          最后,我們看看在C代碼中是怎么安裝終端向量的,例如看 按鍵的外部中斷,是怎么具體設置的,參看/src/keyscan.c 里面的代碼很簡單,里面只有3個函數(shù)
          KeyScan_Test 是按鍵測試的主函數(shù)
          Key_ISR 是按鍵中斷服務函數(shù)
          在 KeyScan_Test里面,我們發(fā)現(xiàn)了有這么一句
          pISR_EINT0 = pISR_EINT2 = pISR_EINT8_23 = (U32)Key_ISR;
          可以理解否? Key_ISR就是上面提到的按鍵中斷服務函數(shù),函數(shù)的名字,代表的就是函數(shù)的地址!?。?!
          將中斷服務函數(shù)的地址,注意了,是地址,這是一個 U32型的變量。送到幾個變量,我們以pISR_EINT0 作為例子,查看頭文件定義,在 2440addr.h 里面找到
          // Interrupt vector
          #define pISR_EINT0 (*(unsigned *)(_ISR_STARTADDRESS+0x20))
          _ISR_STARTADDRESS有沒有似曾相識的感覺?沒錯,剛才分析的匯編代碼里面就提到了
          ^ _ISR_STARTADDRESS ; _ISR_STARTADDRESS=0x33FF_FF00
          HandleReset # 4
          HandleUndef # 4
          ......
          對,地址就是這里,然后 _ISR_STARTADDRESS+0x20 就是跳過前面的異常向量,進入IRQ中斷向量的入口,所以說到尾
          pISR_EINT0 = (U32)Key_ISR;
          完成的操作就是,將 Key_ISR 的地址存放到
          HandleEINT0 # 4
          這個IRQ向量表里面?。。?!
          當按鍵中斷發(fā)生的時候,發(fā)生IRQ異常中斷當前PC值-4 保存到LR_IRQ里面,然后執(zhí)行
          b HandlerIRQ
          然后是執(zhí)行
          HandlerIRQ
          sub sp,sp,#4 ; 預留一個用來存放PC地址
          stmfd sp!,{r0} ; 保存R0,因為下面使用了
          ldr r0,=HandleIRQ ; 將HandleIRQ(服務程序)的地址裝載到R0
          ldr r0,[r0]
          str r0,[sp,#4] ; 保存到剛才預留的地方
          ldmfd sp!,{r0,pc} ; 彈出堆棧,恢復R0,并且將剛才計算好的 HandleIRQ 地址彈出到 PC堆棧是向下生長的,所以 SUB SP,SP,#4 就相當于 PUSH XX,但是這個XX這個時候并沒有用,因為這里用的是強制移動 SP 指針實現(xiàn)的。然后得到服務程序的地址,再將這個值放回剛才預留的棧的空位上面,最后就是POP出R0恢復,并且將剛才得到的服務程序的地址送到 PC,那么實現(xiàn)的效果就是跳轉到 HandleIRQ 里面了。
          接著看剛才是怎么安裝的HandleIRQ 的
          ; Setup IRQ handler
          ldr r0,=HandleIRQ ;This routine is needed
          ldr r1,=IsrIRQ ;if there is not subs pc,lr,#4 at 0x18, 0x1c
          str r1,[r0]
          可以看出,這里將 IsrIRQ 的地址的值保存到 HandleIRQ 中,也就是說,上面的 IRQ 服務程序,這個時候實際上就是指 IsrIRQ !
          所以接著的事情就是轉移到 IsrIRQ 中執(zhí)行:
          IsrIRQ
          sub sp,sp,#4 ; 預留一個值來保存PC
          stmfd sp!,{r8-r9}
          ldr r9,=INTOFFSET ; 計算偏移量,下面解釋
          ldr r9,[r9]
          ldr r8,=HandleEINT0
          add r8,r8,r9,lsl #2
          ldr r8,[r8]
          str r8,[sp,#8] ; 因為保存了2個寄存器R8 R9 ,所以SP下移了8位
          ldmfd sp!,{r8-r9,pc} ; 恢復寄存器,彈出到PC,同上面的一樣怎么保存,操作SP,跟最后彈出到PC的部分和上面的例子一樣,下面說說中間的計算部分計算偏移量,其實原理很簡單,首先 INTOFFSET 保存著當前是哪個IRQ中斷,例如 0代表著 HandleEINT0,1代表HandleEINT1 ..... 等等,這不是亂來,有一個表的,這個是由 S3C2440 的datasheet說的,自己可以去查看。
          然后得到 中斷處理函數(shù)的向量表,這個表的首地址就是 HandleEINT0,那么很自然的想到,怎么查表?那還不簡單?HandleEINT0 + INTOFFSET 不就完了?基地址加偏移量就得到表中某項了,當然,因為這里是中斷處理向量
          每一項占用4個字節(jié),所以用lsl #2處理一下,左移2位相當于乘以4,偏移量乘以4,這應該很好理解的。
          我們這個例子找到的就是 HandleEINT0 ,將里面的值讀出來,里面放的是 HandleEINT0 服務函數(shù)的地址,這個地址怎么來的?是在C程序里面設置的。我們看 keyscan.c 程序,找到一個 void KeyScan_Test(void) 函數(shù),
          里面有這么一句:
          pISR_EINT0 = pISR_EINT2 = pISR_EINT8_23 = (U32)Key_ISR;
          這里是安裝了3個按鍵中斷服務程序,我們只關注 0號中斷,也就是
          pISR_EINT0 = (U32)Key_ISR;
          這句話什么意思?先看看pISR_EINT0的定義,在 2440addr.h 中定義
          #define pISR_EINT0 (*(unsigned *)(_ISR_STARTADDRESS+0x20))
          看到?jīng)]有?_ISR_STARTADDRESS 不就是剛才說的那個異常向量的入口地址?加上一個 0x20 之后實際上指向的,就是 HandleEINT0 ?。?!這么說來,上面的意思就是,將 Key_ISR 處理函數(shù)的入口地址,送到 HandleEINT0 中。
          再來看 Key_ISR ,這是一個典型的服務程序,加了_irq 作為編譯關鍵字,告訴編譯器,這個函數(shù)是中斷服務程序
          得保存需要的寄存器,免得被破壞。具體可以參考 《ARM體系結構與編程》P283 頁的描述。
          static void __irq Key_ISR(void)
          {
          .......
          }
          加上 _irq 關鍵字之后,編譯器就會處理好所有的保存動作了,并不需要多關心。但是這個是 ARM-CC 編譯器的關鍵字,GCC中并沒有這個東西,所以GCC處理中斷的時候最好還是自己保存一下。
          到這里為止,整個中斷的過程就解釋完畢。分析的過程中確實學習了很多。
          上一頁 1 2 下一頁

          關鍵詞: 2440中斷機

          評論


          技術專區(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); })();