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.

TM4C123GH6PM: UART stops working when enabling overrun error interrupts

Part Number: TM4C123GH6PM


As I mentioned in my previous few forum posts, i'm implementing the FreeMODBUS library on the TM4C123GH6PM. I managed to get it working, and successfully tested it with Modbus Poll on Windows. Now i'm implementing the Modbus diagnostics function, and I need to enable UART overrun interrupts to count the number of overrun errors. However, something unexpected happens.

The Modbus application periodically calls the following code, in order to enable and disable UART Rx/Tx interrupts:

When running the application with this code in debugging mode, I can pause the execution of the code or stop at a breakpoint, and then resume the application as normal. Everything still works as expected - the controller continues to receive and send Modbus messages. Now I want to add the following mask to the UARTIntEnable function calls, in order to enable UART overrun error interrupts:

If I add this code, the application initially works as expected. However if I pause the application, or stop and resume from a breakpoint, the application stops working. The UART interrupts are no longer triggered, and Modbus messages are no longer sent or received. I have no idea why this happens, and I would be hesitant to use this code in the final controller build. The UART ISR currently looks as follows - I haven't even tried to handle the overrun error interrupts yet:

Any help would be greatly appreciated.

Many thanks,

Ksawery 

  • Not sure, but here is a thought. When you suspend the CPU you create an overrun. When you resume, both the overrun and the RX interrupts are set. When you check the status for "ui32status == UART_INT_RX" it will fail because the status is "UART_INT_RX | UART_INT_OE", so you don't read any characters from the FIFO. Since the FIFO is full, the next character received creates a new overrun and again, the interrupt routine does not read any characters from the FIFO. Your check for a RX interrupt might be better written as:

        if((ui32status & UART_INT_RX) != 0u)
    

    Some additional suggestions. If you are using the FIFO you might want to also enable the receive timeout interrupt and check for either the FIFO level or the timeout.

        if((ui32Istatus & (UART_INT_RX | UART_INT_RT)) != 0)
    

    Also, you might want to move the line clearing the interrupts to earlier in the service routine. Here is the note in "uart.c" above the UARTIntClear() function:

    //! \note Because there is a write buffer in the Cortex-M processor, it may
    //! take several clock cycles before the interrupt source is actually cleared.
    //! Therefore, it is recommended that the interrupt source be cleared early in
    //! the interrupt handler (as opposed to the very last action) to avoid
    //! returning from the interrupt handler before the interrupt source is
    //! actually cleared.  Failure to do so may result in the interrupt handler
    //! being immediately reentered (because the interrupt controller still sees
    //! the interrupt source asserted).
    

  • Thank you very much for your detailed reply, its very helpful. I will try your suggestions tomorrow and see if that solves my problem. The UART FIFO is disabled by the way. In terms of checking for interrupts, should I use the format you suggested to isolate the different interrupt sources, in addition to the receive interrupt? So:

    if((ui32status & UART_INT_RX) != 0u) {} //receive

    if((ui32status & UART_INT_TX) != 0u) {} // transmit

    if((ui32status & UART_INT_OE) != 0u) {} // overrun error

    etc.

    Best regards,

    Ksawery

  • Yes because more than one interrupt flag can be valid at the same time. By checking each flag individually you will service each issue even if more than one is pending.

  • Thank you. I implemented your suggestions and it has fixed the issue, the controller continues to receive and send data after resuming the application. What I observe now however, is that the overrun error is detected when I pause the program the first time, but not subsequent times. I'm not sure why that is? Shouldn't the overrun error be triggered every time the CPU is suspended, and new data keeps coming in? Now i'm wondering whether the ISR is capturing all overrun errors correctly. My ISR now looks as follows:

    xMBDiagUpdateCounter(DIAG_COUNT_8) is called only once, despite pausing the program multiple times.

    Regards,

    Ksawery

  • I don't see an issue with the interrupt routine. Not sue why you would not get subsequent overflow errors.

  • Ok. Well as long as the ISR is correct, the controller should work as expected in the final build.

    Regards,

    Ksawery