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.

LAUNCHXL-CC3235SF: UART DMA and UART2 driver

Part Number: LAUNCHXL-CC3235SF
Other Parts Discussed in Thread: CC3235SF, SYSCONFIG

Hi,

I'm testing UART with CC3235SF LaunchPad and CC32xx SDK 4.40.00.07.

I use both UART0 and UART1 with 921600 baud rate, and I try to bypass the data from UART1 to UART0(Data packet -> UART1 Rx -> UART0 Tx -> PC, final goal is from UART1 to Wi-Fi).

and the size of data packet is variable, but it is about 800 bytes on average and it is transmitted at 100ms intervals.

I modify the uartecho example for using Read callback mode and my code is work well.

1. 

But for using DMA, after enable the DMA in sysconfig tool, it occur the data loss on terminal program(tera term).

Source code isn't modified.

what am i doing wrong?

here is my code

/*
 * Copyright (c) 2015-2020, Texas Instruments Incorporated
 * All rights reserved.
 *
 * 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.
 */

/*
 *  ======== uartecho.c ========
 */
#include <stdint.h>
#include <stddef.h>

/* Driver Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/UART.h>

/* Driver configuration */
#include "ti_drivers_config.h"

/* Ringbuffer */
#include "rb.h"

UART_Handle uart0, uart1;
RingFifo_t UART0Rx_Rb, UART1Rx_Rb;
uint8_t input;
uint32_t cbCount;

/*
 *  ======== UART RX Callback (HWI) ========
 */
void UART_RX_cb(UART_Handle handle, void *buf, size_t count)
{
    if(handle == uart0)
    {
        RB_write(&UART0Rx_Rb, ((uint8_t*)buf)[0]);
    }
    else if(handle == uart1)
    {
        RB_write(&UART1Rx_Rb, ((uint8_t*)buf)[0]);
    }
}
/*
 *  ======== mainThread ========
 */
void *mainThread(void *arg0)
{
    const char  echoPrompt[] = "Echoing characters from UART0:\r\n";
    const char  echoPrompt2[] = "Echoing characters from UART1:\r\n";

    UART_Params uartParams;
    uint8_t ch;

    /* Call driver init functions */
    GPIO_init();
    UART_init();

    /* Configure the LED pin */
    GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);

    RB_init(&UART0Rx_Rb, 128);
    RB_init(&UART1Rx_Rb, 4096);

    /* Create a UART with data processing off. */
    UART_Params_init(&uartParams);
    uartParams.writeDataMode = UART_DATA_BINARY;
    uartParams.readDataMode = UART_DATA_BINARY;
    uartParams.readReturnMode = UART_RETURN_FULL;
    uartParams.readEcho = UART_ECHO_OFF;
    uartParams.readMode = UART_MODE_CALLBACK;
    uartParams.readCallback = UART_RX_cb;
    uartParams.baudRate = 921600;

    uart0 = UART_open(CONFIG_UART_0, &uartParams);
    if (uart0 == NULL) {
        /* UART_open() failed */
        while (1);
    }

    uart1 = UART_open(CONFIG_UART_1, &uartParams);
    if (uart1 == NULL) {
        /* UART_open() failed */
        while (1);
    }

    /* remove uart receive from LPDS dependency */
//    UART_control(uart, UART_CMD_RXDISABLE, NULL);

    /* Turn on user LED to indicate successful initialization */
    GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON);

    UART_write(uart0, echoPrompt, sizeof(echoPrompt));
    UART_write(uart1, echoPrompt2, sizeof(echoPrompt2));

    UART_read(uart0, &input, 1);
    UART_read(uart1, &input, 1);

    /* Loop forever bypass */
    while (1) {
        if(!RB_isempty(&UART0Rx_Rb))
        {
            ch = RB_read(&UART0Rx_Rb);
            UART_write(uart1, &ch, 1);
            UART_read(uart0, &input, 1);
        }

        if(!RB_isempty(&UART1Rx_Rb))
        {
            ch = RB_read(&UART1Rx_Rb);
            UART_write(uart0, &ch, 1);
            UART_read(uart1, &input, 1);
        }
    }
}

