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 Interrupt time consuming problem

Part Number: TDA4VM

Hi,we are testing uart driver and find out the UART Interrupt function: UART_v1_hwiIntFxn() will take more than 3.8us to process,so when we have amount of data coming in(eg:460800bps,9KB/sec of data), the system will not be real time, and this will make our application unuseable, we want to know why the uart ISR take so much time, and is there any solution for this?

alse we want to know how to enable uart rx fifo, we use UART_read(gUARTHandle,(void *)(uintptr_t)rxData,16); to read multiple bytes but found out it still enter ISR every single byte.

the second Chanel indicate how long it take to process the ISR using gpio write.

our test case

Regards,

JasonZhang

  • we set gpio to low when enter ISR,and set gpio to high when exit ISR,here is the code in pdk_jacinto_08_02_00_21/packages/ti/drv/uart/src/v1/UART_v1.c 

    static void UART_v1_hwiIntFxn(uintptr_t arg)
    {
        UART_Handle         handle = (UART_Handle)arg;
        UART_V1_Object     *object = (UART_V1_Object*)handle->object;
        UART_HwAttrs const *hwAttrs = (UART_HwAttrs const *)handle->hwAttrs;
        uint32_t            intType;
        uint8_t             rdData;
    
        while ((bool)true)
        {
            BSP_GPIO_WritePin(LED_FC_R_PORT,LED_FC_R_PIN,0);
    
            intType = UARTIntIdentityGet(hwAttrs->baseAddr);
    
            if ((intType & UART_INTID_RX_THRES_REACH) == UART_INTID_RX_THRES_REACH)
            {
                if ((intType & UART_INTID_RX_LINE_STAT_ERROR) ==
                    UART_INTID_RX_LINE_STAT_ERROR)
                {
                    /* RX line status error */
                    UART_procLineStatusErr(handle);
                }
                else
                {
                    if ((intType & UART_INTID_CHAR_TIMEOUT) == UART_INTID_CHAR_TIMEOUT)
                    {
                        /* rx timeout, log the rx timeout errors */
                        object->rxTimeoutCnt++;
                    }
    
                    /* RX FIFO threshold reached */
                    if (object->readSize > 0U)
                    {
                        object->readSize = (size_t)UART_v1_readData(handle, (int32_t)(object->readSize));
                        if ((object->readSize) == 0U)
                        {
                            UARTIntDisable(hwAttrs->baseAddr, UART_INT_RHR_CTI | UART_INT_LINE_STAT);
                            /* Reset the read buffer so we can pass it back */
                            object->readBuf = (uint8_t *)object->readBuf - object->readCount;
                            if (object->readTrans != NULL)
                            {
                                object->readTrans->count = (uint32_t)(object->readCount);
                                object->readTrans->status = UART_TRANSFER_STATUS_SUCCESS;
                            }
    
                            /* Call back to application if in callback mode */
                            UART_v1_callback(handle, (bool)true);
                            object->readTrans = NULL;
                        }
                    }
                    else
                    {
                        (void)UARTCharGetNonBlocking2(hwAttrs->baseAddr, &rdData);
                        UARTIntDisable(hwAttrs->baseAddr, UART_INT_RHR_CTI | UART_INT_LINE_STAT);
                    }
                }
            }
            else if ((intType & UART_INTID_TX_THRES_REACH) == UART_INTID_TX_THRES_REACH)
            {
                /* TX FIFO threshold reached */
                if (object->writeSize > 0U)
                {
                    object->writeSize = (size_t)UART_writeData_v1(handle, (int32_t)(object->writeSize));
                    if ((object->writeSize) == 0U)
                    {
                        UARTIntDisable(hwAttrs->baseAddr, UART_INT_THR);
                        /* Reset the write buffer so we can pass it back */
                        object->writeBuf = (const uint8_t *)object->writeBuf - object->writeCount;
    
                        if (object->writeTrans != NULL)
                        {
                            object->writeTrans->count = (uint32_t)(object->writeCount);
                            object->writeTrans->status = UART_TRANSFER_STATUS_SUCCESS;
                        }
    
                        object->txDataSent = TRUE;
                        UARTInt2Enable(hwAttrs->baseAddr, UART_INT2_TX_EMPTY);
                    }
                }
                else
                {
                    UARTIntDisable(hwAttrs->baseAddr, UART_INT_THR);
                }
            }
            else
            {
                break;
            }
        }
    
        if (object->txDataSent == TRUE)
        {
            intType = UARTInt2StatusGet(hwAttrs->baseAddr);
            if ((intType & UART_INT2_TX_EMPTY) != 0U)
            {
                UARTInt2Disable(hwAttrs->baseAddr, UART_INT2_TX_EMPTY);
    
                /* Call back to application if in callback mode */
                UART_v1_callback(handle, (bool)false);
                object->writeTrans = NULL;
                object->txDataSent = FALSE;
            }
        }
        BSP_GPIO_WritePin(LED_FC_R_PORT,LED_FC_R_PIN,1);
    }

    and our test code is:

    /*
     *  ======== UART init config ========
     */
    static void UART_initConfig(bool dmaMode)
    {
        UART_HwAttrs uart_cfg;
    
        /* Get the default UART init configurations */
        UART_socGetInitCfg(uartTestInstance, &uart_cfg);
    
        if (dmaMode == true)
        {
            uart_cfg.edmaHandle = UartApp_udmaInit(&uart_cfg);
            uart_cfg.dmaMode    = TRUE;
        }
        else
        {
            uart_cfg.edmaHandle = NULL;
            uart_cfg.dmaMode    = FALSE;
        }
        uart_cfg.rxTrigLvl = 8;
        /* Set the DMA enabled UART init configurations */
        UART_socSetInitCfg(uartTestInstance, &uart_cfg);
    }
    
    
    void uartsInit(void)
    {
        UART_Params      uartParams;
        UART_HwAttrs uart_cfg;
        UART_init();
        UART_initConfig(false);
    
        uartParams.baudRate = 460800;
        UART_Params_init(&uartParams);
        gUARTHandle = UART_open(uartTestInstance, &uartParams);
    }
    
    static void uartRxTest(void)
    {
        uint32_t i;
        uint32_t length;
        uint32_t realRxLen;
        while(1)
        {
            UART_read(gUARTHandle,(void *)(uintptr_t)rxData,16);
    
            Osal_delay(1);
        }
    }
    
    

  • Hello Jason,

    Here are some suggestions to your problems.

    For the time consuming problem of  UART_v1_hwiIntFxn(), the 3.8us includes both the time cost of the interrupt function itself and the time cost of your GPIO application. Normally, the GPIO application takes greater time cost. You may need to add a timer to record the time cost of GPIO application, then use 3.8us to minus the result to obtain the time cost of interrupt function. 

    As for the UART RX FIFO problem, I think you may need to add the interrupt enable coding: uart_cfg.enableInterrupt=1; /* Enabling interrupt forcefully */ in your UART_initConfig function. The position of this coding should be between UART_socGetInitCfg(uartTestInstance, &uart_cfg) and UART_socSetInitCfg(uartTestInstance, &uart_cfg). If we do not enable the interrupt, the interrupt will not be used to read from FIFO, and in this situation, the driver will directly read from the FIFO, one byte at a time. This might be the reason why it accesses ISR every single byte.

    Hope this will help.

    Kind Regards,

    Weilun