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.

AM2431: UART with FIFO : How to detect the end of transmission in interrupt

Part Number: AM2431
Other Parts Discussed in Thread: LP-AM243

Dear TI, 

What is the proper way to configure HW to detect end of transmission?
Once the data are transmitted we want to switch to receiving mode or do some other operations.
It is important that we do not switch sooner.

We are using UART FIFO to buffer data to offload the CPU during TX operation.
As soon as "Programmable FIFO threshold" level is hit and there are no more data to be put into UART_THR, the interrupt is disabled and transmission is done.
Starting at this point. Can we detect by interrupt "empty fifo buffer and shift register" to clearly indicate the time where all data are already transmitted?

UART_FCR: TX_FIFO_TRIG configuration do not seems to allow "0 spaces" option to be set.

0h = 8 spaces
1h = 16 spaces
2h = 32 spaces
3h = 56 spaces

It is unclean for me if it is even possible. 

...
p_serial_hw_hdl->p_params->readMode         = UART_TRANSFER_MODE_CALLBACK;
p_serial_hw_hdl->p_params->readReturnMode   = UART_READ_RETURN_MODE_PARTIAL;
p_serial_hw_hdl->p_params->writeMode        = UART_TRANSFER_MODE_CALLBACK;
p_serial_hw_hdl->p_params->readCallbackFxn  = mbp_ti_uart_irq_rx_callback;
p_serial_hw_hdl->p_params->writeCallbackFxn = mbp_ti_uart_irq_tx_callback;
...
p_serial_hw_hdl->p_params->hwFlowControlThr = UART_RXTRIGLVL_56; // greater than or equal to the RX FIFO trigger level
p_serial_hw_hdl->p_params->operMode         = UART_OPER_MODE_13X;
p_serial_hw_hdl->p_params->rxTrigLvl        = UART_RXTRIGLVL_56;
p_serial_hw_hdl->p_params->txTrigLvl        = UART_TXTRIGLVL_56;
...

Thank you.

