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.

CCS/LAUNCHXL-CC1310: Collector system stops working after UART message parsing

Part Number: LAUNCHXL-CC1310

Tool/software: Code Composer Studio

Hey guys,

I am using the collector example in nob-beacon mode 15.4 TI Stack. I've implemented UART read in callback mode. And this works quite good so far, the messages are read and I can rebuild the message and send it back to via UART write. However, something is kind of crashing the application and I cant see how. I store the uart read message in the output buffer and depending on the first byte, I perform different actions.

        Llc_deviceListItem_t item;
        ApiMac_sAddr_t devAddr;
        devAddr.addrMode = ApiMac_addrType_short;
        output[index] = '\n';
        UART_write(hUart, &output, index++);
        index = 0;
        if(output[0] == '1')
        {
            const char reset_note[] = "FRe\r\n";
            UART_write(hUart, &reset_note, 5);
            Csf_ResetBoard();
        }
        if(output[0] == '2')
        {
            const char kick_note[] = "KiS\r\n";
            UART_write(hUart, &kick_note, 5);
            devAddr.addr.shortAddr = UartCopyBuffer(output);
            //Csf_getDevice(&devAddr, &item);
            //Cllc_removeDevice(&item.devInfo.extAddress);
        }
        ClearBuffer(output);

Using breakpoints I can see that both if-loops can be entered. The function Csf_ResetBoard() just resets the board and works fine. However, neither for case 1 or 2, UART_write works, although the UART_write action with "output" as buffer echoing the input works fine. I do then parse the shortAddr from the UART msg and hand it over to dev.Addr.addr.shortAddr, I actually verified, that the number "1" (test) was written into shortAddr. However, if I uncomment the next two functions the board stops working, the red blinking LED stops blinking and nothing happens anymore with the collector application.

The function UartCopyBuffer looks as follows:

uint16_t UartCopyBuffer(char *buffer)
{
    char container[32] = {'0'};
    char *ptr;
    uint8_t p = 0;
    ClearBuffer(container);
    while (buffer[p] != '\r' && buffer[p] != '\n')
    {
        /* start with index 1 because index 0 is not necessary */
        p++;
        container[p-1]=buffer[p];
    }
    cmd_shortAddr = strtol(container, &ptr, 6);

    return(cmd_shortAddr);
}
  1. Any idea why no prints are performed after the ouput buffer flushing? Posts outside uart_print.c are working when the application reaches them, maybe overflow?
  2. Any idea what could crash the application? The last function I can get to in debug mode is UARTCC26XX_swiIntFxn() when ClearBuffer() (see above) is finished.

I added a code snipped showing the content of devAddr right before calling Csf_getDevice().

Any comment welcome

Kind regards

