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.

CC1310: UART not able to receive more than 128 bytes in callback mode

Part Number: CC1310
Other Parts Discussed in Thread: CC1350,

I need to receive a data stream over UART in callback mode and I need to store the stream in buffer entities of 26 bytes. Thus I have used partial return mode. It usually works for messages below 128 bytes, but above it does not work in most of the cases. Sometimes I can receive up to 192 bytes, sometimes I even got 256, but most of the time, I can only receive 128 bytes. 

I have created a minimal test application.

  • Import the uartEcho example from SDK 4.10.01 (you can use TIRTOS, NoRTOS, it doesn't matter)
  • Replace the attached uartecho.c file
  • Configure the serial port to 38400 (or change the baudrate in the example accordingly, the baudrate doesn't really matter)
  • Send a long message from a terminal in one go, for instance 300 bytes long. It is important to send it as a single message. As soon as there is a pause in between, the mcu receives more bytes.
  • Halt the application after sending the message and check the bytesReceived variable.

Could you help me to find out what causes the problem?

Thanks

/*
 * 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>

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

/* Example/Board Header files */
#include "Board.h"

uint8_t data[1024];
uint32_t bytesReceived;

void uartReadCallback(UART_Handle handle, void *buffer, size_t num)
{
    bytesReceived += num;
    UART_read(handle, &data, 26);
}

/*
 *  ======== mainThread ========
 */
void *mainThread(void *arg0)
{
    char        input;
    const char  echoPrompt[] = "Echoing characters:\r\n";
    UART_Handle uart;
    UART_Params uartParams;

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

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

    /* Turn on user LED */
    GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON);

    UART_Params_init(&uartParams);
    uartParams.baudRate = 38400;
    uartParams.readDataMode = UART_DATA_BINARY;
    uartParams.readMode = UART_MODE_CALLBACK;
    uartParams.readCallback = &uartReadCallback;
    uartParams.readEcho = UART_ECHO_OFF;
    uartParams.readReturnMode = UART_RETURN_FULL;

    uart = UART_open(Board_UART0, &uartParams);
    UART_control(uart, UARTCC26XX_CMD_RETURN_PARTIAL_ENABLE, NULL);

    UART_read(uart, &data, 26);


    if (uart == NULL) {
        /* UART_open() failed */
        while (1);
    }

    while (1) {
        usleep(10000);
    }
}

  • Hi Rick,

    1) What version of the SimpleLink CC13x0 SDK have you tested with?

    2) Since you say bad rate doesn't matter, have you tested other baud rates?

    3) When you say you halt the application after sending the message, can you give the exact line number in this source file?

    Cheers,

    Marie H.

  • 1) SimpleLink SDK 4.10.01 as already written

    2) Yes, I see the same behavior on all baudrates

    3) Just hit the pause button after the host has completed sending the message. bytesReceived is a static variable and can be inspected from anywhere.

  • Hi Rick,

    Please note that it is not recommended to call UART_read() from its own callback as this can potentially lead to stack overflow issues. We recommend posting a semaphore from the callback function and then handle subsequent reads from within your task.

    This might solve the issue that you are seeing.

    BR,
    AndresM

  • Hi Andres,

    thanks for your reply. I am just following the official recommendation in https://software-dl.ti.com/simplelink/esd/simplelink_cc13x2_26x2_sdk/4.20.00.35/exports/docs/tidrivers/doxygen/html/_u_a_r_t_c_c26_x_x_8h.html for reading continuous bytes which does exactly that.

    Is the example maybe wrong or am I interpreting it wrong?

    Were you able to reproduce the issue I am reporting here?

    Thanks for your help.

  • Hi Rick,

    I don't believe that you are interpreting the example wrong. But since you are sending relatively long messages, I think that this might lead to some issues. I haven't procured the HW I need to reproduce your issue, but I'll do that soon, and I'll let you know my findings. 

    BR,
    AndresM

  • Hi Rick,

    Several things that need to be considered in your code.

    1. I don’t understand the reason behind using Return Partial Mode (since you know the exact number of bytes to be read). This option is commonly used to end the UART_read() operation if data reception is inactive for a given amount of time.
    2. You might have made a mistake in the code you submitted. Line 80 should be:

               uartParams.readCallback = uartReadCallback;

    1. Each time you are making a call to UART_read() in the callback, you are overwriting data (i.e. the array).

    The following code might be more in line with what you need. I tested it with a 500-byte long message, and I couldn’t see any issues. Basically you read the 500 bytes, and then you use UART_write() to send the same message back with the UART. Hopefully this gives you a better idea on how to proceed.

    uint8_t   data[1024];
    uint32_t  bytesReceived = 0;
    bool      done = false;
    
    
    void uartReadCallback(UART_Handle handle, void *buffer, size_t num)
    {
        bytesReceived += num;
    
        if(bytesReceived == 500)
        {
           done = true;
        }
        else {
            UART_read(handle, &data[bytesReceived], 50);
        }
    
    }
    
    /*
     *  ======== mainThread ========
     */
    void *mainThread(void *arg0)
    {
        UART_Handle uart;
        UART_Params uartParams;
    
        /* Call driver init functions */
        GPIO_init();
        UART_init();
    
        /* Configure the LED pin */
        GPIO_setConfig(Board_GPIO_LED0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    
        /* Turn on user LED */
        GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON);
    
        UART_Params_init(&uartParams);
        uartParams.baudRate = 38400;
        uartParams.readDataMode = UART_DATA_BINARY;
        uartParams.readMode = UART_MODE_CALLBACK;
        uartParams.readCallback = uartReadCallback;
        uartParams.readEcho = UART_ECHO_OFF;
        uartParams.readReturnMode = UART_RETURN_FULL;
    
        uart = UART_open(Board_UART0, &uartParams);
    
        if (uart == NULL) {
            /* UART_open() failed */
            while (1);
        }
    
        UART_read(uart, &data, 50);
    
        while (true) {
    
            if(done) {
            // Nothing else to read. Send back data through the uart.
            UART_write(uart, &data, bytesReceived);
            done = false;
            break;
            }
        }
    }

    BR,
    Andres

  • Hi Andres,

    first of all, thanks for trying to reproduce the issue. The example I have posted did indeed throw away the content by purpose. I just wanted to demonstrate that the MCU does not receive the full message.

    In the meantime I am a step further. I have connected a logic analyzer to the RxD pin of the launchpad and watched the traffic coming from the host. I can see that the XDS110 does only output 128 bytes, sometimes 192 bytes, but not more. So it's clearly a problem of the XDS.

    I can see that behavior only on a CC1310 and CC1350 launchpad. I cannot see it on a CC1352 or CC2642 launchpad, although the XDS110 firmware has the same version on all boards (3.0.0.15). Then I tried a Windows host and I can no longer see the issue.

    Could you please file a bug report to the XDS team, saying that 

    • CC13x0 launchpad with XDS110 (CC13x2/CC26x2 launchpads are not affected)
    • XDS firmware version 3.0.0.15
    • Linux host (kernel 5.4.0), Windows is not affected
    • when sending long messages from the host over the ttyACM device, the transfer stops after 128, sometimes after 192 bytes

    Could you please post here when the XDS teams confirms the issue?

    Thanks

  • Hi Rick,

    It's quite interesting that you are seeing that. Does the same thing happen when using the code I posted?

    Thanks.

    BR,
    Andres

  • Hi Andres,

    as explained in my previous post. This problem turned out to be completely unrelated to the CC1310. All you need to do is to hook up a logic analyzer to the RxD pin on the launchpad and send a long message from a Linux host over the pseudo serial device created by the XDS. Since it works correctly on CC13x2 launchpads, I don't think it's the Linux kernel driver but the XDS that's causing this. Hence my question whether you could file a bug report to the XDS team.

  • Hi Rick,

    Thank you for your answer. Before contacting the XDS team and submitting a bug report, I'll try to reproduce the issue myself and get back to you.

    BR,
    Andres

  • Hi Rick,

    I tried to reproduce the issue that you are facing, but I couldn’t experience what you are seeing. I tried two different revisions of the CC1310 Launchpad.

    My setup:

    • Ubuntu 18.4
    • CC1310 Launchpad Rev. 1.4 (XDS110 based on TM4C129)
    • CC1310 Launchpad Rev. A (XDS110 based on MSP432)
    • CuteCom (For serial communication monitoring)
    • Saleae Logic analyzer

    To run the tests, I used the modified UART echo example that I shared before. I modified it slightly to add a “Hello” message.

    1. The CC1310 sends a Hello message to the Linux host.
    2. From the Linux host (CuteCom), a single message with a length of 500 bytes is sent to the CC1310 through the XDS110.
    3. The CC1310 reads the message with UART_read() and once the 500 bytes have been received, it echoes back the message in its entirety to the Linux host, where it is visualized with CuteCom.
    4. This means that both Tx and Rx are being tested for long messages.

    All of this while also using the logic analyzer to monitor Tx and Rx.

    Attached you will find a screenshot of the CuteCom output. In the CuteCom screenshot, the upper text box shows the message sent from the host, and the lower text box shows the messages that the Linux host received (i.e. the “hello” message and the echoed message).

    Now, I’m aware that most likely there is a difference between the Linux Kernel you have and the one used in my tests, but I don’t sure if this would have such a strong effect in the results.   

     

    BR,
    Andres

  • Hi Andres,

    thank You for taking the time and trying to reproduce the reported issue. You mentioned cutecom. I tried that application and it suddenly worked. Before, I was only testing on command line and outputted values using cat and command-line based terminal applications.

    That indicates that the problem is on the host side. Either in the Linux kernel driver or even just in the port configuration.

    Best regards

    Rick