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.

RTOS/TM4C129ENCPDT: Half duplex UART driver - EOT interrupt not working

Part Number: TM4C129ENCPDT

Tool/software: TI-RTOS

Dear Experts,

I'm working on a UARTTiva adaption, which supports half duplex operation (intended for a master implementation of a proprietary bus). I don't use DMA, but the interrupt driven approach UARTTiva.

Even though I unmasked the EOT bit in the UART Interrupt Mask by following code

#define UART_INT_EOT        0x800       // End of Transmission Interrupt Mask

        /* enable end of transmission interrupt */
        UARTIntClear(hwAttrs->baseAddr, UART_INT_EOT);
        UARTIntEnable(hwAttrs->baseAddr, UART_INT_EOT);

I do not get an interrupt, when the last bit gets transmitted. The debug register view shows the interrupt to be unmasked. Neither in UART Raw Interrupt Status nor in UART Masked Interrupt Status I see the EOT bit set, when an interrupt occurs (always only TXRIS or TXMIS respectively)

After setting the EOT bit in the UART Control (UARTCTL) register by the following code

    UARTDisable(hwAttrs->baseAddr);
    HWREG((hwAttrs->baseAddr) + UART_O_CTL) |= (UART_CTL_EOT);
    UARTEnable(hwAttrs->baseAddr);

the busy flag is always cleared when the interrupt occurs (TXMIS) as expected, but the EOTRIS is still always cleared.

