This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Processor always jumps to default exception handler

Good day,

My code for configuring the NVIC and peripheral interrupts are already working as expected, but the only problem now is the debugger shows that the processor always jumps to the default handler (__default_handler) and never on my defined interrupt handler whenever I trigger the interrupt source. 

I already added the specific interrupt vector in the vector table from the file vector_table_M.s and included it in my project. Am I missing something else?

Hardware: Tiva C Launchpad from TI

IDE: IAR Embedded Workbench

Thanks for any help,

William

Parents
  • I did carefully look at my source code and even the map file but everything seemed fine. By looking at the binary, do you mean the object dump? If yes, in what particular section should I inspect?

    As far as I know only the linker script file can alter the vector table address. I left it with the default value (0x0). My code is running just fine on the board (unless I trigger the interrupt ofcourse), so does that already confirm the vector table is at the right address? (Well, the processor did jump to the reset handler).

Reply
  • I did carefully look at my source code and even the map file but everything seemed fine. By looking at the binary, do you mean the object dump? If yes, in what particular section should I inspect?

    As far as I know only the linker script file can alter the vector table address. I left it with the default value (0x0). My code is running just fine on the board (unless I trigger the interrupt ofcourse), so does that already confirm the vector table is at the right address? (Well, the processor did jump to the reset handler).

