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.

DRA787: Does the UART driver support DMA mode

Part Number: DRA787

We use ti-processor-sdk-rtos-automotive-dra7xx-evm-04.03.00.05.

We found UART_DMA_ENABLE in UART_v1.c, but not found UART_DMA_ENABLE in UART_soc.c.

When  call UART_read, can't read data.

Does the UART driver support DMA mode for DRA78x

  • I means does the UART driver support DMA mode?

  • Yes, UART driver supports DMA mode on both M4 and DSP.  Please take a look at UART_BasicExample_evmDRA78x_DMA_m4Testproject as a reference for setting up UART in DMA mode.

    Thanks,
    Stephen

  • Default mode is FIFO mode for UART_read?

    We found use UART_readPolling, can read data,

    And UART_read, the API not return, because not post readSem.

  • If not use DMA mode, the UART is FIFO mode?

  • Hi,

    You can get the default values for each UART instance in UART_soc.c for the device.  Defaults include:

    • Interrupt mode
    • No DMA mode
    • Rx FIFO trigger level - 8 characters
    • Tx FIFO trigger level - 56

    These defaults can all be modified through calls to UART_socGetInitCfg and UART_socSetInitCfg and by specifying the desired options for UART_Params when calling UART_open.

    -Stephen

  • When no DMA mode, we config IRQ as follow, then can read data, but lost data sometimes.

    CSL_xbarIrqConfigure(CSL_XBAR_IRQ_CPU_ID_IPU1, CSL_XBAR_INST_IPU1_IRQ_43, CSL_XBAR_UART2_IRQ);

    So we want to use DMA mode.

    How to config IRQ?  Which dmaCrossbarInputNo is match CSL_XBAR_DMA_UART2_DREQ_RX? 

    void CSL_xbarDmaConfigure(CSL_XbarDmaCpuId dmaRegType, Uint32 dmaCrossbarInputNo, Uint32 dmaDreqToMapTo)

  • By default, UART Rx and Tx events 51 and 52 are already routed through the DMA XBAR to output request lines 50 and 51, respectively.  See Table 11-7 from section 11.3.1 of the TRM:

    Can you try the following:

    • Call UART_socGetInitCfg to retrieve UART_HwAttrs 
    • Sett txDmaEventNumber and rxDmaEventNumber to CSL_EDMA3_CHA_UART1_TX (50U) and CSL_EDMA3_CHA_UART1_RX (51U), respectively
      • It is intentional that we use UART1 here because CSL numbering uses 0-indexing while TRM uses 1-indexing (sorry for confusion here)
    • UART_socSetInitCfg to set the DMA event numbers.

    Of course, you can change the DMA XBAR routing if you desire to move from the defaults.  UART_HwAttrs will need to be updated for this as well.

    Let me know if this works for you.

    -Stephen

  • Hi Stephen

    Thank you, now can read data in DMA mode, But the data is not correct.

    Recv from other MCU, the excepted data is 0x78 56 34 12 00 00 00 00 01 00 00 00 for 3 uint32 value.

    thus the 3 values is 0x12345678 0x0 0x1.

    But now, the 3 value is 0x12345678 0x9a9a0000 0x10000.

    It seems 0x9a9a is abnormally added. 

    Do you know why?

    And, when use vision sdk, the data is correct, but we must use pdk for our project.

  • dsp2mcu_uart.c
    /*
     * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * Redistributions of source code must retain the above copyright
     * notice, this list of conditions and the following disclaimer.
     *
     * Redistributions in binary form must reproduce the above copyright
     * notice, this list of conditions and the following disclaimer in the
     * documentation and/or other materials provided with the
     * distribution.
     *
     * Neither the name of Texas Instruments Incorporated nor the names of
     * its contributors may be used to endorse or promote products derived
     * from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    
    /**
     *  \file  uart_test.c
     *
     *  \brief  Example application main file. This application will demonstrate
     *          UART RTOS driver for interrupt mode.
     *   This file performs as mentioned below:
     *
     *      1. Configure UART using structure UART_Params where user can configure
     *         readmode writemode etc. different parameters.
     *      2. First call UART_init()
     *      3. Call UART_open with UART_Params structure to get UART instance handle.
     *      4. Then user is expected to input some data(can be upto max 1000 chars)
     *         and it is printed back on console using UART RTOS API's
     *         UART_read() and UART_write() respectively.
     *   Note
     *      1. The sample application is written for TDAXX EVM, DRA75X EVM and AM57XX.
     *      2. The UART instance used is UART1 for TDA2XX,AM57XX,DRA75X and
     *         UART3 for TDA3XX,DRA78X
     *
    **/
    
    /* ========================================================================== */
    /*                             Include Files                                  */
    /* ========================================================================== */
    /* XDCtools Header files */
    #include <xdc/std.h>
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/Error.h>
    #include <xdc/runtime/System.h>
    
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    
    #include "stdio.h"
    #include "stdint.h"
    #include "stdlib.h"
    #include "string.h"
    
    /* UART Header files */
    #include <ti/drv/uart/UART.h>
    #include <ti/drv/uart/src/UART_osal.h>
    #include <ti/drv/uart/soc/UART_soc.h>
    #include <ti/csl/hw_types.h>
    #include <ti/csl/soc.h>
    #include "protocol/dsp2mcu.h"
    
    #define UART_DMA_MODE
    #ifdef UART_DMA_MODE
    #include <ti/sdo/edma3/drv/edma3_drv.h>
    #include <ti/sdo/edma3/rm/edma3_rm.h>
    #include <ti/sdo/edma3/rm/sample/bios6_edma3_rm_sample.h>
    
    static EDMA3_RM_Handle UartApp_edmaInit(void);
    
    extern EDMA3_RM_InstanceInitConfig sampleInstInitConfig[][EDMA3_MAX_REGIONS];
    extern EDMA3_RM_GblConfigParams sampleEdma3GblCfgParams[];
    #endif
    
    #if 1
    #pragma DATA_ALIGN (buffPointer, 128)
    char buffPointer[1024];
    #else
    char buffPointer[1024] __attribute__ ((aligned (128)));
    #endif
    
    
    /* ========================================================================== */
    /*                           Macros & Typedefs                                */
    /* ========================================================================== */
    #define UART_INSTANCE 1
    
    /* ========================================================================== */
    /*                          Internal Function Declarations                    */
    /* ========================================================================== */
    /* None */
    
    /* ========================================================================== */
    /*                            Global Variables                                */
    /* ========================================================================== */
    UART_Handle uart_handle;
    
    /* UART parameters structure polled mode*/
    const UART_Params user_params = {
        UART_MODE_BLOCKING,     /* readMode */
        UART_MODE_BLOCKING,     /* writeMode */
        SemaphoreP_WAIT_FOREVER,                     /* readTimeout */
        SemaphoreP_WAIT_FOREVER,                     /* writeTimeout */
        NULL,                  /* readCallback */
        NULL,                 /* writeCallback */
        UART_RETURN_FULL,  /* readReturnMode */
        UART_DATA_BINARY,       /* readDataMode */
        UART_DATA_BINARY,       /* writeDataMode */
        UART_ECHO_OFF,         /* readEcho */
        460800,               /* baudRate */
        UART_LEN_8,           /* dataLength */
        UART_STOP_ONE,        /* stopBits */
        UART_PAR_NONE,         /* parityType */
    	NULL,				   /* readCallback2 */
    	NULL				  /* writeCallback2 */
    };
    
    /* ========================================================================== */
    /*                          Function Definitions                              */
    /* ========================================================================== */
    extern UInt32 ParseRxHead(UInt32* pHeader);
    
    void UART2PadConfig()
    {
    	HW_WR_REG32(SOC_CORE_PAD_IO_REGISTERS_BASE+CTRL_CORE_PAD_IO_UART2_RXD,0x00040000);
        HW_WR_REG32(SOC_CORE_PAD_IO_REGISTERS_BASE+CTRL_CORE_PAD_IO_UART2_TXD,0x00000000);
        //HW_WR_REG32(SOC_CORE_PAD_IO_REGISTERS_BASE+CTRL_CORE_PAD_IO_UART2_CTSN,0x00060000);
        //HW_WR_REG32(SOC_CORE_PAD_IO_REGISTERS_BASE+CTRL_CORE_PAD_IO_UART2_RTSN,0x00060000);
    	
    	CSL_xbarIrqConfigure(CSL_XBAR_IRQ_CPU_ID_IPU1, CSL_XBAR_INST_IPU1_IRQ_43, CSL_XBAR_UART2_IRQ);
    }
    
    EDMA3_RM_Handle gEdmaHandle = NULL;
    
    static EDMA3_RM_Handle UartApp_edmaInit(void)
    {
        EDMA3_DRV_Result edmaResult = EDMA3_DRV_E_INVALID_PARAM;
        uint32_t edma3Id;
    
        if (gEdmaHandle != NULL)
        {
            return(gEdmaHandle);
        }
    
        edma3Id = 0;
        gEdmaHandle = (EDMA3_RM_Handle)edma3init(edma3Id, &edmaResult);
        if (edmaResult != EDMA3_DRV_SOK)
        {
            /* Report EDMA Error */
            System_printf("\nEDMA driver initialization FAIL\n");
        }
        else
        {
            System_printf("\nEDMA driver initialization PASS.\n");
        }
        return(gEdmaHandle);
    }
    
    static void UART_initConfig(bool dmaMode)
    {
        UART_HwAttrs uart_cfg;
    
        /* Get the default UART init configurations */
        UART_socGetInitCfg(UART_INSTANCE, &uart_cfg);
        {
            uart_cfg.edmaHandle = UartApp_edmaInit();
            uart_cfg.dmaMode    = true;
    		uart_cfg.txDmaEventNumber = 50;
    		uart_cfg.rxDmaEventNumber = 51;
        }
    
        UART_socSetInitCfg(UART_INSTANCE, &uart_cfg);
    }
    
    void EcarxDSP2MCUUartComm_Task(UArg arg0, UArg arg1)
    {
        UART_Params      params;
        int32_t count;
    	int32_t fori;
    
        UART2PadConfig();
    
        UART_init();
    #ifdef UART_DMA_MODE
    	UART_initConfig(true);
    #endif
        params = user_params;
        uart_handle = UART_open(UART_INSTANCE, &params);
    
    	ecarx_GPIO_init();
    	DSPInited();
    
        while(1)
        {  
    #ifdef UART_DMA_MODE
    		//CacheP_wbInv((void*)buffPointer, 4, (unsigned short)Cache_Type_ALL, true);
    		CacheP_wbInv((void*)buffPointer, 4);//, (unsigned short)Cache_Type_ALL, true);
    #endif
            count = UART_read(uart_handle,buffPointer,4);
    
    		if(count == 4)
    		{
    			ParseRxHead((UInt32*)buffPointer);
    		}
        }
    }
    
    void EcarxDSP2MCUUartComm_SendBuf(UInt8* pBuf, UInt32 pLen)
    {
    	UART_write(uart_handle,pBuf,pLen);
    }
    
    void EcarxDSP2MCUUartComm_RecvBuf(UInt8* pBuf, UInt32 pLen)
    {
    #ifdef UART_DMA_MODE
    	//CacheP_wbInv((void *)pBuf, pLen, (unsigned short)Cache_Type_ALL, true);
    	CacheP_wbInv((void *)pBuf, pLen);//, (unsigned short)Cache_Type_ALL, true);
    #endif
    	UART_read(uart_handle,pBuf,pLen);
    }
    
    
    int EcarxDSP2MCUUartCommInit(void)
    {
        Task_Handle task;
        Error_Block eb;
    	Task_Params taskParams;
    
        Error_init(&eb);
    
    	Task_Params_init (&taskParams);
    	taskParams.instance->name = "DSP2MCU_Comm_uart";
    	taskParams.arg0 = (UArg) NULL;
    	taskParams.arg1 = (UArg) NULL;
    	taskParams.stackSize = 0x4000;
    	taskParams.priority = 1;
    
    	task = Task_create (EcarxDSP2MCUUartComm_Task, &taskParams, &eb);
    
        if (task == NULL) {
            printf("EcarxStartDSP2MCUUartComm create failed!\n");
        }
    	else
    	{
            printf("EcarxStartDSP2MCUUartComm create success!\n");
    	}
        return (0);
    }
    /********************************* End of file ******************************/
    

  • please help to view the code.

  • Another issue, when not use DMA mode.

    When read data, 0xff is discarded in UART_v1_readData(UART_Handle handle, int32_t size), how to fix the issue?

    while ((size != (int32_t)(0)) && (readIn != (-((int32_t)1))))

    {
    /* If data mode is set to TEXT replace return with a newline. */
    if (object->params.readDataMode == UART_DATA_TEXT)
    {
    if ((uint8_t)readIn == ((uint8_t)('\r')))
    {
    /* Echo character if enabled. */
    if (object->params.readEcho)
    {
    UARTCharPut(hwAttrs->baseAddr, ((uint8_t)('\r')));
    }
    readIn = (int32_t)'\n';
    }
    }

    UART_drv_log2("UART:(0x%x) Read character 0x%x",
    hwAttrs->baseAddr, (uint8_t)readIn);

    *(uint8_t *)object->readBuf = (uint8_t)readIn;
    object->readBuf = (uint8_t *)object->readBuf + 1;    //when data is 0xff, not run here
    object->readCount++;
    size--;

  • Hi,

    Regarding the previous issue, I have not seen this before.  The code snippet you provided looks good for the most part, though the one suspicious change is baud rate set to 460800.  Note that for baud rates above 3.6 Mbps you must switch functional clock to 192MHz (default setting is 48 MHz).  Can you confirm this change on your end?

    On the new issue you bring up, this is known.  It had been fixed later after this SDK was released, so please pick up patches.  There is one for CSL and one for UART:

    Also, I suggest that for new issues you also create a new thread so that we don't go back and forth between issues in a thread and accidentally miss some details or response.

    Thanks,
    Stephen