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.

RTOS/CC1310: Read data from UART using callback method.

Part Number: CC1310


Tool/software: TI-RTOS

Hi,

I would like to use the UART interface for receiving and transferring data. I could see only simple uart echo example. I want to use the Callback method and DMA method. Are there any example to guide how to use UART in cc1310??

Thanks,

Kunal

  • Hi Kunal,

    For callback examples, please see the UART driver documentation:

    dev.ti.com/.../_u_a_r_t_c_c26_x_x_8h.html

    Regarding UART and DMA, the current UART driver does not include any support for using DMA.
  • Thank you for your quick response. I went through the link you provided and "Receive Continously in UART_MODE_CALLBACK" use case is suitable I guess. But, I have below queries for the same :
    i) How could I read the status/error value of "UARTCC26XX_Object.status" for UART_read() error/success validation?
    ii) Can i switch between callback method and blocking method without loss of data? So, that i no need to poll the data in callback. As we should avoid any long operations in callback.

    Any idea for future release of UART driver with DMA ??

    Regards,
    Kunal

  • I had revised UART echo example to use RX callback. I attach my uartecho.c for your reference.

    /*
     * Copyright (c) 2015-2017, 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>
    
    /* Example/Board Header files */
    #include "Board.h"
    
        UART_Handle uart;
        UART_Params uartParams;
    
    const char  echoPrompt[] = "Echoing characters:\r\n";
    const char  rxcb[] = "rx cb:\r\n";
    char        input[100];
    uint8_t     uartLineEndCount = 0;
    
    void Uart_ReadCallback(UART_Handle handle, void *rxBuf, size_t size)
    {
        UART_read(uart, &input, size);
        uartLineEndCount++;
        UART_write(uart, input, sizeof(input));
    }
    
    /*
     *  ======== mainThread ========
     */
    void *mainThread(void *arg0)
    {
    
        /* 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);
    
        /* Create a UART with data processing off. */
        UART_Params_init(&uartParams);
        uartParams.readMode = UART_MODE_CALLBACK;
        uartParams.readCallback = Uart_ReadCallback;
        uartParams.writeDataMode = UART_DATA_TEXT;
        uartParams.readDataMode = UART_DATA_TEXT;
        uartParams.readReturnMode = UART_RETURN_NEWLINE;
        uartParams.readEcho = UART_ECHO_OFF;
        uartParams.baudRate = 115200;
    
        uart = UART_open(Board_UART0, &uartParams);
    
        UART_write(uart, echoPrompt, sizeof(echoPrompt));
    
    
        if (uart == NULL) {
            /* UART_open() failed */
            while (1);
        }
    
        /* Loop forever echoing */
         UART_read(uart, &input, 1);
         while (1);
    
    
    }
    

  • Hi Kunal,

    To read out the status, you will have to access the UARTCC26XX_Object as there is no API available for reading out the status.

    You can not switch between blocking and callback mode when using the driver. You will have to close and re-open it again with the desired mode. Could you elaborate on your intended use case as you are talking about polling data?

    DMA is something that is planned for the UART driver but there is not any dates available on when this might be included.
  • Hi,

    I want to receive variable length data without any time sync, i.e. at any time data can be received.
    - How can i configure FIFO size?? What is default?
    - FIFO threshold will be in multiple of 4?? Do i need to receive data in multiple of 4??

    - Also, if i call UART_read() for 1 byte and FIFO has lets say 5 bytes. Will the call back buffer give me 5 bytes or 1 byte??


    Regards,
    Kunal

  • Hi,
    Thank you sharing the example.
  • Hi Kunal,

    You can not configure the size of the FIFO, what you can configure is the size of the internal ring buffer by increasing/decreasing the size of the array found in the board file.

    There is a RX timeout which means that if the transaction does not fill the FIFO buffer, the interrupt will still go off when after the hardware timeouts.

    If you do a UART_read call for 1 byte, the callback will give you 1 byte and the rest will be stored in the ring buffer until later. For variable length messages is might be of interest to look into enabling partial return.
  • Hi,
    I have tried the demo file given by you. But I am unable to receive any interrupt/callback.
    I am trying to write from minicom and expecting the data back to minicom. It is working fine with polling loop-back but callback loop-back is not working.
    CC1310 supports only 1 UART ?? What if i want some debug print with other UART port?? Any other way to use debug prints ??
    Thanks,
    Kunal
  • Which CC1310 SDK version do you use? CC1310 only supports one UART.
  • SDK Version :simple link cc13x0 2_10_00_36
  • I test it with UART ech example in SimpleLink CC13x0 SDK v:2.20.00.38 and it work fine.
  • Hi,

    I am trying UART polling as well as callback. As per my understanding RX FIFO size is 32 bytes. I am trying polling with below parameters :

    writeDataMode = UART_DATA_BINARY;

    readDataMode = UART_DATA_BINARY;

    baudRate = 115200;

    I want to receive maximum 200 bytes of data. I tried for UART polling read for 128 bytes but i am not able to receive any data, i.e. read call blocks and does not return. My idea is to receive 200 bytes at any time, so i guess polling will be fine if i use separate task for the same, or callback will also work. Can you please suggest me how to receive 200 bytes by both the methods ?? Also, how many bytes of Ring buffer can be increased ?? What is the exact functionality of Ring buffer??

    Thanks,

    Kunal

  • Hi Kunal,

    Polling read/write are not supported in the UART driver for CC1310 as stated in the specific driver documentation:
    dev.ti.com/.../_u_a_r_t_c_c26_x_x_8h.html

    You can use normal read/write operations in blocking or callback mode to achieve this. You could either run a separate task where you receive in blocking mode.Or you could do callback operations instead of blocking which does not necessarily needs it's own task.

    In both scenarios you can enable "PARTIAL RETURN" which means you can read out less then the "expected" data. For example, if you setup a 400 byte read but only get 203 bytes, the operation would still complete.

    The ring buffer is used to buffer RX data in between read calls. When a UART_read() completes, the RX module is left on and keeps storing data into the ring buffer until the next call to UART_read. You can make this bigger if you need to be able to buffer more data in-between read calls by increasing the size of the buffer inside the board file.
  • Hi M-W,

    Sorry for the misunderstanding, i am not using polling mode. I am trying to receive 200 bytes in blocking mode. I found undefined behaviour while receiving 200 bytes from a UART_read(), which is the only task running. I guess maximum size to read any data is 128 bytes. Is this correct ??

    Thanks,
    Kunal

  • Hi Kunal,

    You should not be limited to reading more then 128 bytes of data, you could potentially read much more then that.
    How are you configuring the UART driver, do you enable partial return?

    What is the "undefined behavior" that you are seeing?
  • Hi M-W,

    Thank you for suggesting Partial return, i have tried that and i am able to receive more than 200 bytes. I am using below params : 

    UART_Params_init(&params);

    params.writeDataMode = UART_DATA_BINARY;

    params.readDataMode = UART_DATA_BINARY;

    params.baudrate = 115200;

    fd = UART_open(port, &params);

    UART_control(fd, UARTCC26XX_CMD_RETURN_PARTIAL_ENABLE, NULL);

    I have a task which we will be waiting on UART_read(); for 200 bytes.

    The problem i am facing is when i receive packet with 32 bit delay. Lets say, I transmitted 8 bytes, and cc1310 received 3 bytes, because of 32 bit delay after 3rd byte. So, when i try for read call next it wont give me remaining 5 bytes. Any other solution for this?? I am able to receive remaining bytes when i transmit any other bytes. But this is not my use case. I want to transmit unknown number of bytes but also i should be able to retreive proper data, irrespective of delay.

    Please suggest me solution for the same.

    Thanks,

    Kunal

  • Hi Kunal,

    The bit-delay would possibly trigger the timeout in which case you would get the 3 bytes already received. The following five bytes should however still be received and stored in the internal ringBuffer. These bytes should then be returned to you right away following the next UART_read call.

    Could you share the part of the code where you perform UART_read? Also, what SDK version are you using, have you tried running the latest SDK (2.20)?
  • Hi M-W,

    I am using SDK Version :simple link cc13x0 2_10_00_36. Logically it is correct that Partial returns after timeout. But i am not getting next 5 bytes when i call UART_read call again. Below is my task for reading uart data.

    void *readTask(void* arg) {
    uint8_t data[200];
    uint8_t readBytes, i;

    while(1) {
    readBytes = UART_read(fd, data, 200);

    for(i = 0; i < readBytes; i++) {
    System_printf("rx[%d] : %02x", i, data[i]);
    System_flush();
    }
    System_printf("\r\n");
    System_flush();
    }

    Thanks,
    Kunal
  • Hi Kunal,

    I will need to test this out and see if I can reproduce this. Just too see that I understand the scenario correctly:

    You have device sending you 8 bytes of data over UART with a pause in-between the 3rd and 4th byte, causing a timeout.

    You get the initial three bytes as partial return is enabled, but the other five is never returned when calling UART_read again.

    If you send additional data to the UART, you get the final five bytes + the new data returned.

    Is this correct?

    Would it be possible for you to try and re-create this using the "Empty" example and share it with me?
  • Hi M-W,

    Yes, correct understanding and thank you for understanding the scenario.
    I have found the reason as well. I guess, when we call UART_read, it returns 3 bytes and rest of bytes are stored in Ringbuffer by UART driver.
    When we send additional 2nd packet then, driver sends previous 5 bytes from ring buffer and new packet from fifo.
    Ideally i guess design should be like UART_read should return whatever bytes of data are in ring buffer. Just an idea!!

    As provided above are the only psuedo code, so you can use both above snippet.

    Thanks,
    Kunal
  • Hi Kunal,

    Looking closer at the pseudo code, this would be the expected driver behavior. When operating in blocking mode, the call would not return with the data in the ring buffer unless we can extract as many bytes that was requested.

    What will happen is that it reads out the ring buffer and then goes into RX again awaiting additional data that in turn can trigger the RX timeout and case a "partial return".

    This should not be a problem if you can move to using callback mode, I will look further into if this is something that should be supported.
  • Hi M-W,

    Thanks for your kind response. I will try callback as well. Meanwhile, i am using ring buffer to get remaining data. Let me get back to you, if i face any problem with callback with partial return.

    Thanks
    Kunal