在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<abbr id="27omo"></abbr>

<menu id="27omo"><dl id="27omo"></dl></menu>
    • <label id="27omo"><tt id="27omo"></tt></label>

      新聞中心

      EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > S3C2440中斷代碼的深層次分析

      S3C2440中斷代碼的深層次分析

      作者: 時間:2016-12-01 來源:網(wǎng)絡(luò) 收藏
      在前一段時間分析了ARM異常處理機制的處理方式,分析了在異常產(chǎn)生以后CPU自動完成的相關(guān)處理以及程序員應(yīng)該完成的基本操作。著重分析了異常代碼的返回地址分析已經(jīng)采用通用代碼處理各種異常的可能性。
      異常處理的基本過程如下:異常產(chǎn)生(在指令的臨界中檢測CPU的狀態(tài),一般實質(zhì)在這條指令被執(zhí)行完成,但是還沒有執(zhí)行下一條指令之前檢測)——>保存狀態(tài)寄存器,切換狀態(tài)寄存器,保存LR=PC-4,強制PC跳轉(zhuǎn)到對應(yīng)異常向量(以上的過程都是CPU自動完成)——》調(diào)整返回地址,在棧中保存寄存器,便于恢復(fù)寄存器的值——》異常處理函數(shù)——》退出異常。
      中斷處理機制的兩種形式:
      1、采用在中斷向量中存儲簡單的跳轉(zhuǎn)指令,跳轉(zhuǎn)到異常處理函數(shù)中,但是這種方式存在的缺點就是跳轉(zhuǎn)指令的范圍是有局限性的。
      2、采用更新PC值的方法進行,具體的實現(xiàn)形式是在另一個固定地址處(handle_addr)保存對應(yīng)異常處理函數(shù)的地址,然后采用LDR PC [PC, offset],其中offset = handle_addr – vect – 0x08;這種機制只要保證選擇的地址恰當就能實現(xiàn)不同距離的跳轉(zhuǎn)。
      以上的分析和處理在上一次中已經(jīng)分析,這次分析中斷的處理過程,中斷只是異常的一種特殊情況,對異常的處理得到了好的理解,那么對中斷的處理也就比較方便了。
      在ARM內(nèi)核中只支持IRQ和IFQ兩種類型的中斷,但是不同的廠商提供不同類型的中斷控制器實現(xiàn)對中斷的擴展,使得實際的芯片更加適合我們的使用。但是中斷控制器的差別也使得不同廠商的中斷處理也有差別,但是基本的思想是一致的。
      S3C2440的中斷控制器一個支持60種中斷源,基本的實現(xiàn)如上圖所示?;镜募拇嫫靼⊿RCPND、INTPND(有且僅有1bit會被置位,可以通過這個寄存器判斷中斷源,找出那個IRQ源發(fā)生中斷)、INTMOD、INTMSK、PRIORITY(用來改變中斷的優(yōu)先級順序,但是其中還是存在一些固有的順序,具體的參看手冊)、INTOFFSET(用來表示IRQ中INTPND的那個bit被置位,這樣每一類的中斷源都存在一個固定的偏移量,這個寄存器可以用來用來計算偏移量以及通過這個偏移量找到對應(yīng)的中斷處理函數(shù)地址存儲位置等),當然也存在一些關(guān)于多個中斷源構(gòu)成的子中斷寄存器,SUBSRCPND、INTSUBMSK。
      在S3C2440的啟動代碼中描述了關(guān)于中斷處理過程的基本過程和原理。
      首先需要搞清楚下面的一個宏定義:
      MACRO
      $HandlerLabel HANDLER $HandleLabel
      $HandlerLabel
      subsp,sp,#4;decrement sp(to store jump address)
      stmfd sp!,{r0} ;PUSH the work register to stack(lr does not push because it return to original address)
      ldr r0,=$HandleLabel;load the address of HandleXXX to r0
      ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX
      str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack
      ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)
      MEND
      1、搞清楚ARM中的MACRO偽指令,這個偽指令就是我們在匯編中的宏定義,我們都知道宏的實現(xiàn)能夠避免代碼的重復(fù)型以及代碼的可修復(fù)性。關(guān)于ARM匯編中的宏定義基本的形式如下:
      MACRO
      {$label} macroname {$parameter} {$parameter}…
      Code
      MEND
      其中$label 宏指令被展開時,label可被替換為相應(yīng)的符號,一般為一個標號
      macroname所定義的宏的名稱
      $parameter宏指令的參數(shù),當宏指令被展開時被替換成對應(yīng)的值。
      2、依據(jù)上面的定義我們可以知道當前這段代碼定義了一個宏指令,HANDLER,其中標號為$HandlerLabel,參數(shù)為$HandleLabel
      基本的實現(xiàn)代碼分析如下:
      subsp,sp,#4;在棧中預(yù)留一個區(qū)域,用來保存PC的值
      stmfd sp!,{r0};由于r0還需要被使用,因此需要被壓棧
      ldr r0,=$HandleLabel ;這里的ldr是一個偽指令,主要是將標號$HandleLabel的地址加載到r0中,這也是壓棧r0的原因。
      ldr r0,[r0] ;這是ARM的ldr指令,主要是將$HandleLabel對應(yīng)地址中的內(nèi)容加載到r0中。如果在$HandleLabel中保存的是一個中斷處理函數(shù)的地址,那么只需要將這個值加載到PC即可實現(xiàn)了中斷任務(wù)跳轉(zhuǎn),實際上這個過程就是采用了異常處理的第二種方式:
      即加載PC的方式,而不是簡單的跳轉(zhuǎn)方式。
      str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack
      ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)
      這兩句代碼正是這段代碼的精髓?;拘问饺缦拢?/div>
      str r0,[sp,#4],是指將r0的內(nèi)容,也就是異常處理函數(shù)的地址保存到棧中的SP-4位置處,這個位置也恰好是之前sub sp,sp,#4;用來預(yù)留給保存PC值的位置,這時將異常處理函數(shù)的地址保存在這個地址處,接下來的ldmfd sp!,{r0,pc}剛好就是將棧中的內(nèi)容加載到R0和PC中,這樣也就實現(xiàn)了將異常處理函數(shù)地址加載到PC.實現(xiàn)了跳轉(zhuǎn)過程。
      高地址
      SP_0/SP_3
      SP_1
      Handle_addr
      SP_2
      R0
      低地址
      從上面的分析可以知道這種中斷處理的方式,并不是中斷處理中的簡單跳轉(zhuǎn)方式(因為跳轉(zhuǎn)范圍的局限性)而是采用更新PC值的形式實現(xiàn)的。
      接下來分析IRQ,這種在我們實際開發(fā)中使用比較多的中斷形式進行分析。
      首先可以發(fā)現(xiàn)存在:
      1、b HandlerIRQ;handler for IRQ interrupt
      這種情況下發(fā)生在中斷產(chǎn)生過程中,是在IRQ向量中執(zhí)行的,也就是在0x18處執(zhí)行,其中HandlerIRQ實質(zhì)上是一個標號,對應(yīng)一個具體的地址。其中保存的內(nèi)容就是對應(yīng)IRQ處理函數(shù)的地址。但是在代碼中只有一個HandlerIRQ,形式如下:
      HandlerIRQHANDLER HandleIRQ
      2、HandlerIRQ HANDLER HandleIRQ
      根據(jù)上面的宏定義,可以將這句代碼進行擴展,得到如下的形式:
      HandlerIRQ
      subsp,sp,#4
      stmfd sp!,{r0}
      ldr r0,= HandleIRQ
      ldr r0,[r0]
      str r0,[sp,#4]
      ldmfd sp!,{r0,pc}
      3、關(guān)于HandleIRQ其中存放的內(nèi)容可以從下面的代碼中得到。
      ; 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]
      其中可以看到,在HandleIRQ中保存的內(nèi)容是IsrIRQ的地址,而IsrIRQ我們可以知道是一個中斷服務(wù)函數(shù),因為在寫代碼的過程中進程會遇到這個特殊字符__ISR,這段代碼是在啟動代碼中執(zhí)行的。
      4、IsrIRQ實現(xiàn)問題
      IsrIRQ
      subsp,sp,#4 ;reserved for PC
      stmfd sp!,{r8-r9}
      ldr r9,=INTOFFSET
      ldr r9,[r9]
      ldr r8,=HandleEINT0
      addr8,r8,r9,lsl #2
      ldr r8,[r8]
      str r8,[sp,#8]
      ldmfd sp!,{r8-r9,pc}
      還是一句一句的分析:
      subsp,sp,#4 ;為保存PC值預(yù)留一個棧區(qū)域,這個區(qū)域與上面的處理過程是異曲同工的。
      stmfd sp!,{r8-r9} ;保存r8,r9中的值,因為接下來將使用這兩個寄存器
      ldr r9,=INTOFFSET;這是一個偽指令操作,實質(zhì)上是將寄存器INTOFFSET的地址加載到r9中。
      ldr r9,[r9];得到寄存器中的值,這個寄存器中的值恰好保存了當前最高優(yōu)先級中斷的中斷號(優(yōu)先級是可以調(diào)節(jié)的,而中斷號是一個固定值,因此選擇中斷號比較恰當),這樣也就知道了具體是那個中斷源產(chǎn)生了中斷。
      ldr r8,=HandleEINT0;這句的ldr是偽指令,意思是將標號的地址加載到r8中
      addr8,r8,r9,lsl #2;從指令的意義分析:r8 = r8 + r9>>2 = r8+r9*4;
      其實這兩句結(jié)合一下S3C2440的中斷資料就不難分析得出,因為HandleEINT0實質(zhì)上是指存儲外部中斷0處理函數(shù)地址的地方,那么我們可以將這一塊內(nèi)存地址看做是一個IRQISR中斷向量表,而EINT0恰好是中斷優(yōu)先級最高的中斷,那么可以將這個地址HandleEINT0作為IRQ中斷向量表的入口地址,其他中斷號的地址,只需要通過偏移地址就能得到,由于指針的大小恰好為4個字節(jié),因此得到的相應(yīng)中斷號的入口地址是
      HandleEINT0 = HandleEINT0 + INTOFFSET*4,
      這些地址中都保存了對應(yīng)中斷處理函數(shù)的函數(shù)地址。
      ldr r8,[r8]是指將r8的內(nèi)容加載到r8中,也就是將對應(yīng)中斷處理函數(shù)的地址加載到r8中。
      str r8,[sp,#8];這句代碼的作用實質(zhì)上就是和上面的分析一樣,也就是將r8的值保存到之前為PC預(yù)留的區(qū)域中。
      ldmfd sp!,{r8-r9,pc};這句也恰好驗證了上面的分析,PC中的值恰好就是之前的sp+8處的內(nèi)容,這樣中斷處理函數(shù)的地址就到了PC中。
      上一頁 1 2 下一頁

      關(guān)鍵詞: S3C2440中斷代碼深層次分

      評論


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

      關(guān)閉