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.

[TDA4VM] UART rx timeout interrupt cannot be disabled

Other Parts Discussed in Thread: DRA829, TDA4VM

In "J721E DRA829/TDA4VM/AM752x Processors Silicon Revision 1.0" (Literature Number: SPRUIL1A), it mentions that UART RHR interrupt and time-out interrupt can be disabled by setting UART_IER_UART[0].

Bit    Field        Type      Reset     Description

0      RHR_IT   R/W       0h          0h = Disables the RHR interrupt and time-out interrupt
                                                    1h = Enables the RHR interrupt and time-out interrupt

So I wrote a UART ISR to handle interrupts, when a RX timeout interrupt coming the ISR will set RHR_IT bit to disable it and notify another task to handle the rest works, such as reading the character in RX FIFO and so forth. The RX timeout interrupt will be enabled again in the task if RX FIFO has no character. But I found even I had disabled the RX timeout interrupt first, It will still happen before the task enable it. Can the RHR_IT bit of UART_IER_UART really disable the RX timeout interrupt on TDA4VM?

  • Hi Hunkli,

    If i look at the serial 8250 driver: drivers/tty/serial/8250/8250_omap.c.

    The RX Timeout disabling is done by disabling both RHR_IT & LINE_STS_IT bits.
    Basically bit0 & bit2 are disabled in conjunction. Could you try that and let me know if it helps your case.

    Re-enabling is again by setting both the bits.

    Regards,
    Keerthy

  • Hi Hunkli,

    In the Linux folder of the PSDKLA.

    ti-processor-sdk-linux-automotive-j7-evm-06_02_00/board-support/linux-4.19.94+gitAUTOINC+5a23bc00e0-g5a23bc00e0

    If yo look at the serial 8250 driver: drivers/tty/serial/8250/8250_omap.c:

    /*
    * Disable RX timeout, read IIR to clear
    * current timeout condition, clear EFR2 to
    * periodic timeouts, re-enable interrupts.
    */
    up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
    serial_out(up, UART_IER, up->ier);
    omap_8250_rx_dma_flush(up);
    serial_in(up, UART_IIR);
    serial_out(up, UART_OMAP_EFR2, 0x0);

    On top of disabling the RHR_IT and LINE_STS_IT

    1) EFR2 register is cleared to 0x0. Could you please do that as well
    2) Read IIR register: UART_IIR_UART

    All the steps are mentioned in the same document you referred: 
    https://www.ti.com/lit/ug/spruil1a/spruil1a.pdf

    Section: 

    12.1.6.4.8.1.3.9 Time-Out and Break Conditions

    Regards,
    Keerthy

  • Hi Keerthy,

    I tried them to disable RX timeout interrupt in my ISR handler:

    when RX timeout interrupt comes,

    1. disable both RHR_IT and LINE_STS_IT in UART_IER_UART

    2. read UART_IIR_UART

    3. set UART_EFR2 to 0x0

    ... (the rest of works)

    Unfortunately, the RX timeout interrupt still keeps happening before the RX FIFO reading task re-enable it.

    Looks like it cannot disable the interrupt :(  

  • Hi Hunkli,

    I believe until the FIFO is read out fully this cannot be disabled. I checked
    with the UART expert and he also had similar views.

    Hope this clarifies. Could you resolve the issue if you nothing more on top?

    - Keerthy

  • Hi Keerthy,

    Thanks for the information.

    So the RHR_IT bit actually can't disable the RX timeout interrupt on TDA4VM, it's the hardware designed behavior, right?

    Because I also have an AM572X IDK board, which UART module is similar to TDA4VM. It seems that the RX timeout interrupt can be disabled by setting RHR_IT on AM572x. I can disable the RX timeout int in the ISR handler and re-enable it in another task.

  • Hi Hunkli,

    Let me check on my end and get back to you with details in sometime.

    Thanks,
    Keerthy

  • Hi Hunkli,

    A quick suggestion from the UART expert was to remove all the accesses to EFR2 and see if that helps your case on
    TDA4.

    diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
    index 8c86d1b2f1a6..4be2493e1831 100644
    --- a/drivers/tty/serial/8250/8250_omap.c
    +++ b/drivers/tty/serial/8250/8250_omap.c
    @@ -1217,7 +1217,6 @@ static struct omap8250_dma_params am33xx_dma = {
     
     static struct omap8250_platdata am654_platdata = {
        .dma_params   = &am654_dma,
    -    .habit     = UART_HAS_EFR2,
     };

    Regards,
    Keerthy

  • Hi Keerthy,

    Thanks for the suggestion.

    In my driver, I didn't access EFR2. So I think that might not be the root cause, but I will check the related code in 8250_omap to see if I can find something.

    I think we still have to figure out the hardware behavior, then I can decide how to handle the RX timeout interrupt on TDA4VM.

  • Hi Hunkli,

    One more thing to check would be to dump the IER register content after you disable the RHR_IT
    & when you get the interrupt second time to check if the something else is re-enabling it in the background.

    - Keerthy

  • Hi Keerthy,

    I debugged for the IER. In my ISR, I set IER to 0x0 to disable all INTs when the first RX timeout interrupt happened. When the second time RX timeout interrupt come, the IER is still 0x0. There is no background task will re-enable it.

  • Hi Hunkli,

    We tried to replicate your use case with some hacks for mcu UART on AM654-evm as we do
    not have TDA4VM handy at the moment. AM654/TDMA4VM/AM57 all of them have the same UART IP.

    We disabled the RHR_IT as soon as we got the first interrupt. We do not clear the FIFO in the ISR
    and we get a flood of interrupts because of that so disabling RHR_IT at the beginning of ISR and retruning
    it and trying to clear FIFO later will not really disable the timeout condition and we keep getting interrupts.

    So i am not sure how AM57xx is working for you. Could you share your code? Ideally it is not supposed to work
    on am57xx as well as per our theory. We will want to look at your use case code.

    Thanks,
    Keerthy

  • Hi Keerthy,

    Sorry, I can't provide the source code, but I used the same driver for TDA4VM and AM572x IDK, disabling RX timeout interrupt and waking up another task in ISR. The task will read char in FIFO by polling LSR and re-enable RX timeout interrupt when FIFO is empty. Maybe AM572x UART IP has different hardware design against TDA4VM, and its datasheet indeed said that RHR_IT can "Disables the RHR interrupt and time-out interrupt" as well(Literature Number: SPRUHZ6D). Or maybe my driver has some issue.

    However, if it is possible, could you please help to confirm the detail behavior of RHR_IT on these boards(AM572x IDK, AM654 EVM and TDA4VM) with your chip design team? If I know the hardware behavior of disabling RX timeout interrupt, I think I can figure out why this happened and how to do. 

    Thank you.

  • Hi Hunkli,

    I am trying to get in touch with UART Hardware expert. While i do that could you try to disable
    the IRQ at GIC level?

    https://elixir.bootlin.com/linux/latest/source/kernel/irq/manage.c#L566

    disable_irq(uart_irq_number);

    Do the above the first time you receive interrupt and then re-enable once you drain the FIFO in the work function?

    Can you try that as a workaround?

    - Keerthy

  • Hi Keerthy,

    If I disable the UART interrupt in GIC when the first rx timeout int coming, there will not be any UART interrupt before re-enable the UART GIC interrupt in the FIFO read task. It seems this could be a workaround, but I'm not sure about the side effect of disabling all UART interrupts during RX FIFO read.

  • Hi Hunkli,

    The impact will be that you will not get any type of UART interrupts from that particular instance that you are trying to disable.
    You can do a enable call once you drain out the FIFO. Let me know if your use case is working fine with the suggested work around.

    - Keerthy

  • Hi Keerthy,

    After basic test, this could be a workable workaround for my system. But as I also used THR interrupt to handle TX, I need more tests when both RX & TX work together. In theory the response of TX interrupt may be delay due to the UART interrupt is disabled. I will discuss with my colleagues soon.

    In addition, please let me know also when you get the detail RHR_IT behavior of these boards(TDA4, AM65x, AM572x) from hardware team. Then I have enough reason to explain why I have to use this workaround. 

    Thanks a lot.

  • Hi Hunkli,

    We consulted the UART IP expert. We found one difference w.r.t UART IP on AM57XX and TDA4VM:

    AM572x TRM: http://www.ti.com/lit/ug/spruhz6l/spruhz6l.pdf
    There is no EFR2 register in AM572x.

    TDA4VM TRM: http://www.ti.com/lit/ug/spruil1a/spruil1a.pdf
    We do have EFR2 register.

    AM572x uses UART IP that did not have the EFR2 register, thus did not have the TIMEOUT_BEHAVE functionality.

    Where as on TDA4VM the UART trx timeout is dependent on the Bit 6 of EFR2 register: TIMEOUT_BEHAVE bit.

    12.1.6.6.57 UART_EFR2 Register (Offset = 8Ch) [reset = 0h]
    UART_EFR2 is shown in Figure 12-476 and described in Table 12-1242

    12.1.6.4.8.1.3.10 Time-Out Counter
    An RX idle condition is detected when the receiver line (RX) is high for a time that equals 4x the
    programmed word length + 12 bits or manually configured amount of baud clocks, if a value other zero is
    set in the timeout register. RX is sampled midway through each bit.
    For sleep mode, the counter is reset when there is activity on RX.


    There are two modes of operation:
    • In default operation on the UART_EFR2[6] TIMEOUT_BEHAVE is set to 0. For the time-out interrupt,
    the counter counts only when there is data in the RX FIFO, and the count is reset when there is activity
    on RX or when the UART_RHR register is read.

    • Optionally, for choose to enable the timeout counter even if no character has been received by setting
    UART_EFR2[6] TIMEOUT_BEHAVE bit. This will generate periodic interrupts if the RX line remains
    idle. In this mode the counter will auto-reset when a timeout has been reached. Reading the
    UART_IIR_UART will clear the interrupt, but not the counter.

    There is no such feature on AM57XX. The above is the potential difference. I hope that is the explanation
    you were looking for. We will be doing more experiments on this. Let me know if you have more questions.
    Or else you could resolve the issue.

    Regards,
    Keerthy
     

  • Hi Keerthy,

    "• In default operation on the UART_EFR2[6] TIMEOUT_BEHAVE is set to 0. For the time-out interrupt,
    the counter counts only when there is data in the RX FIFO, and the count is reset when there is activity
    on RX or when the UART_RHR register is read.", so this means that on TDA4/AM65X the RX timeout interrupt can only be cleared by reading UART_RHR rather than clearing RHR_IT bit.

    But on AM572X, it doesn't have the TIMEOUT_BEHAVE functionality, so the RX timeout interrupt can be cleared by clearing RHR_IT bit.

    Do I understand correctly?

  • Hi Hunkli,

    That is very correct. One last work around that UART expert proposed One workaround to clear the interrupt without draining RHR might be to

    Disable the interrupt RHR_IT=0

    Set TIMEOUT_BEHAVE=1 in EFR2 and then drain rx fifo to clear interrupt

    Set TIMEOUT_BEHAVE back to 0

    Then enable the interrupt RHR_IT=1

    This is untested and may not result in the desired behavior.

    As far as the hardware difference understanding goes it is very correct in what you summarized above.

    Hope you can resolve the issue.

    - Keerthy


  • Hi Keerthy,

    The hardware question was clarified well, thanks for your help.