Is the device really supporting an EOT interrupt as described in the Tiva™ TM4C129ENCPDT Microcontroller
DATA SHEET for EOTRIS (p. 1323)?

  • Hi,
    Please try the UARTTxIntModeSet() API with UART_TXINT_MODE_EOT to enable End of Transmission.

    30.2.2.47 UARTTxIntModeSet
    Sets the operating mode for the UART transmit interrupt.
    Prototype:
    void
    UARTTxIntModeSet(uint32_t ui32Base,
    uint32_t ui32Mode)
    Parameters:
    ui32Base is the base address of the UART port.
    ui32Mode is the operating mode for the transmit interrupt. It may be
    UART_TXINT_MODE_EOT to trigger interrupts when the transmitter is idle or
    UART_TXINT_MODE_FIFO to trigger based on the current transmit FIFO level.
    Description:
    This function allows the mode of the UART transmit interrupt to be set. By default,
    the transmit interrupt is asserted when the FIFO level falls past a threshold set via a
    call to UARTFIFOLevelSet(). Alternatively, if this function is called with ui32Mode set to
    UART_TXINT_MODE_EOT, the transmit interrupt is asserted once the transmitter is completely
    idle - the transmit FIFO is empty and all bits, including any stop bits, have cleared the
    transmitter.
    Note:
    The availability of end-of-transmission mode varies with the Tiva part in use. Please consult
    the datasheet for the part you are using to determine whether this support is available.
    Returns:
    None.
  • Hello Charles,

    thank you for the helpful information, I really missed this function.

    Nevertheless it is not exactly what I want to have, because now the uart runs empty within long telegrams due to interrupt latency. (This is maybe acceptable for my usecase.)

    I'm looking for a real EOT interrupt, thus the fifo reloading can be done by the TX interrupt in time while the EOT interrupt changes the pin direction of the TX pin to input to get high impedance. According to the data sheet the EOTIM bit should enable this interrupt type "1 An interrupt is sent to the interrupt controller when the EOTRIS bit in the UARTRIS register is set.", but the EOTRIS bit seems never to be set ...

    Am I missing anything? Is there a defect of the device or the documentation?

    The data sheet is not very clear, because the EOT interrupt is not listed in chapter "19.3.9 Interrupts", but in chapter "19.3.11 DMA Operation": "To indicate transfer completion from the UART's serializer, the end-of-transmission bit (EOT bit) should be enabled in the UARTCTL register. An interrupt can be generated on an end-of-transmission completion by setting the EOTIM bit of the UARTIM register."

    Does the EOT interrupt only work with DMA and EOT bit set in the UARTCTL register? Could you explain under which conditions the EOTRIS bit is set? (The data sheet description "The last bit of all transmitted data and flags has left the serializer." seems not to be complete.)

  •  Hi Sven,

     Please find below excerpt from the interrupt section.

  • Sorry, my last reply got sent out before I finished.
  • Hi,

    I'm looking for a real EOT interrupt, thus the fifo reloading can be done by the TX interrupt in time while the EOT interrupt changes the pin direction of the TX pin to input to get high impedance. According to the data sheet the EOTIM bit should enable this interrupt type "1 An interrupt is sent to the interrupt controller when the EOTRIS bit in the UARTRIS register is set.", but the EOTRIS bit seems never to be set ...

    [CT] Are you able to see any interrupt if you enable the EOT? If you place the breakpoint in the UART ISR will the CPU halt there? If the answer is yes, then an EOT interrupt is generated. If the EOTRIS was never set to begin with then you will never get an interrupt no matter what the EOTIM bit is.

    Does the EOT interrupt only work with DMA and EOT bit set in the UARTCTL register? Could you explain under which conditions the EOTRIS bit is set? (The data sheet description "The last bit of all transmitted data and flags has left the serializer." seems not to be complete.)

    [CT] The EOT is independent of DMA mode or not.
  • Charles Tsai said:

    [CT] Are you able to see any interrupt if you enable the EOT? If you place the breakpoint in the UART ISR will the CPU halt there? If the answer is yes, then an EOT interrupt is generated. If the EOTRIS was never set to begin with then you will never get an interrupt no matter what the EOTIM bit is.

    Hello Charles,

    thank you for clarification and answering my questions.

    I do not exactly understand what you mean by "if you enable the EOT":

    If I enable the EOT bit in the UART Control (UARTCTL) register and unmask the EOT by setting the EOTIM bit to 1, I get an interrupt, the CPU halts at a breakpoint in the UART ISR.

    I use the following code:

    static void UARTTivaHD_hwiIntFxn(UArg arg)
    {
        uint32_t                   status;
        UARTTivaHD_Object           *object = ((UART_Handle)arg)->object;
        UARTTivaHD_HWAttrs const    *hwAttrs = ((UART_Handle)arg)->hwAttrs;
        uint32_t                   rxErrors;
    
        /* Clear interrupts */
        status = UARTIntStatus(hwAttrs->baseAddr, true);
    UARTIntClear(hwAttrs->baseAddr, status); // breakpoint here Log_print3(Diags_USER1, "UART HW Intr: Status %d, %d bytes to write, IsBusy=%d", status, object->writeCount, UARTBusy(hwAttrs->baseAddr)); // ... }

    The status returned by UARTIntStatus is always 32dec, thus the TX interrupt, never 2048dec. UARTBusy is always false.
    This works as expected and is no longer our topic.

    If I only unmask the EOT by setting the EOTIM bit to 1 (keeping the UART_TXINT_MODE_FIFO) I only see an interrupt, if the telegram is longer than the fifo space, thus the UARTTivaHD_write function enables the TX interrupt. This interrupt is always 32dec. The EOTRIS bit in the register view was always cleared.
    If the telegram is short no interrupt occurs at all.

    What do you mean by "If the EOTRIS was never set to begin with": Set by the processor or do I have to set it somehow?

    If you want to have a deeper look into the code, see the following zip file of the project:

    uartconsole_EK_TM4C129EXL_TI.zip

    Maybe you could provide a small example code with working EOT interrupt? I could check my hardware with it.

  • Hi,

    SProbst said:
    I do not exactly understand what you mean by "if you enable the EOT":

      I meant did you call UARTTxIntModeSet() with UART_TXINT_MODE_EOT? By calling UARTTxIntModeSet(), it will set bit 4 (EOT bit) in the UARTCTL register to enable end of transmission for TX interrupt. Note there are two ways to cause a TX interrupt, one is by reaching the programmable TX FIFO level or when FIFO is empty and all bits are transmitted.

     If you had already called  UARTTxIntModeSet() with UART_TXINT_MODE_EOT and still does not see EOTRIS getting set then perhaps there is a reason for it. Note the description for bit 4 (EOT) in the UARTCTL register shown below. By setting bit 4 it will determine the behavior of the 'TXRIS' bit. When TXRIS bit is set, it can mean either the FIFO has reached the specified FIFO level or the FIFO is empty and all bits have left the serializer. If you had called UARTTxIntModeSet() with UART_TXINT_MODE_EOT and only see TXRIS bit set but not EOTRIS bit then this is probably what happens. With the TXRIS bit set, it indirectly indicates the End of Transmission has just happened. You might ask why don't both the TXRIS and EOTRIS set at the same time? That is a question I need to investigate if that is truly the case. But I need to first ask you if you had set UART_TXINT_MODE_EOT  in the UARTCTL register. 

     

  • Hello Charles,
    "But I need to first ask you if you had set UART_TXINT_MODE_EOT in the UARTCTL register. "
    In the first test case: yes
    In the second test case: no.
    Please see my post above.

    I understand the data sheet somewhat different:
    UART_TXINT_MODE_EOT set ==> TXRIS ONLY after last bit sent
    UART_TXINT_MODE_EOT cleared ==> TXRIS ONLY when passing fifo level

    This fits also better to my investigation, that the busy flag is always cleared if UART_TXINT_MODE_EOT set.
    Could you investigate things?
  • Hi Sven,

      

    SProbst said:
    understand the data sheet somewhat different:
    UART_TXINT_MODE_EOT set ==> TXRIS ONLY after last bit sent
    UART_TXINT_MODE_EOT cleared ==> TXRIS ONLY when passing fifo level

      Your understanding is correct.

    SProbst said:
    that the busy flag is always cleared if UART_TXINT_MODE_EOT set.

    When do you read the busy flag? In the ISR? If you had set UART_TXINT_MODE_EOT then EOT is generated when all bits are transmitted out and the FIFO is empty by which time the transmitter has become idle. If the transmitter is in idle then the flag is clear. 

    Sorry I have gone home without the PC. I will read your code tomorrow. 

     

  • Hi Charles,

    yes, I read the busy flag inside the ISR, thus I agree with you, that it is expected to be cleared.

    I want to use UART_TXINT_MODE_FIFO (such that the fifo does not run empty inside a telegram), but would still expect an EOT interrupt after the last bit left the processor.

    Is this possible?

  • Hi Sven,
    Unfortunately, they are mutually exclusive. If you select UART_TXINT_MODE_FIFO then when the TX FIFO falls below the programmable threshold the interrupt is generated while the shift register is in the middle shifting out the serial data. Note that the EOT also means the FIFO must be empty too. It is not just after all bits are shifted per frame.
  • Hello Charles,
    I agree that in UART_TXINT_MODE_FIFO the interrupt due to TXRIS will only occur when the fifo gets below the set threshold. But a second interrupt due to EOTRIS should occur when the last bit left the processor (and the fifo is empty, too). That is how I understand the datasheet description of the EOTRIS bit. What would be the use of this bit, if it gets never set?
    Could you try to contact a designer of the processor to get more information about the EOTRIS bit?
  • Hi Sven,

     Please refer to the below note where it says that if EOT is selected then the TXIFLSEL is ignored. 

  • Hello Charles,
    I don't understand your last post. I want to use the UART_TXINT_MODE_FIFO mode, thus the EOT bit in UARTCTL is CLEARED.
    My question is why I don't get an EOT interrupt. I couldn't find any hint in the data sheet, that the EOT bit in UARTCTL needs to be set for the EOT interrupt. Unmasking the EOTRIS should be sufficient.
  • Hi Sven,
    I agree that the datasheet is not very clear in this regard. The datasheet says that the EOT has the effect on the behavior of the TXRIS bit. Meaning that if the EOT is set then the TXRIS will be set after the FIFO is empty and the last bit is shifted out of the serializer. I think we agree on this. If you think about it, if TXRIS is already indicating the TX completion after the last bit is shifted, what is purpose of the EOTRIS bit? Don't they just duplicate the same status? With this doubt in mind, I wanted to see how it is described in the TM4C123 datasheet. Not to my surprise, the bit field where the EOTRIS is supposed to locate is marked as reserved. If you look at the UARTIntEnable() API there is not even a macro for UART_INT_EOT. You were trying to define this macro by yourself. I have some doubt if the EOTRIS will ever set in any conditions. With that much said, I will also talk to some experts tomorrow.
  • Hello Charles,
    any news about the EOTRIS issue?
  • Hi Sven,
    Sorry for the late reply. I talked to my colleague last week and he said his understanding is the same as the datasheet which is that the UART bit determines how the TXRIS bit is set. If UART bit of the UARTCTL register is set then the TXRIS bit is set after all bits are shifted out and the FIFO empty.

    I ran some code myself and I could not see the EOTRIS bit set at all, regardless with the UART bit set or not. This validates my reasoning in the last reply. When the TXRIS is set, it implies the end-of-transmission and there is no purpose to set EOTRIS which will indicate the same status. Neither will ROTRIS set in FIFO mode.
  • Hello Charles,

    thank you for reproducing my observations. To summarize the long post:

    EOTRIS is not working,

    neither in UART_TXINT_MODE_EOT (EOT bit in UARTCTL register set)

    nor in UART_TXINT_MODE_FIFO (EOT bit in UARTCTL register cleared).

    There is a good rationale for the missing EOTRIS in mode UART_TXINT_MODE_EOT (would be duplicate of TXRIS), but not in mode UART_TXINT_MODE_FIFO.

    If it is an defect / blur of the data sheet or an issue of the silicon could not be judged. Polling the UARTBusy flag (maybe in a timer interrupt) could be a workaround. If things work different with DMA seems questionable.