Best regards,
ms

  • I have found probably the same issue with leads to conclusion that this feature is not supported. 
    https://e2e.ti.com/support/processors-group/processors/f/processors-forum/943209/am3358-ep-determine-end-of-uart-data-tx

    We will try to workaround this by loopbacking the data and setting the "Rx time-out".

  • Marek,

    It appears that the UART_intr2Enable() and UART_intr2Status() API's are what you can use to enable and detect a receive FIFO empty interrupt. For a complete list of UART API's refer to API's for UART.
     

    Also, look into the UART_IE2 Register. Please let me know if you are able to enable and detect an interrupt for empty fifo buffer and shift register using these API's 

    Regards,

    Erik

  • Erik,

    Thank you for hint. To minimize error i switched to LP and official demos and it was failure.

    I run the official demo "uart_echo_low_latency_interrupt_am243x-lp_r5fss0-0_nortos_ti-arm-clang" from SDK (C:\ti\mcu_plus_sdk_am243x_08_02_00_31) on LP-AM243.

    This demo has the necessary function calls and i thought even author intention was to block until done. But he failed as I'm failing. 

    Full code:

    static void App_uartUserISR(void *arg)
    {
        UART_AppPrms  *appPrms     = (UART_AppPrms *) arg;
        uint32_t       intrType;
    
        intrType = UART_getIntrIdentityStatus(appPrms->baseAddr);
    
        /* Check RX FIFO threshold is set */
        if((intrType & UART_INTID_RX_THRES_REACH) == UART_INTID_RX_THRES_REACH)
        {
            uint32_t       readSuccess;
            uint8_t       *readBuf, readChar;
    
            /* Read all data from RX FIFO */
            readBuf = (uint8_t *)appPrms->readBuf + appPrms->readCount;
            while(1)
            {
                readSuccess = UART_getChar(appPrms->baseAddr, &readChar);
                if(readSuccess == TRUE)
                {
                    if(appPrms->readCount >= APP_UART_BUFSIZE)
                    {
                        /* Rx buffer overflow */
                        appPrms->rxOverflow = TRUE;
                    }
                    else
                    {
                        /* Store data in buffer */
                        *readBuf = readChar;
                        readBuf++;
                        appPrms->readCount++;
                    }
                }
                else
                {
                    break;      /* No data left in FIFO */
                }
            }
    
            if(appPrms->rxOverflow == TRUE)
            {
                /* Stop processing further data */
                UART_intrDisable(appPrms->baseAddr, UART_INTR_RHR_CTI);
            }
        }
    
        /* Check TX FIFO threshold is set */
        if((intrType & UART_INTID_TX_THRES_REACH) == UART_INTID_TX_THRES_REACH)
        {
            uint32_t       numBytesToTransfer;
            const uint8_t *writeBuf;
    
            if(appPrms->writeSizeRemaining > 0U)
            {
                numBytesToTransfer = appPrms->writeSizeRemaining;
                if(numBytesToTransfer > appPrms->txTrigLvl)
                {
                    /* Write only threshold level of data */
                    numBytesToTransfer = appPrms->txTrigLvl;
                }
                appPrms->writeSizeRemaining -= numBytesToTransfer;
    
                /* Send characters upto FIFO threshold level or until done */
                writeBuf = appPrms->writeBuf + appPrms->writeCount;
                while(numBytesToTransfer != 0U)
                {
                    UART_putChar(appPrms->baseAddr, *writeBuf);
                    writeBuf++;
                    numBytesToTransfer--;
                    appPrms->writeCount++;
                }
    
                if(appPrms->writeSizeRemaining == 0U)
                {
                    /* Write complete  - disable TX interrupts */
                    appPrms->txDataSent = TRUE;
                    UART_intrDisable(appPrms->baseAddr, UART_INTR_THR);
                    UART_intr2Enable(appPrms->baseAddr, UART_INTR2_TX_EMPTY);
                }
            }
            else
            {
                /* Disable interrupt */
                UART_intrDisable(appPrms->baseAddr, UART_INTR_THR);
            }
        }
    
        /* Check if TX FIFO is empty */
        if(appPrms->txDataSent == TRUE)
        {
            intrType = UART_getIntr2Status(appPrms->baseAddr);
            if((intrType & UART_INTR2_TX_EMPTY) != 0U)
            {
                UART_intr2Disable(appPrms->baseAddr, UART_INTR2_TX_EMPTY);
                appPrms->txDataSent = FALSE;
    
                GPIO_pinWriteHigh(CONFIG_GPIO_PULSE_BASE_ADDR, CONFIG_GPIO_PULSE_PIN);
                GPIO_pinWriteHigh(CONFIG_GPIO_PULSE_BASE_ADDR, CONFIG_GPIO_PULSE_PIN);
                GPIO_pinWriteHigh(CONFIG_GPIO_PULSE_BASE_ADDR, CONFIG_GPIO_PULSE_PIN);
    
                SemaphoreP_post(&appPrms->writeDoneSem);
    
                GPIO_pinWriteLow(CONFIG_GPIO_PULSE_BASE_ADDR, CONFIG_GPIO_PULSE_PIN);
                GPIO_pinWriteLow(CONFIG_GPIO_PULSE_BASE_ADDR, CONFIG_GPIO_PULSE_PIN);
                GPIO_pinWriteLow(CONFIG_GPIO_PULSE_BASE_ADDR, CONFIG_GPIO_PULSE_PIN);
            }
        }
    
        return;
    }

    Here is the point we all hoped to do the magic:

        /* Check if TX FIFO is empty */
        if(appPrms->txDataSent == TRUE)
        {
            intrType = UART_getIntr2Status(appPrms->baseAddr);
            if((intrType & UART_INTR2_TX_EMPTY) != 0U)
            {
                UART_intr2Disable(appPrms->baseAddr, UART_INTR2_TX_EMPTY);
                appPrms->txDataSent = FALSE;
    
                GPIO_pinWriteHigh(CONFIG_GPIO_PULSE_BASE_ADDR, CONFIG_GPIO_PULSE_PIN);
    
                SemaphoreP_post(&appPrms->writeDoneSem);
    
                GPIO_pinWriteLow(CONFIG_GPIO_PULSE_BASE_ADDR, CONFIG_GPIO_PULSE_PIN);
            }
        }

    And this is what happened

    Best regards,

    ms

  • Hello Everyone,

    At the and we have used external loopback between RX and TX with combination with RX timeout. 

    Best regards,

    ms