zoukankan      html  css  js  c++  java
  • ARM异常---一个Uart中断的触发处理过程:

    首先给出一些定义:

    //2440addr.inc

    INTOFFSET    EQU  0x4a000014    ;Interruot request source offset

    //option.inc

    _ISR_STARTADDRESS    EQU 0x33ffff00


    //2440init.s

             MACRO
    $HandlerLabel HANDLER $HandleLabel
    $HandlerLabel
        sub        sp,sp,#4            ;decrement sp(to store jump address)
        stmfd    sp!,{r0}            ;PUSH the work register to stack(lr does t 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


    下面进入正题:

    //2440init.s

        PRESERVE8
        AREA    RESET,CODE,READONLY
        ENTRY
        EXPORT    __ENTRY
    __ENTRY
    ResetEntry
        b    ResetHandler    ;0x0
        b    HandlerUndef    ;handler for Undefined mode
        b    HandlerSWI       ;handler for SWI interrupt
        b    HandlerPabort    ;handler for PAbort
        b    HandlerDabort    ;handler for DAbort
        b    .                       ;reserved
        b    HandlerIRQ        ;handler for IRQ interrupt
        b    HandlerFIQ        ;handler for FIQ interrupt
        b    EnterPWDN        ; Must be @0x20.
    
    ...
    
    HandlerIRQ      HANDLER HandleIRQ
    
    ...
    
    .............
          ; Setup IRQ handler//建立中断表
        ldr    r0,=HandleIRQ       ;This routine is needed
        ldr    r1,=IsrIRQ      ;if there isn t 'subs pc,lr,#4' at 0x18, 0x1c
        str    r1,[r0]
        
    ................
        ^   _ISR_STARTADDRESS        ;0x33ffff00
    HandleReset     #   4
    HandleUndef     #   4
    HandleSWI        #   4
    HandlePabort    #   4
    HandleDabort    #   4
    HandleReserved  #   4
    HandleIRQ        #   4
    HandleFIQ        #   4            ;0x33ffff1C
    ;IntVectorTable
    ;@0x33FF_FF20
    HandleEINT0        #   4            ;0x33ffff20
    HandleEINT1        #   4
    HandleEINT2        #   4
    .................................
    HandleUART1        #   4            ;0x33ffff7C
    .................................

    uart是一个外部中断,走的是FIQ.

    外部中断 --> b    HandlerFIQ ;

      看代码发现HandlerFIQ在init.s中进行了宏定义,展开之后得到:

    //展开宏 HandlerIRQ  HANDLER  HandleIRQ 
    HandlerIRQ
            sub        sp,sp,#4          ;decrement sp(to store jump address)
            stmfd    sp!,{r0}            ;PUSH the work register to stack(lr does t push because it return to original address)
            ldr     r0,=$HandleIRQ       ;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)

      可以看到,HandlerIRQ是一个标准的中断处理过程(正因如此使用了宏进行封装): 首先保存现场,然后跳转到HandleIRQ,从HandleIRQ回来之后恢复现场.

      HandleIRQ其实是一个函数指针,它可以在程序中被我们指向某一个处理函数. 这里我们指向了IsrIRQ. 在IsrIRQ里,我们读取INTOFFSET寄存器的值,加上外部中断的起始值HandleEINT0,这样我们就获得了世纪的中断入口HandleUART1. 通过ldmfd sp!,{r8-r9,pc},我们跳转进入了HandleUART1对应的实际的中断处理函数(见后面的分析).

    //2440init.s
    IsrIRQ sub sp,sp,#4 ;reserved for PC stmfd sp!,{r8-r9} ldr r9,=INTOFFSET ldr r9,[r9] ldr r8,=HandleEINT0 add r8,r8,r9,lsl #2 ;//r8=r8+(r9*4) ldr r8,[r8] str r8,[sp,#8] ldmfd sp!,{r8-r9,pc}

      上面说到,"通过ldmfd sp!,{r8-r9,pc},我们跳转进入了HandleUART1对应的实际的中断处理函数." 怎么跳转的呢,在代码里,我们又实现并绑定了HandleUART1的处理函数Uart1_TxRxInt:

    //2440addr.h
    #define pISR_UART1        (*(unsigned *)(_ISR_STARTADDRESS+0x7c))
    //2440lib.c pISR_UART1=(unsigned)Uart1_TxRxInt; extern unsigned char UartBuf1[256]; void __irq Uart0_TxRxInt(void)//这里只处理了接收中断 { unsigned char *pbuf = UartBuf1; if(rSUBSRCPND & BIT_SUB_RXD0) //接收中断 { rINTSUBMSK |= BIT_SUB_RXD0; while((rUFSTAT0&0x3f)) { *pbuf++ = rURXH0; } *pbuf = ''; rINTSUBMSK &= ~BIT_SUB_RXD0; rSRCPND |= BIT_UART0; rINTPND |= BIT_UART0; rINTSUBMSK &= ~(BIT_SUB_TXD0); } }
  • 相关阅读:
    基于android studio的快捷开发(将持续更新)
    安卓Design包之AppBar和Toolbar的联用
    安卓Design包之超强控件CoordinatorLayout与SnackBar的简单使用
    安卓Design之NavigationView的使用
    安卓Design包之TabLayout控件的简单使用
    使用ViewPager实现自动轮播
    高仿QQ顶部控件之IOS SegmentView
    强大的图片加载框架Fresco的使用
    安卓第一次启动引导页使用ViewPager实现
    android官方下拉刷新控件SwipeRefreshLayout的使用
  • 原文地址:https://www.cnblogs.com/mylinux/p/5722794.html
Copyright © 2011-2022 走看看