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.

Tiva TM4C123GH6P UART interrupt causing fault

Hello guys,

I have a very disturbing problem right know. Enabling the UART0 interrupt causes a FaultISR() call. This happens only in run mode. In debug mode, the code works fine.

Here is my code:

void UART_Init(void)
{
  //
  // Enable the peripherals.
  //
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
  SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
 
  //
  // Set GPIO A0 and A1 as UART pins.
  //
  GPIOPinConfigure(GPIO_PA0_U0RX);
  GPIOPinConfigure(GPIO_PA1_U0TX);
  GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
 
  //
  // Configure the UART for 38400, 8-N-1 operation.
  //
  UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 38400,
                          (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                           UART_CONFIG_PAR_NONE));
  //
  // Enable the UART interrupt.
  //
  UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);
  IntEnable(INT_UART0);
}

void UART_IntHandler(void)
{
  uint8 l_ucReceivedChar;
  uint32_t ui32Status;
 
  //
  // Get the interrrupt status.
  //
  ui32Status = UARTIntStatus(UART0_BASE, true);
 
  //
  // Clear the asserted interrupts.
  //
  UARTIntClear(UART0_BASE, ui32Status);
 
  //
  // Loop while there are characters in the receive FIFO.
  //
  while(UARTCharsAvail(UART0_BASE))
  {
    l_ucReceivedChar = UARTCharGet(UART0_BASE);
    ProcessRxChar(l_ucReceivedChar);
  }
}

The UART_IntHandler function is added in the startup_ewarm,c file in the vectors table.

Any suggestions ?

  • More specifically this function causes the problem:

    UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);

    If I remove this part: UART_INT_RT, the program runs ok but the uart receive interrupt is never called.

  • Tried using the ROM_ functions. No luck.

    Tried lowering the clock from 80Mhz to 40 Mhz. No luck.

    Tried changing the stack size. No luck.

    Using UART_BUFFERED. No luck.

  • Feel your pain mon ami - know this can be so frustrating.

    You've detailed your issue nicely - may I present the following for your review?

    From w/in uart.h: (now we use StellarisWare Ver 9453 - yours may somewhat differ...)

    // Values that can be passed to UARTIntEnable, UARTIntDisable, and UARTIntClear
    // as the ulIntFlags parameter, and returned from UARTIntStatus.
    //
    //*****************************************************************************
    #define UART_INT_9BIT           0x1000      // 9-bit address match interrupt
    #define UART_INT_OE             0x400       // Overrun Error Interrupt Mask
    #define UART_INT_BE             0x200       // Break Error Interrupt Mask
    #define UART_INT_PE             0x100       // Parity Error Interrupt Mask
    #define UART_INT_FE             0x080       // Framing Error Interrupt Mask
    #define UART_INT_RT            0x040       // Receive Timeout Interrupt Mask
    #define UART_INT_TX             0x020       // Transmit Interrupt Mask
    #define UART_INT_RX             0x010       // Receive Interrupt Mask
    #define UART_INT_DSR            0x008       // DSR Modem Interrupt Mask
    #define UART_INT_DCD            0x004       // DCD Modem Interrupt Mask
    #define UART_INT_CTS            0x002       // CTS Modem Interrupt Mask
    #define UART_INT_RI             0x001       // RI Modem Interrupt Mask

    Thus - should that def'n appear w/in your file set - it appears valid.  (and - we've past used w/success)

    You did mention your start-up file - and placement of, "UART Interrupt Handler."  Did you place it - both in the summary section - (atop the vector block) AND w/in the UART0 location w/in the Vector Table?

    [edit 2] 15:48 Just noted - it is "best practice" to clear interrupts prior to their enable - you've not done that.  Further - might you need to employ, "UARTFIFOLevelSet()" - prior to your call to UARTIntEnable() - so that the troublesome, "UART_INT_RT" becomes set & proper?  And, might a call to, "ROM_IntMasterEnable();" be necessary?  (such confuses me as well - often we make no such call - yet interrupts appear well behaved...)

    Suggest that you add these 4 lines of code (adding required parameters) and test/report...

       UARTEnable(UART0_BASE);    In the past - this was required - unsure now - cannot hurt to add/try!
      ROM_IntMasterEnable();          Definite "maybe"
      UARTFIFOLevelSet() // you must parameterize...   Definite "maybe"
      UARTIntClear();      // you must parameterize - do this first - and then:   Best practice...  yet "maybe"
     
      UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);
      IntEnable(INT_UART0);
     
    Examples abound - (i.e. Examples\Peripherals\Uart...) and may supply any, "missing link." [edit 1] or not - in this case - interrupts "not" in play - those Uart examples...
     
    Prior to seeing your post - thought (for sure) I understood UART operation via this vendor's API.  Now - not so much - may well be change between new rebrand library and past one - which we use.  (until convinced that new is indeed, "complete, bug-free, & stable...")
  • Thanks for your reply, I appreciate it. Unfortunately your suggestions don't work. :(

    But, after some hours of trying different configuration, I finally got it working. I removed the UART_INT_RT from the UARTIntEnable function and set the optimizations to low in IAR.

    It still annoys me, because I used the code from the examples. But it if works like this, it's fine ... for know.

  • Hi Andrei

    In the first post you mentioned that it happens in run mode and not in debug mode. How do you check that it is in FaultISR?

    Secondly when it happens, can you check the content of the FAULTSTAT registers at address 0xE000ED28 and 0xE000ED38?


    Regards

    Amit

  • I turned on a LED in FaultISR. ED28 reads 0x8200 and ED38 0x8000.

    I found out that 0x8200 means a bus fault, but I have no idea what 0x8000 means. It's not specified anywhere.

    It still doesn't work as it should. Only enters the receive interrupt randomly.

  • Hi Andrei,

    The CPU tried to write to 0x8000 location which is Flash. I would need the full code so that I can check, or at least the clock configuration SysCtlClockSet API parameters.

    Secondly does this happen immediately or is a random failure?

    Regards

    Amit

  • You can get the code from here : http://1drv.ms/MppNPQ

    It happens immediately. I do hope you can find the problem.

    Thanks,

    Andrei

  • Hi,

    It is wise to learn yourself to debug faults - there is an application note explaining how to do it. Take into account the fault machine is complex and helpful at same time : http://www.ti.com/lit/an/spma043/spma043.pdf

    Such problems can arise any time, so be prepared to solve them.

  • Hi Andrei,

    I can get it to Fault even when the debugger is connected in single stepping and the UART_INT_RT is not set. The issue seems to be in the CRC checker function.

    Also looking at the Fault Register the issue is that the CPU tried to access 0x20008000 location which is more than 32KB SRAM

    Regards

    Amit