Children
  • If you do something like:

    arm-none-eabi-objdump -D myfile.elf

    You'll get a "disassembly" output that starts something like:

    00004000 <exception_table>:
        4000:       20030000        andcs   r0, r3, r0
        4004:       00004e1d        andeq   r4, r0, sp, lsl lr
        4008:       00004e09        andeq   r4, r0, r9, lsl #28
        400c:       00004e09        andeq   r4, r0, r9, lsl #28
        4010:       00004e09        andeq   r4, r0, r9, lsl #28
        4014:       00004e09        andeq   r4, r0, r9, lsl #28
        4018:       00004e09        andeq   r4, r0, r9, lsl #28
            ...
        402c:       00004e09        andeq   r4, r0, r9, lsl #28
        4030:       00004e09        andeq   r4, r0, r9, lsl #28
        4034:       00000000        andeq   r0, r0, r0
        4038:       00004e09        andeq   r4, r0, r9, lsl #28
        403c:       00004e9d        muleq   r0, sp, lr
        4040:       00004e09        andeq   r4, r0, r9, lsl #28
        4044:       00004e09        andeq   r4, r0, r9, lsl #28
        4048:       00004e09        andeq   r4, r0, r9, lsl #28
        404c:       00004e09        andeq   r4, r0, r9, lsl #28
        4050:       00004e09        andeq   r4, r0, r9, lsl #28
        4054:       00004e09        andeq   r4, r0, r9, lsl #28
        4058:       00004e09        andeq   r4, r0, r9, lsl #28
        405c:       00004e09        andeq   r4, r0, r9, lsl #28
        4060:       00004e09        andeq   r4, r0, r9, lsl #28
        4064:       00004e09        andeq   r4, r0, r9, lsl #28
        4068:       00004e09        andeq   r4, r0, r9, lsl #28
        406c:       00004e09        andeq   r4, r0, r9, lsl #28
        4070:       00004da9        andeq   r4, r0, r9, lsr #27
        4074:       00004daf        andeq   r4, r0, pc, lsr #27
        4078:       00004db5                        ; <UNDEFINED> instruction: 0x00004db5
        407c:       00004dbb                        ; <UNDEFINED> instruction: 0x000

    (the "disassembly" is bogus, but this is pretty much the most obvious way to look at the vectors.
    This particular code is for SAMD51 and was compiled to work with a bootloader, so it's vector table is a 0x4000 instead of 0x0.)

    20030000 is the initial stack pointer, 0x4e1d is the start address, and then there are a bunch of vectors that are "obviously" the default vector (0x4e09), and a few that are obviously NOT the default vector.   The first thing I'd check is whether the particular vector you think you've added is NOT the default vector any more.   Then you can use arm-none-eabi-nm -SC myfile.elf |grep -i handler  to see if it actually matches your function:

    arm-none-eabi-nm -SC myfile.elf | grep -i handler
    00004e08 00000002 W AC_Handler               ;; bunch of handlers set to the weak Dummy Handler...
    00004e08 00000002 W ADC0_0_Handler       ;;;  ...
    00004e08 00000002 W DAC_3_Handler
    00004e08 00000002 W DAC_4_Handler
    00004e08 00000002 W DMAC_0_Handler
    00004e08 00000002 W DMAC_1_Handler
    00004e08 00000002 W DMAC_2_Handler
    00004e08 00000002 W DMAC_3_Handler
    00004e08 00000002 W DMAC_4_Handler
    00004e08 00000002 W DebugMon_Handler
    00004e08 00000002 T Dummy_Handler
    00004da8 00000006 T EIC_0_Handler         ;; Non-default handlers!
    00004de4 00000006 T EIC_10_Handler
    00004dea 00000006 T EIC_11_Handler
    00004df0 00000006 T EIC_12_Handler

  • I see your point. I used the "ielfdump" utility provided by IAR, and these are the sections I found useful.

    The symtab shows the vector table is at the correct address and my handler is defined and named "GPIOPortJ_Handler" at address 0x1fd.

    62: __vector_table                              0x0   4 Data Gb
    63: Region$$Table$$Base                         0x0 Ext  --  Gb
    64: Region$$Table$$Limit                        0x0 Ext  --  Gb
    65: __iar_systems$$module                       0x1 Abs  --  Gb
    66: gpio_setup                                0x11d   5 Code Gb 0x36
    67: int_setup                                 0x153   5 Code Gb 0x2a
    68: clear_int                                 0x17d   5 Code Gb 0x20
    69: main                                      0x19d   5 Code Gb 0x24
    70: GPIOPortJ_IRQHandler                      0x1fd   5 Code Gb 0x20
    71: SysTick_Handler                           0x21d   5 Code Gb  0xc
    72: __cmain                                   0x235   5 Code Gb
    73: ?main                                     0x235   5 Code Gb
    74: _call_main                                0x241   5 Code Gb
    75: _main                                     0x24f   5 Code Gb
    76: __low_level_init                          0x253   5 Code Gb  0x4
    77: exit                                      0x257   5 Code Gb  0x4
    78: _exit                                     0x25d   5 Code Gb
    79: __exit                                    0x269   5 Code Gb 0x14
    80: __iar_program_start                       0x27d   5 Code Gb
    81: CSTACK$$Base                        0x2000'0000   6  --  Gb
    82: CSTACK$$Limit                       0x2000'8000   6  --  Gb
    83: __iar_rom_use_0nuD_mcWsqA                 0x286 Abs  --  Gb

    This is the vector table and you can see the exception I'm interested at has the custom function I defined, and everything else has the default handler.

    Section #4 A0:
    
               $d:
               `.intvec7`:
               __vector_table:
        0x0: 0x2000'8000  DC32 CSTACK$$Limit
        0x4: 0x0000'027d  DC32 __iar_program_start
        0x8: 0x0000'025b  DC32 __default_handler
        0xc: 0x0000'025b  DC32 __default_handler
       0x10: 0x0000'025b  DC32 __default_handler
       0x14: 0x0000'025b  DC32 __default_handler
       0x18: 0x0000'025b  DC32 __default_handler
       0x1c: 0x0000'0000  DC32 0x0
       0x20: 0x0000'0000  DC32 0x0
       0x24: 0x0000'0000  DC32 0x0
       0x28: 0x0000'0000  DC32 0x0
       0x2c: 0x0000'025b  DC32 __default_handler
       0x30: 0x0000'025b  DC32 __default_handler
       0x34: 0x0000'0000  DC32 0x0
       0x38: 0x0000'025b  DC32 __default_handler
       0x3c: 0x0000'021d  DC32 SysTick_Handler
       0x40: 0x0000'025b  DC32 __default_handler
       0x44: 0x0000'025b  DC32 __default_handler
        .
        .
        .
        .
        .
        .
      0x110: 0x0000'025b  DC32 __default_handler
      0x114: 0x0000'025b  DC32 __default_handler
      0x118: 0x0000'01fd  DC32 GPIOPortJ_IRQHandler

    The handler itself:

               `.text_4`:
               GPIOPortJ_IRQHandler:
      0x1fc: 0x480a         LDR.N  R0, [PC, #0x28]   ; 0xe000'e104
      0x1fe: 0x6800         LDR    R0, [R0]
      0x200: 0xf5b0 0x2f00  CMP.W  R0, #524288       ; 0x80000
      0x204: 0xd109         BNE.N  @21a
      0x206: 0x4809         LDR.N  R0, [PC, #0x24]   ; 0x4006'03fc
      0x208: 0x6801         LDR    R1, [R0]
      0x20a: 0xf051 0x0102  ORRS.W R1, R1, #2
      0x20e: 0x6001         STR    R1, [R0]
      0x210: 0x4807         LDR.N  R0, [PC, #0x1c]   ; 0x4006'43fc
      0x212: 0x6801         LDR    R1, [R0]
      0x214: 0xf091 0x0102  EORS.W R1, R1, #2
      0x218: 0x6001         STR    R1, [R0]
               @21a:
      0x21a: 0x4770         BX     LR

    Is this information enough? It's really weird because whenever I trigger the interrupt, a bus fault still occurs and it jumps straight to the default handler and I really can't say what exactly the problem is anymore.

  • Also, this is the .s file from IAR that I modified and added to my project. I'll just leave it here in case it provides any useful info.

    /**************************************************
     *
     * Part one of the system initialization code, contains low-level
     * initialization, plain thumb variant.
     *
     * Copyright 2008-2017 IAR Systems AB.
     *
     * $Revision: 112610 $
     *
     **************************************************/
    
    ;
    ; The modules in this file are included in the libraries, and may be replaced
    ; by any user-defined modules that define the PUBLIC symbol __iar_program_start or
    ; a user defined start symbol.
    ; To override the cstartup defined in the library, simply add your modified
    ; version to the workbench project.
    ;
    ; The vector table is normally located at address 0.
    ; When debugging in RAM, it can be located in RAM, aligned to at least 2^6.
    ; The name "__vector_table" has special meaning for C-SPY, which
    ; is where to find the SP start value.
    ; If vector table is not located at address 0, the user has to initialize the  NVIC vector
    ; table register (VTOR) before using interrupts.
    ;
    ; Cortex-M version
    ;
    
    
    MODULE  ?vector_table
    
            AAPCS INTERWORK, VFP_COMPATIBLE, RWPI_COMPATIBLE
            PRESERVE8
    
    
              CFI Names cfiNames0
              CFI StackFrame CFA R13 DATA
              CFI Resource R0:32, R1:32, R2:32, R3:32, R4:32, R5:32, R6:32, R7:32
              CFI Resource R8:32, R9:32, R10:32, R11:32, R12:32, R13:32, R14:32
              CFI EndNames cfiNames0
            
              CFI Common cfiCommon0 Using cfiNames0
              CFI CodeAlign 2
              CFI DataAlign 4
              CFI ReturnAddress R14 CODE
              CFI CFA R13+0
              CFI R0 Undefined
              CFI R1 Undefined
              CFI R2 Undefined
              CFI R3 Undefined
              CFI R4 SameValue
              CFI R5 SameValue
              CFI R6 SameValue
              CFI R7 SameValue
              CFI R8 SameValue
              CFI R9 SameValue
              CFI R10 SameValue
              CFI R11 SameValue
              CFI R12 Undefined
              CFI R14 SameValue
              CFI EndCommon cfiCommon0
            
            
            
            
            ;; Forward declaration of sections.
            SECTION CSTACK:DATA:NOROOT(3)
    
            SECTION .intvec:CODE:NOROOT(2)
    
            EXTERN  __iar_program_start
            PUBLIC  __vector_table
    
            DATA
    
    __iar_init$$done:               ; The vector table is not needed
                                    ; until after copy initialization is done
    
    __vector_table
            DCD     sfe(CSTACK)
            DCD     __iar_program_start
    
            DCD     NMI_Handler
            DCD     HardFault_Handler
            DCD     MemManage_Handler
            DCD     BusFault_Handler
            DCD     UsageFault_Handler
            DCD     0
            DCD     0
            DCD     0
            DCD     0
            DCD     SVC_Handler
            DCD     DebugMon_Handler
            DCD     0
            DCD     PendSV_Handler
            DCD     SysTick_Handler
    ;;       
    ;; Device Specific Interrupts
    ;;
            DCD     GPIOPortA_IRQHandler
            DCD     GPIOPortB_IRQHandler
            DCD     GPIOPortC_IRQHandler
            DCD     GPIOPortD_IRQHandler
            DCD     GPIOPortE_IRQHandler
            DCD     UART0_IRQHandler
            DCD     UART1_IRQHandler
            DCD     SSI0_IRQHandler
            DCD     I2C0_IRQHandler
            DCD     PWMFault_IRQHandler
            DCD     PWMGen0_IRQHandler
            DCD     PWMGen1_IRQHandler
            DCD     PWMGen2_IRQHandler
            DCD     QEI0_IRQHandler
            DCD     ADCSeq0_IRQHandler
            DCD     ADCSeq1_IRQHandler
            DCD     ADCSeq2_IRQHandler
            DCD     ADCSeq3_IRQHandler
            DCD     Watchdog_IRQHandler
            DCD     Timer0A_IRQHandler
            DCD     Timer0B_IRQHandler
            DCD     Timer1A_IRQHandler
            DCD     Timer1B_IRQHandler
            DCD     Timer2A_IRQHandler
            DCD     Timer2B_IRQHandler
            DCD     Comp0_IRQHandler
            DCD     Comp1_IRQHandler
            DCD     Comp2_IRQHandler
            DCD     SysCtrl_IRQHandler
            DCD     FlashCtrl_IRQHandler
            DCD     GPIOPortF_IRQHandler
            DCD     GPIOPortG_IRQHandler
            DCD     GPIOPortH_IRQHandler
            DCD     USART2_IRQHandler
            DCD     SSI1_IRQHandler
            DCD     Timer3A_IRQHandler
            DCD     Timer3B_IRQHandler
            DCD     I2C1_IRQHandler
            DCD     QEI1_IRQHandler
            DCD     CAN0_IRQHandler
            DCD     CAN1_IRQHandler
            DCD     CAN2_IRQHandler
            DCD     Ethernet_IRQHandler
            DCD     Hibernate_IRQHandler
            DCD     USB0_IRQHandler
            DCD     PWMGen3_IRQHandler
            DCD     uDMAST_IRQHandler
            DCD     uDMAError_IRQHandler
            DCD     ADC1Seq0_IRQHandler
            DCD     ADC1Seq1_IRQHandler
            DCD     ADC1Seq2_IRQHandler
            DCD     ADC1Seq3_IRQHandler
            DCD     I2S0_IRQHandler
            DCD     EBI0_IRQHandler
            DCD     GPIOPortJ_IRQHandler
            
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;
    ;; Default interrupt handlers.
    ;;
    
            PUBWEAK NMI_Handler
            PUBWEAK HardFault_Handler
            PUBWEAK MemManage_Handler
            PUBWEAK BusFault_Handler
            PUBWEAK UsageFault_Handler
            PUBWEAK SVC_Handler
            PUBWEAK DebugMon_Handler
            PUBWEAK PendSV_Handler
            PUBWEAK SysTick_Handler
            PUBWEAK GPIOPortA_IRQHandler
            PUBWEAK GPIOPortB_IRQHandler
            PUBWEAK GPIOPortC_IRQHandler
            PUBWEAK GPIOPortD_IRQHandler
            PUBWEAK GPIOPortE_IRQHandler
            PUBWEAK UART0_IRQHandler
            PUBWEAK UART1_IRQHandler
            PUBWEAK SSI0_IRQHandler
            PUBWEAK I2C0_IRQHandler
            PUBWEAK PWMFault_IRQHandler
            PUBWEAK PWMGen0_IRQHandler
            PUBWEAK PWMGen1_IRQHandler
            PUBWEAK PWMGen2_IRQHandler
            PUBWEAK QEI0_IRQHandler
            PUBWEAK ADCSeq0_IRQHandler
            PUBWEAK ADCSeq1_IRQHandler
            PUBWEAK ADCSeq2_IRQHandler
            PUBWEAK ADCSeq3_IRQHandler
            PUBWEAK Watchdog_IRQHandler
            PUBWEAK Timer0A_IRQHandler
            PUBWEAK Timer0B_IRQHandler
            PUBWEAK Timer1A_IRQHandler
            PUBWEAK Timer1B_IRQHandler
            PUBWEAK Timer2A_IRQHandler
            PUBWEAK Timer2B_IRQHandler
            PUBWEAK Comp0_IRQHandler
            PUBWEAK Comp1_IRQHandler
            PUBWEAK Comp2_IRQHandler
            PUBWEAK SysCtrl_IRQHandler
            PUBWEAK FlashCtrl_IRQHandler
            PUBWEAK GPIOPortF_IRQHandler
            PUBWEAK GPIOPortG_IRQHandler
            PUBWEAK GPIOPortH_IRQHandler
            PUBWEAK USART2_IRQHandler
            PUBWEAK SSI1_IRQHandler
            PUBWEAK Timer3A_IRQHandler
            PUBWEAK Timer3B_IRQHandler
            PUBWEAK I2C1_IRQHandler
            PUBWEAK QEI1_IRQHandler
            PUBWEAK CAN0_IRQHandler
            PUBWEAK CAN1_IRQHandler
            PUBWEAK CAN2_IRQHandler
            PUBWEAK Ethernet_IRQHandler
            PUBWEAK Hibernate_IRQHandler
            PUBWEAK USB0_IRQHandler
            PUBWEAK PWMGen3_IRQHandler
            PUBWEAK uDMAST_IRQHandler
            PUBWEAK uDMAError_IRQHandler
            PUBWEAK ADC1Seq0_IRQHandler
            PUBWEAK ADC1Seq1_IRQHandler
            PUBWEAK ADC1Seq2_IRQHandler
            PUBWEAK ADC1Seq3_IRQHandler
            PUBWEAK I2S0_IRQHandler
            PUBWEAK EBI0_IRQHandler
            PUBWEAK GPIOPortJ_IRQHandler  
            
            SECTION .text:CODE:REORDER:NOROOT(1)
              CFI Block cfiBlock0 Using cfiCommon0
              CFI Function __default_handler
            THUMB
    
    NMI_Handler
    HardFault_Handler
    MemManage_Handler
    BusFault_Handler
    UsageFault_Handler
    SVC_Handler
    DebugMon_Handler
    PendSV_Handler
    SysTick_Handler
    GPIOPortA_IRQHandler
    GPIOPortB_IRQHandler
    GPIOPortC_IRQHandler
    GPIOPortD_IRQHandler
    GPIOPortE_IRQHandler
    UART0_IRQHandler
    UART1_IRQHandler
    SSI0_IRQHandler
    I2C0_IRQHandler
    PWMFault_IRQHandler
    PWMGen0_IRQHandler
    PWMGen1_IRQHandler
    PWMGen2_IRQHandler
    QEI0_IRQHandler
    ADCSeq0_IRQHandler
    ADCSeq1_IRQHandler
    ADCSeq2_IRQHandler
    ADCSeq3_IRQHandler
    Watchdog_IRQHandler
    Timer0A_IRQHandler
    Timer0B_IRQHandler
    Timer1A_IRQHandler
    Timer1B_IRQHandler
    Timer2A_IRQHandler
    Timer2B_IRQHandler
    Comp0_IRQHandler
    Comp1_IRQHandler
    Comp2_IRQHandler
    SysCtrl_IRQHandler
    FlashCtrl_IRQHandler
    GPIOPortF_IRQHandler
    GPIOPortG_IRQHandler
    GPIOPortH_IRQHandler
    USART2_IRQHandler
    SSI1_IRQHandler
    Timer3A_IRQHandler
    Timer3B_IRQHandler
    I2C1_IRQHandler
    QEI1_IRQHandler
    CAN0_IRQHandler
    CAN1_IRQHandler
    CAN2_IRQHandler
    Ethernet_IRQHandler
    Hibernate_IRQHandler
    USB0_IRQHandler
    PWMGen3_IRQHandler
    uDMAST_IRQHandler
    uDMAError_IRQHandler
    ADC1Seq0_IRQHandler
    ADC1Seq1_IRQHandler
    ADC1Seq2_IRQHandler
    ADC1Seq3_IRQHandler
    I2S0_IRQHandler
    EBI0_IRQHandler
    GPIOPortJ_IRQHandler
    Default_Handler
    __default_handler
            CALL_GRAPH_ROOT __default_handler, "interrupt"
            NOCALL __default_handler
            B __default_handler
              CFI EndBlock cfiBlock0
              
            END

  • Are you sure about the vector number?

    I found GPIO J uses vector 67 (TM4C1294NCPDT).

  • I don't know what to say.. I double checked the table order and it turned out my handler was pointing to the wrong exception. After fixing it, it finally worked.

    I went through all this trouble just because I didn't double check everything. Lesson learned I think. This seems to be a silly problem, but at least I learned more about startup files and disassembly because of this

    Thanks to you and Bill.

    Cheers

  • Ah.  Thanks for the update!
    Yeah, all the memory dumps I asked for looked correct (maybe the technique will come in handy again sometime.)
    I was just getting around to "Wait, does the Tiva-C Launchpad even HAVE a Port J?  Isn't that a TM4C123GH6PM that has vectors at 0x118 as "reserved"", and trying to figure our whether my documentation was up to date...

    There are some other TM4C chips (TM4C123GH6PGE) with a PortJ vector at 118, but they're not (AFAIK) on Launchpads...

  • BTW, my main theory for the possibly-corrupt vector table was that somehow you had added your new vectors, but the compiler was still including the default vector table from "somewhere else", resulting in your vectors getting appended rather than located at 0...