2. 

I tried to open both UART0 and UART1 by referring to the uart2callback example to try the UART2 driver too.

But it is not work.

As a result to run debug in CCS, when process the UART_open function, it is trapped loop. (more detail, UART_open -> HwiP_construct -> Hwi_construct2 -> Hwi_construct)

here is my code

/*
 * Copyright (c) 2015-2020, Texas Instruments Incorporated
 * All rights reserved.
 *
 * 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.
 */

/*
 *  ======== uartecho.c ========
 */
#include <stdint.h>
#include <stddef.h>

/* Driver Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/UART2.h>

/* Driver configuration */
#include "ti_drivers_config.h"

/* Ringbuffer */
#include "rb.h"

UART2_Handle uart0, uart1;
RingFifo_t UART0Rx_Rb, UART1Rx_Rb;
uint8_t input;

/*
 *  ======== UART2 RX Callback (HWI) ========
 */
void UART2_RX_cb(UART2_Handle handle, void *buf, size_t count, void *userArg, int_fast16_t status)
{
    if (status != UART2_STATUS_SUCCESS) {
        /* RX error occured in UART2_read() */
        while (1);
    }

    if(handle == uart0)
    {
        RB_write(&UART0Rx_Rb, ((uint8_t*)buf)[0]);
        UART2_read(uart0, &input, 1, NULL);
    }
    else if(handle == uart1)
    {
        RB_write(&UART1Rx_Rb, ((uint8_t*)buf)[0]);
        UART2_read(uart1, &input, 1, NULL);
    }
}
/*
 *  ======== mainThread ========
 */
void *mainThread(void *arg0)
{
    const char  echoPrompt[] = "Echoing characters from UART0:\r\n";
    const char  echoPrompt2[] = "Echoing characters from UART1:\r\n";

    UART2_Params uartParams;
    uint32_t status = UART2_STATUS_SUCCESS;
    uint8_t ch;

    /* Call driver init functions */
    GPIO_init();
//    UART_init();

    /* Configure the LED pin */
    GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);

    RB_init(&UART0Rx_Rb, 256);
    RB_init(&UART1Rx_Rb, 4096);

    /* Create a UART with data processing off. */
    UART2_Params_init(&uartParams);
    uartParams.readMode = UART2_Mode_CALLBACK;
    uartParams.readCallback = UART2_RX_cb;
    uartParams.baudRate = 921600;

    uart0 = UART2_open(CONFIG_UART2_0, &uartParams);
    if (uart0 == NULL) {
        /* UART_open() failed */
        while (1);
    }

    uart1 = UART2_open(CONFIG_UART2_1, &uartParams);
    if (uart1 == NULL) {
        /* UART_open() failed */
        while (1);
    }

    /* remove uart receive from LPDS dependency */
//    UART_control(uart, UART_CMD_RXDISABLE, NULL);

    /* Turn on user LED to indicate successful initialization */
    GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON);

    UART2_write(uart0, echoPrompt, sizeof(echoPrompt), NULL);
    UART2_write(uart1, echoPrompt2, sizeof(echoPrompt2), NULL);

    status = UART2_read(uart0, &input, 1, NULL);
    if (status != UART2_STATUS_SUCCESS) {
        /* UART2_read() failed */
        while (1);
    }

    status = UART2_read(uart1, &input, 1, NULL);
    if (status != UART2_STATUS_SUCCESS) {
        /* UART2_read() failed */
        while (1);
    }

    /* Loop forever echoing */
    while (1) {
        if(!RB_isempty(&UART0Rx_Rb))
        {
            ch = RB_read(&UART0Rx_Rb);
            UART2_write(uart1, &ch, 1, NULL);
        }

        if(!RB_isempty(&UART1Rx_Rb))
        {
            ch = RB_read(&UART1Rx_Rb);
            UART2_write(uart0, &ch, 1, NULL);
        }
    }
}

