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.

LAUNCHCC3220MODASF: Using Timeout and Function UART_read, the CR and LF Codes are Are Never Read From UART.

Part Number: LAUNCHCC3220MODASF
Other Parts Discussed in Thread: CC3220MODA

Using the CC3220 with code based on the Network Terminal example we have tried to add a read from a UART to our system and need the read from that UART not to block.

We have experimented with turning on the UART time out and the following code to read the UART strings which are terminated with CR and or LF.

Our conditional test never sees the termination codes (CR LF). See line 32 of the code below.

Would like some ideas.

Lee Erickson

Here is the UART initialization:

//*****************************************************************************
//
//! Initialization
//!
//! This function
//!        1. Configures the UART to be used.
//!
//! \param  none
//!
//! \return none
//
//*****************************************************************************
UART_Handle InitTerm(void)
{

    UART_Params   		uartParams;

    UART_init();
    UART_Params_init(&uartParams);

    uartParams.writeDataMode    = UART_DATA_TEXT;
    uartParams.readDataMode     = UART_DATA_TEXT;
    uartParams.readReturnMode   = UART_RETURN_NEWLINE;
    uartParams.readEcho         = UART_ECHO_OFF;
    uartParams.readTimeout      = 2000;
    uartParams.baudRate         = 115200;

    uartHandle = UART_open(Board_UART0, &uartParams);

    /* remove uart receive from LPDS dependency */
    UART_control(uartHandle, UART_CMD_RXDISABLE, NULL);
    uart1Handle = UART_open(Board_UART1, &uartParams);      // GAA 30Aug2018

    /* remove uart receive from LPDS dependency */
    UART_control(uart1Handle, UART_CMD_RXDISABLE, NULL);     // GAA 30Aug2018

    return(uartHandle);
}

Here is the code:

