This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

EK-TM4C129EXL: faultISR( ) using modified Tivaware uDMA ping-pong example

Part Number: EK-TM4C129EXL
Other Parts Discussed in Thread: TM4C129ENCPDT

Hi all!
I am working on a project based on the uDMA ping-pong example of the Tivaware library, where the Data is then sent via TCP to a remote server [Compilled using gnu linaro v9.2.1 on the EK-TM4C129EXL]. Currently, I face a faultISR() after a couple of thousands of execution of the main loop (the server receives about 10k packets before the faultISR()).
I read the `Diagnosing Software Faults in Stellaris® Microcontrollers` (spma043.pdf) and checked the NVIC_FAULT_STAT where (NVIC_FAULT_STAT_IMPRE=1 and other bits to 0). Checking the value of the stack pointer at MSP=0x200022324, the xPSR=0x0000CFCF points to this section of the disassembly of my code:

          sys_now():
0000cf80:   B480                push       {r7}
0000cf82:   AF00                add        r7, r13, #0
 69           return(g_ui32LocalTimer);
0000cf84:   4B03                ldr        r3, [pc, #0xc]
0000cf86:   681B                ldr        r3, [r3]
 70       }
0000cf88:   4618                mov        r0, r3
0000cf8a:   46BD                mov        r13, r7
0000cf8c:   F85D7B04            ldr        r7, [r13], #4
0000cf90:   4770                bx         r14
0000cf92:   BF00                nop        
0000cf94:   9E10                ldr        r6, [r13, #0x40]
0000cf96:   2000                movs       r0, #0
 83       {
          sys_arch_protect():
0000cf98:   B580                push       {r7, r14}
0000cf9a:   AF00                add        r7, r13, #0
 84         return((sys_prot_t)MAP_IntMasterDisable());
0000cf9c:   4B03                ldr        r3, [pc, #0xc]
0000cf9e:   681B                ldr        r3, [r3]
0000cfa0:   3308                adds       r3, #8
0000cfa2:   681B                ldr        r3, [r3]
0000cfa4:   4798                blx        r3
0000cfa6:   4603                mov        r3, r0
 85       }
0000cfa8:   4618                mov        r0, r3
0000cfaa:   BD80                pop        {r7, pc}
0000cfac:   0048                lsls       r0, r1, #1
0000cfae:   0100                lsls       r0, r0, #4
 98       {
          sys_arch_unprotect():
0000cfb0:   B580                push       {r7, r14}
0000cfb2:   B082                sub        r13, #8
0000cfb4:   AF00                add        r7, r13, #0
0000cfb6:   4603                mov        r3, r0
0000cfb8:   71FB                strb       r3, [r7, #7]
101         if(!(lev & 1)) {
0000cfba:   79FB                ldrb       r3, [r7, #7]
0000cfbc:   F0030301            and        r3, r3, #1
0000cfc0:   2B00                cmp        r3, #0
0000cfc2:   D104                bne        #0xcfce
102           MAP_IntMasterEnable();
0000cfc4:   4B04                ldr        r3, [pc, #0x10]
0000cfc6:   681B                ldr        r3, [r3]
0000cfc8:   3304                adds       r3, #4
0000cfca:   681B                ldr        r3, [r3]
0000cfcc:   4798                blx        r3
104       }
0000cfce:   BF00                nop        // <--------HERE 
0000cfd0:   3708                adds       r7, #8
0000cfd2:   46BD                mov        r13, r7
0000cfd4:   BD80                pop        {r7, pc}
0000cfd6:   BF00                nop        
0000cfd8:   0048                lsls       r0, r1, #1
0000cfda:   0100                lsls       r0, r0, #4
 240      {
          InitDMADescriptors():
0000cfdc:   B580                push       {r7, r14}
0000cfde:   B082                sub        r13, #8
0000cfe0:   AF00                add        r7, r13, #0
 244         for(ui32Loop = 0; ui32Loop < NUM_TX_DESCRIPTORS; ui32Loop++)
0000cfe2:   2300                movs       r3, #0
0000cfe4:   607B                str        r3, [r7, #4]
0000cfe6:   E03F                b          #0xd068
 246             g_pTxDescriptors[ui32Loop].pBuf = (struct pbuf *)0;
0000cfe8:   4977                ldr        r1, [pc, #0x1dc]
0000cfea:   687A                ldr        r2, [r7, #4]
0000cfec:   4613                mov        r3, r2
0000cfee:   00DB                lsls       r3, r3, #3
0000cff0:   4413                add        r3, r2
0000cff2:   009B                lsls       r3, r3, #2
0000cff4:   440B                add        r3, r1
0000cff6:   3320                adds       r3, #0x20
0000cff8:   2200                movs       r2, #0
0000cffa:   601A                str        r2, [r3]
 247             g_pTxDescriptors[ui32Loop].Desc.ui32Count = 0;
0000cffc:   4972                ldr        r1, [pc, #0x1c8]
0000cffe:   687A                ldr        r2, [r7, #4]
0000d000:   4613                mov        r3, r2
0000d002:   00DB                lsls       r3, r3, #3
0000d004:   4413                add        r3, r2
0000d006:   009B                lsls       r3, r3, #2
0000d008:   440B                add        r3, r1
0000d00a:   3304                adds       r3, #4
0000d00c:   2200                movs       r2, #0
0000d00e:   601A                str        r2, [r3]
 248             g_pTxDescriptors[ui32Loop].Desc.pvBuffer1 = 0;

But I am out of luck when it comes to identifying the issue in the assembly.
If anyone can give me some input about how to find the cause of the fault ISRR, I would greatly appreciate it.
Thanks,
Pierrick.

  • Hello Pierrick,

    My first thought with such an error is a potential stack overflow issue. How much stack are you using and have you tried increasing that?

    Now then going into the code you shared - it's interesting that this is occurring when you enable processor interrupts - or at least it looks like that is what is going on.

    That would indicate something happened where the NVIC is now able to try and process interrupts but one of those interrupts caused a Fault. It's hard to say what that would be with the data presented, but something you could try and do is review how different interrupts are configured and handled to see if there is a flaw somewhere with your interrupts. Not sure how many are being used so that might be too broad of a search, but it's a thought that comes to mind.

    Another area worth poking at is the stack pointer. The address for the stack pointer looks incorrect by the way - can you verify what the actual value is? I am going to assume it is 0x2000.2324 which would be a valid value and points to a location in RAM. With that address, you can look into the memory browser to see what variable is there. One thing to check would be to see if there is a buffer preceding it, and then it would be worth to check for any possible buffer overflow too. But it may also give you another clue to see what the SP was trying to access from RAM.

    Best Regards,

    Ralph Jacobi

  • Hello Ralph,

    Thank you for your answer! 

    1)  I thought about a potential stack overflow issue, but I am not quite sure how I can change the stack size when using GCC. It is pretty straightforward with the Ti compiler, but as far as I understand, changing the stack size with a GCC project requires changing the .lds and startup_css_gcc.c files of the project. I admit I don't completely understand how to read these; I have attached them and would really appreciate it if you could help me with that.

    tm4c129encpdt.lds

     

    /******************************************************************************
     *
     * Default Linker script for the Texas Instruments TM4C129ENCPDT
     *
     * This is derived from revision 15071 of the TivaWare Library.
    
     *****************************************************************************/
    
    MEMORY
    {
        FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x00100000
        SRAM (WX)  : ORIGIN = 0x20000000, LENGTH = 0x00040000
    }
    
    REGION_ALIAS("REGION_TEXT", FLASH);
    REGION_ALIAS("REGION_BSS", SRAM);
    REGION_ALIAS("REGION_DATA", SRAM);
    REGION_ALIAS("REGION_STACK", SRAM);
    REGION_ALIAS("REGION_HEAP", SRAM);
    REGION_ALIAS("REGION_ARM_EXIDX", FLASH);
    REGION_ALIAS("REGION_ARM_EXTAB", FLASH);
    
    SECTIONS {
    
        PROVIDE (_intvecs_base_address = 0x0);
    
        .intvecs (_intvecs_base_address) : AT (_intvecs_base_address) {
            KEEP (*(.intvecs))
        } > REGION_TEXT
    
        PROVIDE (_vtable_base_address = 0x20000000);
    
        .vtable (_vtable_base_address) : AT (_vtable_base_address) {
            KEEP (*(.vtable))
        } > REGION_DATA
    
        .text : {
            CREATE_OBJECT_SYMBOLS
            *(.text)
            *(.text.*)
            . = ALIGN(0x4);
            KEEP (*(.ctors))
            . = ALIGN(0x4);
            KEEP (*(.dtors))
            . = ALIGN(0x4);
            __init_array_start = .;
            KEEP (*(.init_array*))
            __init_array_end = .;
            *(.init)
            *(.fini*)
        } > REGION_TEXT
    
        PROVIDE (__etext = .);
        PROVIDE (_etext = .);
        PROVIDE (etext = .);
    
        .rodata : {
            *(.rodata)
            *(.rodata*)
        } > REGION_TEXT
    
        .data : ALIGN (4) {
            __data_load__ = LOADADDR (.data);
            __data_start__ = .;
            *(.data)
            *(.data*)
            . = ALIGN (4);
            __data_end__ = .;
        } > REGION_DATA AT> REGION_TEXT
    
        .ARM.exidx : {
            __exidx_start = .;
            *(.ARM.exidx* .gnu.linkonce.armexidx.*)
            __exidx_end = .;
        } > REGION_ARM_EXIDX
    
        .ARM.extab : {
            *(.ARM.extab* .gnu.linkonce.armextab.*)
        } > REGION_ARM_EXTAB
    
        .bss : {
            __bss_start__ = .;
            *(.shbss)
            *(.bss)
            *(.bss.*)
            *(COMMON)
            . = ALIGN (4);
            __bss_end__ = .;
        } > REGION_BSS
    
        .heap : {
            __heap_start__ = .;
            end = __heap_start__;
            _end = end;
            __end = end;
            KEEP(*(.heap))
            __heap_end__ = .;
            __HeapLimit = __heap_end__;
        } > REGION_HEAP
    
        .stack : ALIGN(0x8) {
            _stack = .;
            __stack = .;
            KEEP(*(.stack))
        } > REGION_STACK
    }
    

    tm4c129encpdt_startup_ccs_gcc.c

    //*****************************************************************************
    //
    // Startup code for use with TI's Code Composer Studio and GNU tools.
    //
    // Copyright (c) 2011-2014 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    //
    // Software License Agreement
    //
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    //
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    //
    //*****************************************************************************
    
    #include <stdint.h>
    
    //*****************************************************************************
    //
    // Forward declaration of the default fault handlers.
    //
    //*****************************************************************************
    void ResetISR(void);
    static void NmiSR(void);
    static void FaultISR(void);
    static void IntDefaultHandler(void);
    
    #ifndef HWREG
    #define HWREG(x) (*((volatile uint32_t *)(x)))
    #endif
    
    //*****************************************************************************
    //
    // The entry point for the application.
    //
    //*****************************************************************************
    extern int main(void);
    
    //*****************************************************************************
    //
    // Reserve space for the system stack.
    //
    //*****************************************************************************
    //__attribute__ ((section(".stack")))
    
    static uint32_t pui32Stack[128];
    
    //*****************************************************************************
    //
    // External declarations for the interrupt handlers used by the application.
    //
    //*****************************************************************************
    // registering the ADC interrupt to the NVIC
    extern void _c_int00(void);
    extern void ADCSeq0Handler(void);
    extern void uDMAErrorHandler(void);
    // registering the Ethernet interrupt to the NVIC
    extern void lwIPEthernetIntHandler(void);
    extern void SysTickIntHandler(void);
    
    //*****************************************************************************
    //
    // The vector table.  Note that the proper constructs must be placed on this to
    // ensure that it ends up at physical address 0x0000.0000 or at the start of
    // the program if located at a start address other than 0.
    //
    //*****************************************************************************
    __attribute__((section(".intvecs"))) void (*const g_pfnVectors[])(void) =
        {
            (void (*)(void))((uint32_t)pui32Stack + sizeof(pui32Stack)),
            // The initial stack pointer
            ResetISR,          // The reset handler
            NmiSR,             // The NMI handler
            FaultISR,          // The hard fault handler
            IntDefaultHandler, // The MPU fault handler
            IntDefaultHandler, // The bus fault handler
            IntDefaultHandler, // The usage fault handler
            0,                 // Reserved
            0,                 // Reserved
            0,                 // Reserved
            0,                 // Reserved
            IntDefaultHandler, // SVCall handler
            IntDefaultHandler, // Debug monitor handler
            0,                 // Reserved
            IntDefaultHandler, // The PendSV handler
            // IntDefaultHandler,      // The SysTick handler
            SysTickIntHandler, // The SysTick handler
            IntDefaultHandler, // GPIO Port A
            IntDefaultHandler, // GPIO Port B
            IntDefaultHandler, // GPIO Port C
            IntDefaultHandler, // GPIO Port D
            IntDefaultHandler, // GPIO Port E
            IntDefaultHandler, // UART0 Rx and Tx
            IntDefaultHandler, // UART1 Rx and Tx
            IntDefaultHandler, // SSI0 Rx and Tx
            IntDefaultHandler, // I2C0 Master and Slave
            IntDefaultHandler, // PWM Fault
            IntDefaultHandler, // PWM Generator 0
            IntDefaultHandler, // PWM Generator 1
            IntDefaultHandler, // PWM Generator 2
            IntDefaultHandler, // Quadrature Encoder 0
            ADCSeq0Handler,    // TODO: ADC Sequence 0
            IntDefaultHandler, // ADC Sequence 1
            IntDefaultHandler, // ADC Sequence 2
            IntDefaultHandler, // ADC Sequence 3
            IntDefaultHandler, // Watchdog timer
            IntDefaultHandler, // Timer 0 subtimer A
            IntDefaultHandler, // Timer 0 subtimer B
            IntDefaultHandler, // Timer 1 subtimer A
            IntDefaultHandler, // Timer 1 subtimer B
            IntDefaultHandler, // Timer 2 subtimer A
            IntDefaultHandler, // Timer 2 subtimer B
            IntDefaultHandler, // Analog Comparator 0
            IntDefaultHandler, // Analog Comparator 1
            IntDefaultHandler, // Analog Comparator 2
            IntDefaultHandler, // System Control (PLL, OSC, BO)
            IntDefaultHandler, // FLASH Control
            IntDefaultHandler, // GPIO Port F
            IntDefaultHandler, // GPIO Port G
            IntDefaultHandler, // GPIO Port H
            IntDefaultHandler, // UART2 Rx and Tx
            IntDefaultHandler, // SSI1 Rx and Tx
            IntDefaultHandler, // Timer 3 subtimer A
            IntDefaultHandler, // Timer 3 subtimer B
            IntDefaultHandler, // I2C1 Master and Slave
            IntDefaultHandler, // CAN0
            IntDefaultHandler, // CAN1
            // IntDefaultHandler, // Ethernet
            lwIPEthernetIntHandler, // Ethernet
            IntDefaultHandler,      // Hibernate
            IntDefaultHandler,      // USB0
            IntDefaultHandler,      // PWM Generator 3
            IntDefaultHandler,      // uDMA Software Transfer
            uDMAErrorHandler,  // TODO: error handler defined in the ping pong example
            IntDefaultHandler, // ADC1 Sequence 0
            IntDefaultHandler, // ADC1 Sequence 1
            IntDefaultHandler, // ADC1 Sequence 2
            IntDefaultHandler, // ADC1 Sequence 3
            IntDefaultHandler, // External Bus Interface 0
            IntDefaultHandler, // GPIO Port J
            IntDefaultHandler, // GPIO Port K
            IntDefaultHandler, // GPIO Port L
            IntDefaultHandler, // SSI2 Rx and Tx
            IntDefaultHandler, // SSI3 Rx and Tx
            IntDefaultHandler, // UART3 Rx and Tx
            IntDefaultHandler, // UART4 Rx and Tx
            IntDefaultHandler, // UART5 Rx and Tx
            IntDefaultHandler, // UART6 Rx and Tx
            IntDefaultHandler, // UART7 Rx and Tx
            IntDefaultHandler, // I2C2 Master and Slave
            IntDefaultHandler, // I2C3 Master and Slave
            IntDefaultHandler, // Timer 4 subtimer A
            IntDefaultHandler, // Timer 4 subtimer B
            IntDefaultHandler, // Timer 5 subtimer A
            IntDefaultHandler, // Timer 5 subtimer B
            IntDefaultHandler, // FPU
            0,                 // Reserved
            0,                 // Reserved
            IntDefaultHandler, // I2C4 Master and Slave
            IntDefaultHandler, // I2C5 Master and Slave
            IntDefaultHandler, // GPIO Port M
            IntDefaultHandler, // GPIO Port N
            0,                 // Reserved
            IntDefaultHandler, // Tamper
            IntDefaultHandler, // GPIO Port P (Summary or P0)
            IntDefaultHandler, // GPIO Port P1
            IntDefaultHandler, // GPIO Port P2
            IntDefaultHandler, // GPIO Port P3
            IntDefaultHandler, // GPIO Port P4
            IntDefaultHandler, // GPIO Port P5
            IntDefaultHandler, // GPIO Port P6
            IntDefaultHandler, // GPIO Port P7
            IntDefaultHandler, // GPIO Port Q (Summary or Q0)
            IntDefaultHandler, // GPIO Port Q1
            IntDefaultHandler, // GPIO Port Q2
            IntDefaultHandler, // GPIO Port Q3
            IntDefaultHandler, // GPIO Port Q4
            IntDefaultHandler, // GPIO Port Q5
            IntDefaultHandler, // GPIO Port Q6
            IntDefaultHandler, // GPIO Port Q7
            IntDefaultHandler, // GPIO Port R
            IntDefaultHandler, // GPIO Port S
            IntDefaultHandler, // SHA/MD5 0
            IntDefaultHandler, // AES 0
            IntDefaultHandler, // DES3DES 0
            IntDefaultHandler, // LCD Controller 0
            IntDefaultHandler, // Timer 6 subtimer A
            IntDefaultHandler, // Timer 6 subtimer B
            IntDefaultHandler, // Timer 7 subtimer A
            IntDefaultHandler, // Timer 7 subtimer B
            IntDefaultHandler, // I2C6 Master and Slave
            IntDefaultHandler, // I2C7 Master and Slave
            IntDefaultHandler, // HIM Scan Matrix Keyboard 0
            IntDefaultHandler, // One Wire 0
            IntDefaultHandler, // HIM PS/2 0
            IntDefaultHandler, // HIM LED Sequencer 0
            IntDefaultHandler, // HIM Consumer IR 0
            IntDefaultHandler, // I2C8 Master and Slave
            IntDefaultHandler, // I2C9 Master and Slave
            IntDefaultHandler, // GPIO Port T
            IntDefaultHandler, // Fan 1
            0,                 // Reserved
    };
    
    //*****************************************************************************
    //
    // The following are constructs created by the linker, indicating where the
    // the "data" and "bss" segments reside in memory.  The initializers for the
    // for the "data" segment resides immediately following the "text" segment.
    //
    //*****************************************************************************
    extern uint32_t __data_load__;
    extern uint32_t __data_start__;
    extern uint32_t __data_end__;
    extern uint32_t __bss_start__;
    extern uint32_t __bss_end__;
    
    //*****************************************************************************
    //
    // This is the code that gets called when the processor first starts execution
    // following a reset event.  Only the absolutely necessary set is performed,
    // after which the application supplied entry() routine is called.  Any fancy
    // actions (such as making decisions based on the reset cause register, and
    // resetting the bits in that register) are left solely in the hands of the
    // application.
    //
    //*****************************************************************************
    void ResetISR(void)
    {
        uint32_t *pui32Src, *pui32Dest;
    
        //
        // Copy the data segment initializers from flash to SRAM.
        //
        pui32Src = &__data_load__;
        for (pui32Dest = &__data_start__; pui32Dest < &__data_end__;)
        {
            *pui32Dest++ = *pui32Src++;
        }
    
        //
        // Zero fill the bss segment.
        //
        __asm("    ldr     r0, =__bss_start__\n"
              "    ldr     r1, =__bss_end__\n"
              "    mov     r2, #0\n"
              "    .thumb_func\n"
              "zero_loop:\n"
              "        cmp     r0, r1\n"
              "        it      lt\n"
              "        strlt   r2, [r0], #4\n"
              "        blt     zero_loop");
    
        //
        // Enable the floating-point unit.  This must be done here to handle the
        // case where main() uses floating-point and the function prologue saves
        // floating-point registers (which will fault if floating-point is not
        // enabled).  Any configuration of the floating-point unit using DriverLib
        // APIs must be done here prior to the floating-point unit being enabled.
        //
        // Note that this does not use DriverLib since it might not be included in
        // this project.
        //
        HWREG(0xE000ED88) = ((HWREG(0xE000ED88) & ~0x00F00000) | 0x00F00000);
    
        //
        // Call the application's entry point.
        //
        main();
    }
    
    //*****************************************************************************
    //
    // This is the code that gets called when the processor receives a NMI.  This
    // simply enters an infinite loop, preserving the system state for examination
    // by a debugger.
    //
    //*****************************************************************************
    static void
    NmiSR(void)
    {
        //
        // Enter an infinite loop.
        //
        while (1)
        {
        }
    }
    
    //*****************************************************************************
    //
    // This is the code that gets called when the processor receives a fault
    // interrupt.  This simply enters an infinite loop, preserving the system state
    // for examination by a debugger.
    //
    //*****************************************************************************
    static void
    FaultISR(void)
    {
        //
        // Enter an infinite loop.
        //
    //    SysCtlReset();
    //    ResetISR();
        while (1)
        {
        }
    }
    
    //*****************************************************************************
    //
    // This is the code that gets called when the processor receives an unexpected
    // interrupt.  This simply enters an infinite loop, preserving the system state
    // for examination by a debugger.
    //
    //*****************************************************************************
    static void
    IntDefaultHandler(void)
    {
        //
        // Go into an infinite loop.
        //
        while (1)
        {
        }
    }
    

    2) I will check all my interrupts and let you know if I find something odd.

    3) For the stack pointer, my apologies. There were an extra 2 and MSP=0x2000.2324. To confirm the way to read it, using the following screenshot: I am reading the MSP register (0x2000.2384) and then using the memory browser to find the value of xPSR (0x0000.0B53) like explained on page 11 of spma043.pdf. Is that correct?

    4) Finally, since my last post, I discovered that the value in the NVIC_FAULT_STAT is not always the same. I encountered value of (NVIC_FAULT_STAT_INVPC=1 other 0) and (NVIC_FAULT_STAT_BFARV=1, NVIC_FAULT_STAT_PRECISE=1, other 0). Do I need to consider these issues as separate issues or related ones?

    Best,
    Pierrick

  • Hello Pierrick,

    //*****************************************************************************
    //
    // Reserve space for the system stack.
    //
    //*****************************************************************************
    //__attribute__ ((section(".stack")))
    
    static uint32_t pui32Stack[128];

    Here is where to increase the stack size in the startup file. 128 bytes is a very small stack for this program. I would recommend a notable bump, you have a ton of RAM on this device so you can easily do something like 1024 or 2048 which is what we typically start at for TCP applications,

    This would be my leading guess - especially if you are getting multiple errors, because stack overflow could cause different faults.

    Best Regards,

    Ralph Jacobi

  • Hello Ralph,
    Thanks for the answer; that did it! The firmware has been running for 3hours without issues. So I am marking this as resolved.
    Best regards, 
    Pierrick