Please help me out where I'm making mistake.

Thanks.

But for using DMA, after enable the DMA in sysconfig tool, it occur the data loss on terminal program(tera term). Eng



그러나 DMA를 사용하는 경우 sysconfig 도구에서 DMA를 활성화 한 후 터미널 프로그램 (테라 용어)에서 데이터 손실이 발생합니다.
  • Hi Jinhyeong Lee,

    1. Your screenshot shows that DMA is actually disabled. To enable DMA, the option box for "Use DMA" should have a checkmark. DMA is enabled by default in the uartecho example.
    2. Can you share a screenshot of how you are configuring your UART2 peripherals in the .syscfg file?

    Best regards,

    Sarah

  • Thank you for reply,

    1.I enabled and built the DAM checkmark before written this thread, and have experienced data loss.

    Also, DMA is disabled by default in uartecho example of SDK CC32xx 4.40.00.07. 

    2. Here is my UART2 peripherals in syscfg file.

  • Hi Jinhyeong Lee,

    How are you defining the read and write buffers? I'm also unsure what your RB_* APIs are meant to be doing here.

    Best regards,

    Sarah

  • It is a simple ring buffer to store UART data. Implementation is below.

    unsigned char 
    RB_init(RingFifo_t * ptRB, unsigned short size)
    {
      
        if(size & (size-1))
          return 1;
        
    		ptRB->size = size;
    		ptRB->wrIdx= 0;
    		ptRB->rdIdx= 0;
    		ptRB->data = malloc(size);
        
        assert(ptRB->data);
        
    		return 0;		
    }
    
    void
    RB_write(RingFifo_t * ptRB, unsigned char data)
    {
      if(RB_isfull(ptRB))
        return;
        
    	ptRB->data[ptRB->wrIdx] = data;
    	ptRB->wrIdx = (ptRB->size-1) & (ptRB->wrIdx+1);	
    }
    
    unsigned char
    RB_read(RingFifo_t * ptRB)
    {
    
    	unsigned char val = ptRB->data[ptRB->rdIdx];
    	ptRB->rdIdx = (ptRB->size-1) & (ptRB->rdIdx+1);	
    	
    	return val;
    }

  • Hi Jinhyeong Lee,

    Are you trying to read and write directly to yourself on the same MCU?

    Best regards,

    Sarah

  • Yes, read data from UART1, then write the data to UART0 on the same MCU. (UART1 to UART0 data bypass)

  • Hi Jinhyeong Lee,

    May I ask what is the application for this?

    Can you send and receive data to a serial terminal without losing data? If so, then it seems the drivers should be working as expected.

    Best regards,

    Sarah

  • My application is to send/receive without data loss at 921600bps using 2 UARTs.

    I implemented the bypass code in Read Callback mode using UART driver(not used DMA), and it worked well.

    However, data loss occurs when DMA is enabled(by selecting the DMA checkmark in syscfg) and executed.

    I understood that the UART driver API usage method is the same regardless of whether DMA is used or not, but data loss occurred.

    And apart from the above, I used the UART2 driver, but my code was blocked in UART2 open.

    My questions are below.

    1. Why does activating the DMA cause data loss?

    2. How can I use 2 UARTs (uart0 and uart1) using UART2 driver?

    Thanks.

  • Hi Jinhyeong Lee,

    My colleague put together this demo based on the uartecho example running both UARTs to external terminals at the max baud rate, and he did not see any data loss. Can you try this example to verify the drivers?

    3365.uartecho2.c
    /*
     * Copyright (c) 2015-2019, Texas Instruments Incorporated
     * All rights reserved.
     *
     * 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.
     */
    
    /*
     *  ======== uartecho.c ========
     */
    #include <stdint.h>
    #include <stddef.h>
    #include <unistd.h>
    #include <string.h>
    
    /* Driver Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/UART.h>
    
    /* Driver configuration */
    #include "ti_drivers_config.h"
    #include "uart_term.h"
    
    /*
     *  ======== mainThread ========
     */
    void *mainThread(void *arg0)
    {
        const char  echoPrompt[] = "Echoing characters to UART1:\r\n";
        const char  echoPrompt1[] = "Echoing characters to UART0:\r\n";
        UART_Handle uart0;
        UART_Params uart0Params;
        UART_Handle uart1;
        UART_Params uart1Params;
        char cmnd_in[80], bbff[80];
        int i;
    
        /* Call driver init functions */
        GPIO_init();
        UART_init();
    
        /* Configure the LED pin */
        GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    
        /* Turn on user LED */
        GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON);
    
        /* Create a UART with data processing off. */
        UART_Params_init(&uart0Params);
        uart0Params.writeDataMode = UART_DATA_BINARY;
        uart0Params.readDataMode = UART_DATA_BINARY;
        uart0Params.readReturnMode = UART_RETURN_FULL;
        uart0Params.readEcho = UART_ECHO_OFF;
       // uart0Params.baudRate = 115200;
        uart0Params.baudRate = 3000000;
    
        uart0 = UART_open(CONFIG_UART_0, &uart0Params);
    
        if (uart0 == NULL) {
            /* UART_open() failed */
            while (1);
        }
    
        /* Create a UART with data processing off. */
        UART_Params_init(&uart1Params);
        uart1Params.writeDataMode = UART_DATA_BINARY;
        uart1Params.readDataMode = UART_DATA_BINARY;
        uart1Params.readReturnMode = UART_RETURN_FULL;
        uart1Params.readEcho = UART_ECHO_OFF;
     //   uart1Params.baudRate = 115200;
        uart1Params.baudRate = 3000000;
    
        uart1= UART_open(CONFIG_UART_1, &uart1Params);
    
        if (uart1 == NULL) {
            /* UART_open() failed */
            while (1);
        }
    
        /* Loop forever to start the console */
        while (1)
        {                                   // today
            memset(cmnd_in, 0x00, sizeof cmnd_in);
            UART_write(uart0, echoPrompt, sizeof(echoPrompt));
            i = UART_read(uart0, cmnd_in, 20);
            if (i != 20)
            {
                while (1)
                    ;
            }
    
            UART_write(uart1, cmnd_in, strlen(cmnd_in));
            UART_write(uart1, "\r\n", 2);
    
            UART_write(uart1, echoPrompt1, sizeof(echoPrompt1));
            i = UART_read(uart1, bbff, 20);
            if (i != 20)
            {
                while (1)
                    ;
            }
            UART_write(uart0, "\r\n\n", 3);
            UART_write(uart0, &bbff[0], i);
            UART_write(uart0, "\r\n\n", 3);
    
        }
    }
    

    What is the data loss when you enable DMA?

    Best regards,

    Sarah

  • The code you provided works well.
    My code also works well when data is not large and fast using DMA. but, when receive the packet of variable size and large(In my test case, period 100ms, on average 800bytes.), occur data loss using DMA.

    Is this related to the size of the receiving ring buffer?

    In case not use DMA, I configured Ring Buffer size to 4096 in syscfg.
    In case use DMA, I can't configure Ring Buffer size because enable the DMA checkmark, its configuration items disappear.

    and I found that arbitration size of DMA is from 1 to 1024 in CC323x reference manual.

    Is it correct that arbitration size means the size of the buffer that can be processed?

    Thanks.

  • Hi Jinhyeong Lee,

    The ring buffer size parameter in SysConfig controls is size of ring buffer internal to the driver. It has nothing to do with the ring buffer you are using with your RB_* APIs. If you are not seeing data loss with the test code, then the issue is somewhere in your application code.

    The arbitration size controls the switching between various DMA operations. The DMA max buffer size is fixed to 1024 words no matter the arbitration size.

    Best regards,

    Sarah