Slev1n

  • New Info: We have made  new tests.

    If I have 5 sensors in the network and send a message to the collector via uart to kick sensor 0x0001. again, the system stops working indicated by the red led stopping to blink. however, if i immediately press the reset button, the following happens:

    • collector restarts
    • sensor is kicked
    • sensor rejoins but receives an already in use short adress and is stored incorrectly in NV

    This is the uart print:

    07.12.2019 10:56:18	Sli
    07.12.2019 10:56:19	0x01 | 09:4d:76:19:00:4b:12:00
    07.12.2019 10:56:19	0x02 | 48:49:76:19:00:4b:12:00
    07.12.2019 10:56:19	0x03 | 7d:49:76:19:00:4b:12:00
    07.12.2019 10:56:19	0x04 | 67:49:76:19:00:4b:12:00
    07.12.2019 10:56:19	0x05 | 00:49:76:19:00:4b:12:00
    07.12.2019 10:56:20	NumS: 5
    
    07.12.2019 10:56:35	kick1
    
    07.12.2019 10:56:36	initC
    07.12.2019 10:56:36	PAN_ID: ffff 
    07.12.2019 10:56:37	Csa: 38f3 
    07.12.2019 10:56:37	TI Collector
    07.12.2019 10:56:37	startApp
    07.12.2019 10:56:37	Restarted
    07.12.2019 10:56:37	CH: 0
    07.12.2019 10:56:38	PJ-ON
    07.12.2019 10:56:39	MAC: 7d:49:76:19:00:4b:12:00
    07.12.2019 10:56:39	AMA 5:1;0;0;0;0;
    07.12.2019 10:56:41	disD 0x01
    07.12.2019 10:56:42	MAC: 00:49:76:19:00:4b:12:00
    07.12.2019 10:56:42	AMA 5:0;0;0;0;0;
    07.12.2019 10:56:46	oUART
    07.12.2019 10:56:46	ConfigRsp: 0x2
    07.12.2019 10:56:47	ConfigRsp: 0x3
    07.12.2019 10:56:47	ConfigRsp: 0x4
    07.12.2019 10:56:51	ConfigRsp: 0x5
    07.12.2019 10:56:51	disD 0x01
    07.12.2019 10:56:53	newD
    07.12.2019 10:56:53	joinD: 0x05 | 09:4d:76:19:00:4b:12:00
    07.12.2019 10:56:56	Sli
    07.12.2019 10:56:56	0x02 | 48:49:76:19:00:4b:12:00
    07.12.2019 10:56:57	0x03 | 7d:49:76:19:00:4b:12:00
    07.12.2019 10:56:57	0x04 | 67:49:76:19:00:4b:12:00
    07.12.2019 10:56:57	0x05 | 00:49:76:19:00:4b:12:00
    07.12.2019 10:56:57	0x05 | 00:49:76:19:00:4b:12:00
    07.12.2019 10:56:57	NumS: 5

    The Sli is a sensor list, data is printed from the NV memory indicating that something went pretty wrong. This is reproducible. note hat i use the newest SDK 3.20.

    Any idea whats happening?

    kind regards

    Slev1n

  • Hey Slev1n,

    It appears that Ammar is helping with your TI 15.4-Stack issues here: https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz/f/156/t/863606

    We should try to focus on the UART issues for this thread.  Have you referenced the available TI Driver UART examples?  Is there a reason you decided not to re-purpose the Board UART interface created by the default collector example?  Please provide details of how you disabled this existing interface and initialized your own, along with replication steps starting from TI-provided code.

    Regards,
    Ryan

  • Ryan Brown1 said:
    It appears that Ammar is helping with your TI 15.4-Stack issues here: https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz/f/156/t/863606

    you are totally right, this are overlapping issues and the wrong short address assignment should be treated in the other thread.

    Ryan Brown1 said:
    Have you referenced the available TI Driver UART examples?

    Yes I did and I was able to solve some issues I had transferring this example into the collector example code. (check my first post in https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz/f/156/t/857475 )

    Basically I use the same uart parameter from the collector example and just added the read UART part.

    #if defined(BOARD_DISPLAY_USE_UART)
        /* Enable System_printf(..) UART output */
        UART_init();
        UART_Params_init(&uartParams);
    #ifndef TIMAC_AGAMA_FPGA
        uartParams.baudRate = 115200;
    //_________________MY CHANGE START____________
    #ifdef UART_READ
        uartParams.readDataMode = UART_DATA_BINARY;
        uartParams.readMode = UART_MODE_CALLBACK;
        uartParams.readCallback = readCmdCallback;
        uartParams.readEcho = UART_ECHO_OFF;
    #endif
    //__________________MY CHANGE END______________
    #else
        uartParams.baudRate = 460800;
    #endif
        UartPrintf_init(UART_open(Board_UART0, &uartParams));
    #endif /* BOARD_DISPLAY_USE_UART */

    Ryan Brown1 said:
    Is there a reason you decided not to re-purpose the Board UART interface created by the default collector example? 

    Correct me if I am wrong, but I dont think, that I am using another UART interface than the already provided one in the collector example.

    Ryan Brown1 said:
    Please provide details of how you disabled this existing interface and initialized your own, along with replication steps starting from TI-provided code.

    The UART initialization is presented above. I have a clock activating an event once, which calls check_UART()

        if(Collector_events & UART_COLLECTOR_OPEN)
        {
            System_printf("oUART\r\n");
            int_fast32_t ret = check_UART();
            /* Clear the event */
            Util_clearEvent(&Collector_events, UART_COLLECTOR_OPEN);
        }

    The readCallback function is provided in my first post. Note that I've also tried using LCD_WRITE_STRING() instead of write_UART in the callback function, doesnt work either. Besides, I still got no clue why and were exactly the code crashes...

  • Quick update of the callback function, I decided to rewrite the code to trigger an event instead of directly calling the disassociate and remove functions.

    void readCmdCallback(UART_Handle handle, void *buffer, size_t num)
    {
        if (rx_input == '\n')
        {
            output[index] = '\n';
            /* Echo the read bytes until \n is found */
            UART_write(hUart, &output, index++);
            index = 0;
    
            /* Trigger a factory reset if the cmd starts with 1 */
            if(output[0] == '1')
            {
    //            const char reset_note[] = "FRe\r\n";
    //            UART_write(hUart, &reset_note, 5);
                Csf_factoryReset();
            }
            /* Set an event to kick a sensor if the cmd starts with 2 */
            if(output[0] == '2')
            {
                //LCD_WRITE_STRING("before", 3);
                /* If short address is not 0 and not invalid initiate kicking */
                if(UART_getShortAddr(output) && UART_getShortAddr(output) != CSF_INVALID_SHORT_ADDR)
                {
                    /* parse short address from the UART message and set the sensor kick event */
                    disSens_shortAddr = UART_getShortAddr(output);
                    Util_setEvent(&Collector_events, COLLECTOR_KICK_SENSOR_EVT);
                }
                //LCD_WRITE_STRING("after", 3);
            }
            ClearBuffer(output);
        }
        else if(rx_input == '\r')
        {
            output[index] = '\r';
            index++;
        }
        else
        {
            output[index] = rx_input;
            index++;
        }
        UART_read(hUart, &rx_input, 1);
    }

    Is the UART_read at the end ok, or can this cause a stack overflow?!

    EDIT: I noticed that if after some time I hit the "pause" button in debug mode I see that the code is pending here in the while loop, but only if the condition output[0] == '2' is met...

    void Main_assertHandler(uint8_t assertReason)
    {
        Main_assertReason = assertReason;
    
    #if defined(RESET_ASSERT)
        Csf_assertInd(assertReason);
    
        /* Pull the plug and start over */
        SysCtrlSystemReset();
    #else
        Hwi_disable();
        while(1)
        {
            /* Put you code here to do something if in assert */
        }
    #endif
    }

  • You should not be trying a UART_read inside of a readCmdCallback.  I don't understand how check_UART can be used in this context either.

    Regards,
    Ryan

  • Ryan Brown1 said:
    I don't understand how check_UART can be used in this context either.

    This function is called once if a timer elapses at the start calling UART_read once initiating the "Receive Continuously" functionality (see below).

    Ryan Brown1 said:
    You should not be trying a UART_read inside of a readCmdCallback. 

    Using UART_read insinde the callback function allows me to read a number of bytes with unknown length. And in UARTCC26XX.h File Reference is written:

    After a successful read, RX remains on. UART_read() must be called again before FIFO goes full in order to avoid overflow. It is safe to call another UART_read() from the read callback, See Receive Continously use case below.


    To receive continuously I call UART_read in the callback. This works fine if I am not entering If(output[0] == '2'). In the later application the collector will receive UART msgs very rarely, however, I want the collector to react quickly. If you have a better idea to be able to react quickly on a UART string cmd with unknown length I will be thankful.

    Nevertheless, can you explain how I enter the Main_assertHandler()?

  • I recommend that you reference the CUI from the SIMPLELINK_CC13X2_26X2-SDK for instances of UART_read and UartReadCallback usage.  Hector has already assisted you in regards to Main_assertHandler: https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz/f/156/t/722216

    Regards,
    Ryan

  • Ryan Brown1 said:
    I recommend that you reference the CUI from the SIMPLELINK_CC13X2_26X2-SDK for instances of UART_read and UartReadCallback usage. 

    I am sorry, but I dont understand what you exactly mean by this. I dont know what you mean with CUI. If you are referring to the uartecho example, I've been through this and it works fine using UART_read within the callback function. I also went through the API documentation it does encourage to use uart_read within the callback function: There are no additional stack requirements for calling UART_read() within its own callback.


  • CUI stands for Common User Interface.  Although you use the CC13x0, not CC13x2, the UART drivers are shared and it is a good example of parsing incoming UART data.  Although I do understand what the API documentation states: http://software-dl.ti.com/dsps/dsps_public_sw/sdo_sb/targetcontent/tirtos/2_20_00_06/exports/tirtos_full_2_20_00_06/products/tidrivers_cc13xx_cc26xx_2_20_00_08/docs/doxygen/html/_u_a_r_t_c_c26_x_x_8h.html 

    Regards,
    Ryan

  • Hey Ryan,

    this might be an unsatisfying answer but on Friday evening the code worked although I have no idea how I made it work. All changes I made in the afternoon weren't altered and although the application crashed sometimes, after using the debug-mode once, the system was stable even after closing debug mode and even after re-flashing the board with the same software. However, I want to share some insights I have made, though some claims are based on speculation on my side.

    1. If you have an application where you dont know when a UART message arrives and you dont know the length and you wanna react quickly use UART_read with callback mode. Read only 1 byte and call uart_read again within the callback. You can also close UART_read after receiving some character you assigned for "end of string" to know when to close, i.e. \n or \r would be an idea. However, by doing this you should call UART_read once in a while checking for pending bytes (not sure here if the UART driver stores the incoming TX bytes in a FIFO even if UART_read_close was called before check the API). Another approach to quickly react on incoming bytes would be a combined HwI where the source of the message is providing a signal causing the HwI to be triggered, notifying the user to call UART_read.

    2. Within the read callback function dont make excessive use of UART_write. I am not sure if the combination of UART_write and UART_read within the callback function can cause issues (I actually do have one UART_write and one UART_read call), however, I outsourced the issue by setting events applying the Util_setEvent() function.

    I hope I can help others with this approach, however, note that my understanding is not well enough and I dont have too much experience with the TI-RTOS UART driver but if questions occur check the link first, ryan posted above (not valid for all boards), it helped me a lot to understand some parts of the UART API.

    Thanks for help Ryan.

    Slev1n