TMDS64EVM: Regarding the UART Rx timeout interrupt

Part Number: TMDS64EVM

Hello TI support team.

I have a question regarding UART receive interrupts on the TMDS64EVM.

The "12.1.5.45 UART Interrupt Requests" section of the AM64x TRM lists "RX time-out" and "RHR interrupt."
Based on my reading of the documentation, it appears that an RX time-out interrupt occurs when stale data remains in the FIFO.
There is also a description regarding the time-out interrupt in section "1.5.4.8.1.3.7.1 Time-Out Counter."
Therefore, what are the specific criteria—such as the amount of data (in bytes) remaining in the FIFO and the duration for which it remains—that trigger the time-out interrupt?
I would like to know the specific timing sequence and conditions under which an RX time-out occurs.
For example, how many bytes must accumulate in the FIFO and how much time must elapse without them being read before an RX time-out occurs?

Also, is there a way to enable only the RHR interrupt while disabling the RX time-out interrupt?

Furthermore, when a receive interrupt occurs—specifically when the LSR's RX_FIFO_E bit is 0 and the IIR indicates an RX time-out—what value is returned when reading the RHR register? Is it an undefined value?

I would appreciate a prompt reply.

Best regards,

Kiyomasa Imaizumi.

  • Just a quick update: the core being used is the CA53.

  • One further point:
    Currently, I am encountering a situation where, upon a receive interrupt, the IIR indicates an "Rx time-out," yet the RX_FIFO_E bit in the LSR is 0.
    I surmise that multiple bytes of data were received, causing the RHR interrupt condition and the Rx time-out condition to occur almost simultaneously. Is this assumption correct?

    If the interrupt handler exits without reading the RHR when the LSR's RX_FIFO_E is 0 and the IIR indicates an Rx time-out, what happens to the IIR register if data is subsequently received? Will an interrupt trigger again, and will the IIR indicate an RHR interrupt, or will it indicate an Rx time-out?

  • Hello Kiyomasa Imaizumi,

    Therefore, what are the specific criteria—such as the amount of data (in bytes) remaining in the FIFO and the duration for which it remains—that trigger the time-out interrupt?

    The time-out interrupt fires when the following conditions are simultaneously true. Based on the AM64x TRM in section 12.1.5.4.8.1.3.7.1 Time-Out Counter:

    • At least 1 byte is present in the RX FIFO (no minimum byte count beyond 1; it does not need to be at or above the trigger level)
    • No new character has been received on the RX line for a duration equal to 4× the programmed character length + 12 baud clocks (the "idle" detection window)
    • No RHR read has occurred during that same idle window
    • The timeout counter is only running while data exists in the FIFO (default behavior: UART_EFR2[6] TIMEOUT_BEHAVE = 0)

    Character time reference for 8-bit words:

    1 start + 8 data + 1 parity + 1 stop = 11 bits per character 4 character times = 44 baud clocks

    So for 115200 baud with 8-bit words and 1 stop bit, the timeout fires after ~382 µs of RX line idle with at least one unread byte in the FIFO. You can override this default window by writing a custom value to the TIMEOUTH/TIMEOUTL registers (a non-zero value replaces the auto-calculated 4× character width).

    Also, is there a way to enable only the RHR interrupt while disabling the RX time-out interrupt?

    No, they share a single enable bit. From UART_IER_UART[0] in section 14.9.1.5.2.7 UART_IER_UART Register:

    Bit 0 — RHR_IT:

    • 0 = Disables the RHR interrupt and time-out interrupt.
    • 1 = Enables the RHR interrupt and time-out interrupt.

    The RHR interrupt and the RX time-out interrupt are controlled by the same IER bit. There is no independent bit to disable only the time-out while keeping the RHR interrupt active. They are inseparable in hardware on the AM64x UART (16C750-derived IP).

    Furthermore, when a receive interrupt occurs—specifically when the LSR's RX_FIFO_E bit is 0 and the IIR indicates an RX time-out—what value is returned when reading the RHR register? Is it an undefined value?

    LSR.RX_FIFO_E = 0 means the FIFO is empty — there are no valid bytes to read. Reading UART_RHR in this state will return an undefined/invalid value (no valid data is present). The TRM does not define a specific value returned on an empty-FIFO read of RHR, so you must not interpret that value as valid data.

     It is possible for IIR to show "RX Time-Out" when LSR.RX_FIFO_E = 0. There is a silicon erratum— Advisory i2310 in the AM64x Silicon Errata:

    i2310 USART: Erroneous clear/trigger of timeout interrupt The USART may erroneously clear or trigger the timeout interrupt when RHR/MSR/LSR registers are read.

    Specifically, the timeout interrupt can be erroneously asserted even when the FIFO is empty. Your scenario (IIR = RX time-out, but LSR.RX_FIFO_E = 0) is a recognized manifestation of this bug— it is not simply a race condition from simultaneous RHR + timeout conditions.

    Your hypothesis about simultaneous conditions is a reasonable interpretation for cases where data was present but was consumed very quickly (e.g., by a prior RHR interrupt service that fully drained the FIFO before the timeout interrupt was acknowledged). However, advisory i2310 makes it clear there is also a hardware-level erratum that can independently cause this. Workaround from i2310 (CPU use-case, erroneously set timeout with empty FIFO):

    • Write a high value to TIMEOUTH and TIMEOUTL registers
    • Set EFR2[6] = 1 (switch to periodic timeout mode)
    • Read the IIR register to clear the interrupt
    • Set EFR2[6] = 0 (restore default timeout mode)

    Best Regards,

    Borislav Lazarkov

  • Hello Borislav Lazarkov.

    Thank you for your reply.
    That was very helpful.

    I have a question based on your answer.


    1.
    I have some code I tested before receiving your reply.
    When a UART receive interrupt occurred, I included code within the interrupt handler to read the RHR if the IIR indicated an "Rx time-out" and the LSR's RX_FIFO_E bit was 0. Please refer to the pseudocode below.
    At that time, the Rx time-out condition appeared to be resolved.

    However, the i2310 requires a specific procedure involving registers like TIMEOUTH as part of its Rx time-out workaround.
    In reality, is simply reading the RHR insufficient to handle the Rx time-out? Should I implement only the i2310-specific workaround?
    Or is it necessary to read the RHR *in addition* to performing the i2310 workaround?
    Note that I am not using DMA for the UART.

    The pseudocode is provided below; some details have been omitted.
    Please let me know if you have any suggestions for improving the code implementation.

    void UartInterruptHandler()
    {
    	int c;
    	if(IIR == Rx timeout || IIR == RHR interrupt){
    		// Rx interrupt
    		if(LSR & RX_FIFO_E) {
    			// At least one data character in the RX FIFO
    			c = RHR;
    			putbuffer(c);
    		}else{
    			// Rx time-out !
    #if 1
    			int dummy = RHR; // RHR dummy read.Will the cause of the Rx time-out interrupt be resolved?
    #else
    			// i2310 Workaround
    			TIMEOUTH = 0xFF;
    			TIMEOUTL = 0xFF;
    			EFR2 |= 0x40; // bit 6 to 1
    			int dummy = IIR;  // dummy read
    			EFR2 &= 0x40; // bit 6 back to 0
    			// Is it necessary to read out the RHR?
    #endif
    		}
    	}
    }
    

    2.
    Currently, there is only one CPU board where the RX_FIFO_E flag is 0 due to an RX timeout when a receive interrupt occurs; this issue has not been observed on any other boards.
    Regarding the i2310, should this be considered an issue specific to individual CPU units—meaning it occurs on some but not others?

    Best regards,
    Kiyomasa Imaizumi.

  • Hello Kiyomasa Imazumi,

    1.

    These are two distinct scenarios and must not be confused with each other:

    • Scenario A — Normal (Non-Errata) RX Timeout: RHR Read Is Correct and Sufficient
      • Per the AM64x TRM section 12.1.5.4.5.1 UART Mode Interrupt Management interrupt table:

    IIR[5:0] = 001100 — RX time-out Interrupt Reset Method: "Read the UART_RHR register if using the default timeout behavior: EFR2[6]=0."

    In default mode (EFR2[6]=0), the timeout interrupt is cleared by reading RHR. Your current #if 1 code path, doing a dummy RHR read, is the correct hardware-specified mechanism for a true timeout interrupt. It is not a workaround; it is how the hardware is designed to work.

    Furthermore, per AM64x TRM section 12.1.5.4.8.1.3.7.1 Time-Out Counter:

    "…the count is reset when there is activity on RX or when the UART_RHR register is read."

    So reading RHR both:

    • Clears the timeout interrupt
    • Resets the timeout counter
    • Scenario B — Errata i2310: Timeout Erroneously Set with EMPTY FIFO
      • The i2310 workaround is only needed when the FIFO is confirmed empty (LSR.RX_FIFO_E = 0) yet IIR still shows timeout. In this case, reading RHR does not reliably clear the interrupt because there is no valid data to read — the hardware has fired the interrupt spuriously. The full sequence from the Errata document is required:
        • Write high value to TIMEOUTH/TIMEOUTL.
        • Set EFR2[6] = 1 (switch to periodic mode).
        • Read IIR (clears the interrupt in periodic mode).
        • Set EFR2[6] = 0 (restore default mode).

    Your code already checks LSR.RX_FIFO_E first. So:

    State

    LSR.RX_FIFO_E

    IIR

    What to do

    Data present

    1

    RHR or Timeout

    Read RHR → clears both interrupt types normally

    FIFO empty

    0

    Timeout

    This is the errata case → use i2310 workaround

    Your #if 1 branch (dummy RHR read on empty FIFO) may appear to work because reading any register during an erroneously-set interrupt may incidentally settle the hardware state in some silicon revisions, but it is not architecturally correct and is not guaranteed to work reliably. The i2310 workaround is the correct fix for the empty-FIFO + timeout case.

    Here is a corrected and improved version based on the TRM and erratum:

    void UartInterruptHandler(void)
    {
        uint32_t iir = IIR & 0x3F;  // Read IIR once; this also participates in clearing some interrupts
    
        if (iir == 0x0C || iir == 0x04)  // RX Timeout (001100) or RHR interrupt (000100)
        {
            uint32_t lsr = LSR;
    
            if (lsr & RX_FIFO_E)
            {
                // FIFO has data — drain it completely.
                // Always loop until empty; this handles both RHR trigger level
                // and timeout conditions in one unified path.
                do {
                    int c = RHR;
                    putbuffer(c);
                    lsr = LSR;
                } while (lsr & RX_FIFO_E);
            }
            else
            {
                // FIFO is empty yet IIR shows timeout.
                // This is the i2310 errata condition. Apply the documented workaround.
                TIMEOUTH = 0xFF;
                TIMEOUTL = 0xFF;
                EFR2 |= (1 << 6);       // Set EFR2[6] = 1 (periodic mode)
                (void)IIR;               // Read IIR to clear interrupt in periodic mode
                EFR2 &= ~(1 << 6);      // Restore EFR2[6] = 0 (default mode)
                // Do NOT read RHR here — the FIFO is empty and the read would be invalid.
            }
        }
    }
    

    2.

    i2310 applies to every AM64x silicon unit, on both revision 1.0 and revision 2.0. It is a silicon design defect present across the entire production population, not a manufacturing variation or a defect unique to individual units.

    The fact that you only observe it on one board does not mean the other boards are immune. i2310 is a race condition / timing-sensitive defect, it manifests only under specific register access timing, not unconditionally on every interrupt. Several factors can cause board-to-board variation in observability:

    • CPU clock speed / bus loading differences — Even minor PCB layout differences or power supply variations affect register access timing, which determines whether the race condition is hit.
    • UART traffic patterns — The erratum is triggered by reads of RHR, MSR, or LSR registers at a specific moment relative to the timeout counter. If the data rate or message cadence differs slightly between boards, the triggering conditions may not align on the other boards.
    • Interrupt latency — Any difference in interrupt response latency (e.g., CPU load, cache state, compiler optimization level) changes the exact timing of register reads relative to the timeout event, making it more or less likely to hit the race window.
    • Observability bias — Because i2310 can also cause the timeout interrupt to be erroneously cleared (not just erroneously set), the other boards may actually be hitting a different manifestation of the same bug — the timeout gets silently cleared and re-triggered, which appears normal and is therefore not noticed.

    Best Regards,

    Borislav Lazarkov