//*****************************************************************************
//  Non blocking
//! Rec chars from UART1 (RS485) and writes them to the global Rec buffer
//
//*****************************************************************************
void RS485Recvnb(void)
{
    char    cChar;
    int     i = 0;
    int index1 =0;
    int index2 =0;
    int len=0;

        memset((char *)gUARTRecBuf, 0, sizeof((char *)gUARTRecBuf));
        gUARTRecBufIndex =0;

        memset((char *)TempRecBuf, 0, sizeof((char *)gUARTRecBuf));
        TempRecBufIndex =0;

        cChar = 0;
        while ( (cChar != '>') && (cChar !='#') ) {
           UART_read(uart1Handle, &cChar, 1);
        }

        gUARTRecBuf[gUARTRecBufIndex++] = cChar;
        UART_writePolling(uartHandle, &cChar, 1);    // Echo the received character to the debug UART

        while(1)
            {
            int_fast32_t testint = UART_read(uart1Handle, &cChar, 1);
            UART_PRINT("%d/n", testint);
            if ((cChar == '\r') || (cChar =='\n')) {
                gUARTRecBuf[gUARTRecBufIndex++] = cChar;
                UART_writePolling(uartHandle, &cChar, 1);    // Echo the received character to the debug UART
                break;
            }
            else {
                gUARTRecBuf[gUARTRecBufIndex++] = cChar;
                UART_writePolling(uartHandle, &cChar, 1);    // Echo the received character to the debug UART
            }
        }
}

  • Hi Lee,

    Have you tried using a logic analyzer to make sure the new line is actually being transmitted?

    Jesu

  • Jesu,

    Before we changed the code we were  using a blocking UART read and the CR at the end of the message was coming through.

    I do not have a logic analizer (just an Oscilloscope) However, the data into the UART we can monitor (it's a RS485 bus with other listeners) and the CR is present.  Here is a screen shot from the input of the UART side showing  the line is terminated with CR.

    It is as if the "UART_read" is swallowing the CR.

  • Is the "UART_read" known to swallow CR (and or LF) ?

    Wonder where I can find examples of how to use the UART with a time out so that if the RS485 instrument bus the UART connects to does not respond, the program exicution is not blocked and we can ask again or do other tasks and come back later and try again.

  • Hi Lee,

    I recently learned that timeouts only work in UART blocking mode and the UART_DATA_TEXT mode seems to add some steps to the driver depending on the mode and whether read or write. 

    First lets make sure you are in fact in blocking mode by add uartParams.readMode = UART_MODE_BLOCKING and the same for writeMode.

    Next try using UART_DATA_BINARY instead of UART_DATA_TEXT to remove the data processing and explicitly write the CR and LF (\r and \n) to your uart writes.

    This should fix your issues or at least remove any doubts about UART_DATA_TEXT and what mode you're operating on.

    Jesu

  • Hello Jesu,

    Thanks for getting back to us.  I sort of have the time out working but data is not making it through.

    I am experimenting and am try to make the code as concise possible and have updated UART  initialization as follows:

    UART_Handle InitTerm(void)
    {
    
        UART_Params   		uartParams;
    
        UART_init();
        UART_Params_init(&uartParams);
    
        //uartParams.writeDataMode    = UART_DATA_TEXT; //From Terry's code.
        //uartParams.readDataMode     = UART_DATA_TEXT;
        uartParams.writeDataMode    = UART_DATA_BINARY;
        uartParams.readDataMode     = UART_DATA_BINARY;
        uartParams.readMode = UART_MODE_BLOCKING;
        uartParams.readReturnMode   = UART_RETURN_FULL;
        uartParams.readEcho         = UART_ECHO_OFF;
        uartParams.readTimeout      = 2000;   // FLE guess at a time out in mS. 20191010
        uartParams.baudRate         = 115200;
    
        uartHandle = UART_open(Board_UART0, &uartParams);
    
        /* remove uart receive from LPDS dependency */
        UART_control(uartHandle, UART_CMD_RXDISABLE, NULL);
        uart1Handle = UART_open(Board_UART1, &uartParams);      // GAA 30Aug2018
    
        /* remove uart receive from LPDS dependency */
        UART_control(uart1Handle, UART_CMD_RXDISABLE, NULL);     // GAA 30Aug2018
    
        return(uartHandle);
    }

    I have copied and updated a new UART receive on which to experiment as follows:

    void RS485RecvnbExperiment(void)
    {
        char    cChar = 'A';    //Initialize with something printable
        int_fast32_t numRead =0;
    
        gUARTRecBufIndex =0;
        memset((char *)gUARTRecBuf, 0, sizeof((char *)gUARTRecBuf));
        GPIO_write(CC3220SF_LAUNCHXL_GPIO_TP217,1); //For instrument of RS485 buss traffic.
        numRead = UART_read(uart1Handle, &cChar, 1);              // FLE 21091010 Try the read rather than polling
        GPIO_write(CC3220SF_LAUNCHXL_GPIO_TP217,0);
        while(1)
           {
            if ((cChar == '\r') || (cChar =='\n') || (numRead == 0)) // Checking the end of Command or Timeout
               {
               UART_writePolling(uartHandle, &cChar, 1);    // Echo the received character to the debug UART
               gUARTRecBuf[gUARTRecBufIndex++] = cChar;     // and store the character in a buffer
               break;
               }
            else
               {
                UART_writePolling(uartHandle, &cChar, 1);   // Echo the received character to the debug UART
                gUARTRecBuf[gUARTRecBufIndex++] = cChar;    // and store the character in a buffer
               }
            GPIO_write(CC3220SF_LAUNCHXL_GPIO_TP217,1); //For instrument of RS485 buss traffic.
            numRead = UART_read(uart1Handle, &cChar, 1);              // FLE 21091010 Try the read rather than polling
            GPIO_write(CC3220SF_LAUNCHXL_GPIO_TP217,0);
          }       // while (1)
        gUARTRecBuf[gUARTRecBufIndex++] = '\0';             // put a string terminator in the buffer
    //    UART_PRINT("RS485Recv: end \r\n");
    }// End RS485RecvnbExperiment

    The read now times out after 2 seconds. However the data is not getting through. More details: I send a ">04" command using a terminal program on my phone connected to the CC3220 WiFi Access Point.   The WiFi is writing the ">04" on to the 485 buss and the response is written back to the bus ("#04....")  The CC3220 UART is not sending the response out the WiFi to my phone terminal. Only the letter "A" and some  characters I think represent the CR LF come back to my phone terminal.

    Here is a screen shot where the left terminal windows is the CC3220 UART1 RS485 bus and the right terminal is the WiFi DEBUG UART0.

    The right terminal window should have response: "#040000086200000000000001C90000016F00"

    <edited>

  • Screen shot from my phone terminal.

  • The InitTerm() function was worked up by an engineer no longer here. So I am now coming up to speed. Looking at it I see that UART0 and UART1 are both initialized the same way by this code. Not sure if that is a problem since we are now trying to make UART1 have this Timeout behavior but am sure I do not know the implications for the DEBUG interface on UART0.

  • Hi Lee,

    Regarding configuring UART0 and UART1  it should not matter as long as you update the UART_params before you call UART open. UART_open returns a handle to distinguish one UART from the other. To give you an idea code should look like below for configuring both UARTs differently.

    // set UART params
    // Call UART_open UART0
    // update UART_params
    // Call UART_open UART1

    I'm not 100% sure what is going on. It seems like you have multiple device and channels (2 UARTS and WiFi) at play here. The best i could tell you is debug our device to make sure the data coming in and out across both mediums is what is expected and verify that across every node in play. I currently cannot tell which device is not sending the correct data. More so if it's because of how the transmitter is configured to transmit or how the receiver is configured to receive. Some terminal programs are configured to implicitly format data.

    Jesu

  • Hello Jesu,

    I worked up independant inilization for the two UARTs as above. It did not change antying for the worse or better but now they are independant as they should be.

    Regarding our project. I will try to summarize.
    My predecessors began with the Network Terminal example code. Where UART0 is the command and debug interface. Then UART1 was added to the design for interface in our instrument as an RS485 bus.

    We added a socket transceiver function for the wireless interface and when data was received from a wireless connected device with an appropriate  command (example ">04CR" the command is written to UART1 for the RS485 bus. Then the program goes into a blocking UART_read to await for the RS485 response which is something like "#04xxxxxxxxxxxxxxxCR" where xxxxxxxxxxxxx is several sets of data.  Very very infrequently, the other device on the bus which is supposed to provide the "#04xxxxxxxxxxxxxxxCR" fails to do so and then we have to power cycle our product to restore communication.  That is why we want to get the time out to work. The wireless controlling device retries the request and so would likely be successful on a retry if the UART unblocked.

    I have now become familiar with the uartecho example project you recommended. I have worked it up to try different initialization of the UART and both the UART_readPolling and UART_read functions.

    With UART_readPolling the time out does not work but with UART_read the time out works as desired and the characters echo as expected and my time out message is sent every 2 seconds if I am not sending data.   I will post the code after this post. 

    However when I try the same UART setup and a similar code with UART_read in our project there are not characters read by the UART. The time out is happening and the time out is held off when I send characters but the character returned from the UART_read is not changed from the value I set when it was declared.   I will see if I can make our project code readable and post excerpts in yet another post.

  • My uartecho code:

    /*
     * 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.
     */
    
    /*
     * /brief Modifications by F. Lee Erickson
     *
     * /date 20191011
     *
     *  Toggle LED. (It is the blue one).
     */
    
    /*
     *  ======== 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 Read Types */
    //#define usePolling 1
    
    /*
     *  ======== mainThread ========
     */
    void *mainThread(void *arg0)
    {
        char        input = 'Y';
        const char  echoPrompt[] = "Echoing characters in Blocking Mode with Timeout:\r\n";
        const char  echoCR[] = " Received CR ";
        const char  echoLF[] = " Received LF ";
        const char  echoZeroLN[] = "\r\nReceived Zero Length.";
        UART_Handle uart;
        UART_Params uartParams;
        int_fast32_t numRead = 9999;    // Number read in UART.
    
        /* Call driver init functions */
        GPIO_init();
        UART_init();
    
        /* Configure the LED pin */
        //GPIO0 BLUE
        //GPIO1 ???
        GPIO_setConfig(Board_GPIO_LED0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
        GPIO_setConfig(Board_GPIO_LED1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    
        /* Turn on user LED */
        GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON);
        GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_ON);
    
        /* Create a UART with data processing off. */
        UART_Params_init(&uartParams);
    
        /* Parameters from example. */
        /* Byte by byte is transferred one at a time. */
    //    uartParams.writeDataMode = UART_DATA_BINARY;
    //    uartParams.readDataMode = UART_DATA_BINARY;
    //    uartParams.readReturnMode = UART_RETURN_FULL;
    //    uartParams.readEcho = UART_ECHO_OFF;
    //    uartParams.baudRate = 115200;
    
        /* Experimental parameters for testing time out. */
        /* Create a UART with data processing off. */
        /* Byte by byte is transfered one at a time. */
        uartParams.writeDataMode = UART_DATA_BINARY;
        uartParams.readDataMode = UART_DATA_BINARY;
        uartParams.readReturnMode = UART_RETURN_FULL;
    //    uartParams.readMode         = UART_MODE_CALLBACK;
        uartParams.readMode         = UART_MODE_BLOCKING;
        uartParams.readEcho = UART_ECHO_OFF;
        uartParams.readTimeout      = 2000;   // FLE guess at a time out in mS. 20191010
        uartParams.baudRate = 115200;   // Character drop out on files with RealTerm.
    
        uart = UART_open(Board_UART0, &uartParams);
        if (uart == NULL) {
            /* UART_open() failed */
            while (1);
        }
    
        /* Let's write and read once in polling mode to see if that makes a problem. */
    //    UART_writePolling(uart, echoPrompt, sizeof(echoPrompt));
    //    numRead = UART_readPolling(uart, &input, 1);
    
    #ifdef usePolling
        UART_writePolling(uart, echoPrompt, sizeof(echoPrompt));
    #else
        UART_write(uart, echoPrompt, sizeof(echoPrompt));
    #endif
    
        /* Loop forever echoing */
        while (1) {
                #ifdef usePolling
                        numRead = UART_readPolling(uart, &input, 1);
                #else
                        numRead = UART_read(uart, &input, 1);
                #endif
    
            if (numRead == 0){
                #ifdef usePolling
                            // UART_readPolling
                            UART_writePolling(uart, echoZeroLN, sizeof(echoZeroLN));
                #else
                            UART_write(uart, echoZeroLN, sizeof(echoZeroLN));
                #endif
                GPIO_toggle(Board_GPIO_LED0);  /* Toggle user LED */
            }
            else if (input == '\r' ) {
                #ifdef usePolling
                    UART_writePolling(uart, echoCR, sizeof(echoCR));
                #else
                    UART_write(uart, echoLF, sizeof(echoCR));
                #endif
    
            }
            else if (input == '\n') {
                #ifdef usePolling
                    UART_writePolling(uart, echoLF, sizeof(echoLF));
                #else
                    UART_write(uart, echoLF, sizeof(echoLF));
                #endif
            }
    
            #ifdef usePolling
                UART_writePolling(uart, &input, 1);
            #else
                UART_write(uart, &input, 1);
            #endif
        }
    }
    

    I have run this on a CC3220MODA Launchpad.

  • The receive routine in our project which times out but which does not get characters into cChar.  The value remains stuck at "Y".


    //*****************************************************************************
    //
    // Receive chars from UART1 (RS485) and writes them to the global Rec buffer
    // also echoes characters to the debug UART
    // Exits on CR LF or time out (read zero character)
    // Lets make TP216 go high when WiFi transmitting RS485 UART data  FLE 20190827
    // Lets make TP217 go high when WiFi waiting to receive RS485 UART data.
    //
    //*****************************************************************************
    void RS485RecvnbExperiment(void)
    {
        char    cChar = 'Y';    //Initialize with something printable
        int_fast32_t numRead =0;
        const char  echoCR[] = " Received CR ";
        const char  echoLF[] = " Received LF ";
        const char  echoZeroLN[] = " Received Zero Length \r\n";
        gUARTRecBufIndex = 0;
        memset((char *)gUARTRecBuf, 0, sizeof((char *)gUARTRecBuf));
    
        GPIO_write(CC3220SF_LAUNCHXL_GPIO_TP217,1); //For instrument of RS485 buss traffic.
        numRead = UART_read(uart1Handle, &cChar, 1);              // FLE 21091010 Try the read rather than polling
        GPIO_write(CC3220SF_LAUNCHXL_GPIO_TP217,0);
        while(1){
            if ((numRead == 0)) // Checking Timeout
               {
               //UART_writePolling(uartHandle, &cChar, 1);    // Echo the received character to the debug UART
               UART_write(uartHandle, &cChar, 1);    // Echo the received character to the debug UART
               UART_write(uartHandle, echoZeroLN, sizeof(echoZeroLN));
               gUARTRecBuf[gUARTRecBufIndex++] = cChar;     // and store the character in a buffer
               break;
               }
            else if ((cChar =='\n')) // Checking for new line
               {
               //UART_writePolling(uartHandle, &cChar, 1);    // Echo the received character to the debug UART
               UART_write(uartHandle, &cChar, 1);    // Echo the received character to the debug UART
               UART_write(uartHandle, echoLF, sizeof(echoLF));
               gUARTRecBuf[gUARTRecBufIndex++] = cChar;     // and store the character in a buffer
               break;
                       }
            else if ((cChar =='\r')) // Checking for CR
               {
               //UART_writePolling(uartHandle, &cChar, 1);    // Echo the received character to the debug UART
               UART_write(uartHandle, &cChar, 1);    // Echo the received character to the debug UART
               UART_write(uartHandle, echoCR, sizeof(echoCR));
               gUARTRecBuf[gUARTRecBufIndex++] = cChar;     // and store the character in a buffer
               break;
               }
            else  // cChar is something but not CR LF.
               {
                //UART_writePolling(uartHandle, &cChar, 1);   // Echo the received character to the debug UART
                UART_write(uartHandle, &cChar, 1);    // Echo the received character to the debug UART
                gUARTRecBuf[gUARTRecBufIndex++] = cChar;    // and store the character in a buffer
               }
            GPIO_write(CC3220SF_LAUNCHXL_GPIO_TP217,1); //For instrument of RS485 buss traffic.
            numRead = UART_read(uart1Handle, &cChar, 1);              // FLE 21091010 Try the read rather than polling
            GPIO_write(CC3220SF_LAUNCHXL_GPIO_TP217,0);
          }       // while (1)
        gUARTRecBuf[gUARTRecBufIndex++] = '\0';             // put a string terminator in the buffer
    //    UART_PRINT("RS485Recv: end \r\n");
    }// End RS485RecvnbExperiment
    

  • Jesu,

    The documentation for the UART says not to mix the Polling functions with the non Polling. Our project specific code is the only code accessing UAR1 however the Network Terminal code for UART0 is using the Polling method. It had me wondering if something from one UART function call might affect another UART.  Sure seams unlikely but I am at a loss for what to suspect.

    Thanks,

  • Hi Forrest,

    Thanks for the explanation and congrats on producing the behavior you want on uart_ehco.

    UART_write and writePolling are mutually exclusive and read and readPolling as well. It also makes sense that the timeout does not work with polling because it is defined to not return until the expected number of bytes have been read. From a performance standpoint it is better not to use polling anyway because polling just hogs up the CPU until it is finish.

    Network terminal uses UART_PRINT, APP_PRINT and if I remember correctly Report throughout the entire application which all end up using writePolling and readPolling. Make sure there is none of those lingering around somewhere. Also, since you're using UART_MODE_BLOCKING write and read must be called in a task so that it can properly block. If you are calling it in a function it will probably cause weird behavior.

    Jesu

  • Jesu,

    Regarding, "...the entire application which all end up using writePolling and readPolling. Make sure there is none of those lingering around somewhere."
    We have removed NONE of them and assume we do not have to because they use UART0 exclusively.

    Our added code uses UART1 exclusively.

    We are assuming the documentation that says not to mix the modes has an unstated qualification of, "for a given UART, to not mix UART_read and UART_readPOLLING".

    Can you confirm that we can use one mode on UART0 and the other mode on UART1 and it will be OK?  

    BTW,  My coworker says that if we had the source code for the UART_read that would help us. Where might we find it?

  • Hi Lee,

    Correct - I just wanted to make sure the calls are not getting mixed but using polling on one peripheral and non-polling on the other UART should be okay. UART source can be found in SDK_root/source/ti/driver. There is a uart folder in there with the actual implementation. UART.h and UART.c is just an abstraction layer that calls the functions in the uart folder.

    Jesu

  • I found the problem where our UART_read was timing out with no characters.

    In our init code above was this line:

    UART_control(uart1Handle, UART_CMD_RXDISABLE, NULL);     // GAA 30Aug2018


    This caused the UART not to read. Not sure how our UART0 was reading because the same code is run on it too.
    But when I commented out that line then our project works like the modification I made to the uartecho.
    My co-worker and I suspect that elsewhere in the project there are additional changes to the setup of the
    UARTs which we have not yet located.

    This resolves my problem.

    Jesu,
    Thanks again for all your help and patients.