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.

UART interrupt stops working

Other Parts Discussed in Thread: OMAPL138We use the UART1 of an L138(DSP part) to communicate with a host PC (115200@8N1). Packets have 1kByte and are sent once a second to the PC and received about once a minute from the PC. The DSP of the L138 services the UART via interrupts. The link to the host is working fine as long as only one interrupt (either Receiver Data Ready (RDR) or Transmitter Holding Register Empty (THRE)) occurs. When both events occur at the same time, it happens sometimes that the UART stops signaling interrupts. It seems that the THRE interrupt is cleared when a RDR interrupt is read, so we changed the ISR to service the THRE by polling. The ISR serves reads the IIR-register and executes the RDR and timeout-ints. After that we poll the LSR-register to see if there is space in the TX-FIFO. It works much better now, but did not solve the problem completely. Still the UART hangs once in a while, when both interrupts occur at the same time. We think that it is the same reason here: e2e.ti.com/.../274366 Now the questions: Has anyone a bullet proof solution to this problem? Is there any recommendation from TI how to serve the UART interrupts correctly? Thanks, Alex
  • Welcome to the TI E2E forum. I hope you will find many good answers here and in the TI.com documents and in the TI Wiki Pages (for processor issues). Be sure to search those for helpful information and to browse for the questions others may have asked on similar topics (e2e.ti.com). Please read all the links below my signature.

    Moving this thread to OMAP-L1x forum for faster and appropriate response. Thank you for your patience.

    Note: We strongly recommend you to create new e2e thread for your queries instead of following up on an old/closed e2e thread, new threads gets more attention than old threads and can provide link of old threads or information on the new post for clarity and faster response.

  • Hi,

    Thanks for your post.

    I think, in your case, the Receive data-ready interrupt would have not cleared where Rx. FIFO drops below the trigger level under any of the unfortunate circumstances and because of this, you are not able to assert both the interrupts simultaneously.

    Please make sure that you are not getting any receiver time-out interrupt or any receiver line-status interrupt which will be triggered based out of over-run error, parity error, framing error or a break if any, because line-status interrupt has higher priority than the receiver data-ready interrupt.

    In general, if trigger level is reached, the UART FIFO will not accept any new data and what i mean to say here is, once the trigger level is reached, it will wait for the time duration of four character times as mentioned in Table 31-4 of TRM and of this duration, if you didn't find any access to UART FIFO, I mean, if the UART FIFO didn't drop below the trigger level which maintains the same trigger level as before, then the 2nd receiver data-ready interrupt will be asserted again.

    I think, alternatively you could try to download rCSL sample UART examples available for OMAPL138 as below:

    http://processors.wiki.ti.com/index.php/QuickStartOMAPL1x_rCSL#Downloads

    Try first the UART hyper terminal and UART interrupt loopback examples which uses interrupt to update the status of transmit and receive buffers. Kindly check the above link for the same.

    Thanks & regards,

    Sivaraj K

    -------------------------------------------------------------------------------------------------------

    Please click the Verify Answer button on this post if it answers your question.

    -------------------------------------------------------------------------------------------------------

  • Hello Sivaraj,

    Thanks for your suggestions!

    As I already wrote, the link to the PC works fine most of the time.
    Only when a receive and a transmit interrupt occur at the same time (which is a rather rare case in typical UART applications) we have this problems.

    First our ISR looked like this:

    switch(CSL_FEXT(uart2Regs->IIR, UART_IIR_INTID))
    {
    case RecLineStat:
    ..... set error flag / breakpoint ...;
    break;
    case RecDatRdy:
    case RecTimOut:
    ... read until RX FIFO is empty ...;
    break;
    case THRE:
    .... write max. 16 chars to TX FIFO...;
    .... disable TX int if transmission completed ... ;
    break;
    }

    As written in table 31-11 the THRE int is cleared by reading the IIR-register.
    This is as we would expect, but the THRE is cleared even if a RDR-int is read from the IIR.
    And then, after RDR is serviced the DSP jumps out of the ISR the UART seems to hang (because the THRE was cleared but not seviced?).
    After that, the UART triggers NO INT any more.
    By polling we see that a receive overflow occurs after a while, but this triggers no interrupt.

    This means that if a RDR and a THRE interrupt occur at the same time, reading the IIR gives you the ID of the RDR and semi-clears (?) the THRE-interrupt.


    We changed the ISR to :

    switch(CSL_FEXT(uart2Regs->IIR, UART_IIR_INTID))
    {
    case RecLineStat:
    ..... set error flag / breakpoint ...;
    break;
    case RecDatRdy:
    case RecTimOut:
    ... read until RX FIFO is empty ...;
    break;
    }
    if (THRE in Line Status Register is set)
    .... write max. 16 chars to TX FIFO...;
    .... disable TX int if transmission completed ... ;
    }

    With this change the behavior changed,
    the probability of UART hangs was reduced.
    But sometimes when RX and TX event occur at the same time, the UART still stops working.

    Thanks for your help,
    Alex
  • *push*

    Does anybody know a method for reliable int-based full-duplex transfer?

    Thanks,
    Alex
  • Just as an update:
    The Problem with the UART hangs in interrupt-based full duplex mode is still not solved.


    Thanks to TI for the useful help
    Alex
  • Try reading IIR register repeatedly until the IIR queue is empty. This is what I have seen in most ISR code out there.

    while((iir = CSL_FEXT(uart2Regs->IIR, UART_IIR_INTID)) != 0)
    {
    switch(iir)
    {
    ...
    }
    }
  • Hello Norman,

    unfortunately reading the IIR register only gives the ID of the RDR.

    If a THRE-condition occurs at the same time with the RDR, there is no second IIR-entry.

    It seems that reading the RDR from the IIR register also clears the pending THRE interrupt.

    Even if I check the THRE flag at the end of the ISR and service the transmitter if necessary it may happen that the UART-interrupt stops working.

    Thanks,

    Alex

  • I see what you mean. Ideally, you should see this sequence.
    1) UART rx and tx happen simultaneously. Sets Rx and Tx IRQ bits.
    2) ISR is called.
    3) Read IIR. Get a Receiver data-ready interrupt. Also clears Tx IRQ bit.
    4) Handle Rx interrupt which clears Rx IRQ bit.
    5) Read IIR again. Get a Transmitter holding register empty interrupt.
    6) Handle Tx interrupt. Tx IRQ bit is already cleared.
    Step 5 and 6 do not happen because IIR is 0.

    I used the following pseudo-code for my hander:

    uart_isr()
    {
    unsigned char iir;
    for(;;)
    {
    iir = IIR; // Read HW register
    if(iir & IPEND) break; // Pending bit is set if there is no pending interrupt
    iir &= INTID; // Extract type
    switch(iir)
    {
    ...
    }
    }
    }

    On occasion, my ISR would get called and the ID was 0. I seem to get called again and did not seem to miss interrupts. My usage was a command and response scenario where simultaneous IO was not likely. It is a bit disturbing that I could have a hung transmitter.

    The only wierdness with the Tx IRQ is that just enabling interrupts on an empty tx does not generate an Tx IRQ. I had to manually write one out first.

    The linux driver seems to check a for a cleared IIR pending bit (interrupt is pending) in a timer handler and restarts Tx.