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.

CC2340R5: call sleep() then call UART2_open() can not open UART

Part Number: CC2340R5

CCS version : 12.7.0

Arm compiler version : 3.2.2LTS

Syscfg version : 1.20.0


I tested the UART function every minute in the basic_ble project of SDK: 7.40.00.64. When I open the UART for the first time, it's normal, then I also called UART2_close() to close it, but as long as I called sleep() or usleep(). As a result, my second call to UART2_open() failed. I used the Debug mode to check and found that object->state.opened in UART2_open() was set to true, resulting in return NULL, but I am sure that after I called UART2_close() , object->state.opened is set to false, but it will be set to true after calling sleep()。

I wrote the same Code to SDK: 7.10.00.35 and it doesn't happen.

Calling UART2_close() and calling sleep() are in different threads. Is it because it enters sleep() first, so UART2_close() is not actually executed successfully?

  • Hi,

    Calling UART2_close() and calling sleep() are in different threads. Is it because it enters sleep() first, so UART2_close() is not actually executed successfully?

    No, calling sleep should only put the device into low power mode if there are no other threads ready to run. In your case, it sounds like the UART thread is ready to run.

    When UART2_open is called, the UART driver notifies the Power driver that the UART is in use, so the Power driver will make sure to maintain the required power mode to ensure UART operates properly. When UART2_close is called, the UART driver notifies the Power driver that there is no more power dependency on UART.

    CCS version : 12.7.0

    I've noticed at least one other E2E post where using CCS 12.7 has caused unexpected behavior: https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1357887/cc2652r7-consecutive-builds-without-code-change-results-in-different-hex-files

    Can you try these tests and share the results:

    1. Run your same code, built from SDK 7.10 and CCS 12.7
    2. Run your same code, built from SDK 7.40 and previous CCS (that you originally used for SDK 7.10)\

    Thanks,
    Toby

  • Hello Toby,

    About the test you mentioned :

    (1)The 7.10.00.35 version I described in the article uses CSS 12.7.0 for debugging, but this does not happen.


    (2)When I used SDK 7.10 version before, the CCS version I used was 12.2. However, when I used CCS 12.2 to execute SDK 7.40, it would get stuck in while(1) about RCL. At that time, I asked related questions on the forum, and the engineer The reply given to me was to update the CCS version, then I updated CCS to 12.7, so I cannot provide the test results of SDK 7.40 and CCS 12.2.

    In addition, I found during testing that the above situation occurs when I call sleep(1), but if I change it to usleep(50000), it will succeed when I open UART2_open for the second time, and then I try to change it to usleep(100000). Still won't be able to open

  • Thanks for confirming and more details.

    So this issue does seem related to the SDK version.

    Can you share some code snippets of how you are setting up these two threads (1. thread calling UART2_open/close; 2. thread calling sleep)?

    Does the issue happen 100% of the time? Or are there some times where the UART2_close --> UART2_open works ok?

    Thanks,
    Toby

  • (1)I call sleep(1) in App_StackInitDoneHandler() of app.main.c, and for UART, I create a separate thread specifically for UART use.

    (2)happens every time

  • Got it.

    I'll take a look into this and update here within 3 business days.

  • OK , I also found some clues here

    I found that such a situation can also be found in the UART's own thread. It seems that it does not necessarily happen when a different thread calls sleep(), and I tested that this situation will occur as long as the setting exceeds usleep(16000), but I have other Setting sleep(1) locally will not affect it, which is quite strange. It may be triggered or certain conditions are reached before UART2_open() cannot be opened, and I use single-stepping UART2_open() to view the inside of the function. , it seems that the reason is that UART determines object->state.opened == 1

  • Hi Ryan,

    I looked further into this, but unable to reproduce the issue.

    I am using 7.40 SDK as well.

    /*
     * Copyright (c) 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.
     */
    
    /*
     *  ======== uart2echo.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"
    
    /*
     *  ======== mainThread ========
     */
    void *mainThread(void *arg0)
    {
        char input;
        const char echoPrompt[] = "Echoing characters:\r\n";
        UART2_Handle uart;
        UART2_Params uartParams;
        size_t bytesRead;
        size_t bytesWritten = 0;
        uint32_t status     = UART2_STATUS_SUCCESS;
    
        /* Call driver init functions */
        GPIO_init();
    
        /* Configure the LED pin */
        GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    
        /* Create a UART where the default read and write mode is BLOCKING */
        UART2_Params_init(&uartParams);
        uartParams.baudRate = 115200;
    
        uart = UART2_open(CONFIG_UART2_0, &uartParams);
    
        if (uart == NULL)
        {
            /* UART2_open() failed */
            while (1) {}
        }
    
        /* Turn on user LED to indicate successful initialization */
        GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON);
    
        UART2_write(uart, echoPrompt, sizeof(echoPrompt), &bytesWritten);
    
        /* Loop forever echoing */
        while (1)
        {
            bytesRead = 0;
            while (bytesRead == 0)
            {
                status = UART2_read(uart, &input, 1, &bytesRead);
    
                if (status != UART2_STATUS_SUCCESS)
                {
                    /* UART2_read() failed */
                    while (1) {}
                }
            }
    
            bytesWritten = 0;
            while (bytesWritten == 0)
            {
                status = UART2_write(uart, &input, 1, &bytesWritten);
    
                if (status != UART2_STATUS_SUCCESS)
                {
                    /* UART2_write() failed */
                    while (1) {}
                }
            }
    
            UART2_close(uart);
    
    //        usleep(16000); // working ok
    //        usleep(17000); // working ok
    //        usleep(30000);
            sleep(1);   // working ok
    
            uart = UART2_open(CONFIG_UART2_0, &uartParams);
            if (uart == 0)
            {
                while (1);
            }
        }
    }
    

    ^ I used the above code in the default uartecho example (C:\ti\simplelink_lowpower_f3_sdk_7_40_00_64\examples\rtos\LP_EM_CC2340R5\drivers\uart2echo)

    Can you try this on your end to see if you can reproduce my results? (Successful, repeated UART2_open and UART2_close).

    Thanks,
    Toby

  • Hi Toby,


    I use uart2echo and add the Code you provided and modify it slightly (because I use QFN-24's CC2340R5), UART2_open() can run successfully, but the project I am currently using uses basic_ble_LP as the base project

    But as I mentioned above, it seems that not every sleep() will affect UART2_open(), because I have used sleep(1) in many places, but it will not affect UART2_open()

  • How does your UART thread work?

    Is there any possibility that the UART2_open is being inadvertently called twice in a row?

    One possible debug step:

    1. Introduce two counters, openCount and closeCount. Any access to these counters must be in a critical section.
    2. After any call to UART2_open, increment openCount.
    3. After any call to UART2_close, increment closeCount.
    4. When the issue occurs, compare values of openCount and closeCount.
    5. In an ideal case, after any UART2_close, we expect openCount == closeCount. If there is a difference, this could indicate a double call to UART2_open
  • I have described above how my UART thread is created and how it works,

    The code written in my uartthread is just the picture, so there is no other place to open UART2_open(), and if according to your assumption, there are other places to repeatedly open UART2_open(), then how to explain the use of usleep(16000) can it work normally? This doesn’t make sense

  • What does "mainThreadUart" look like?

    Are you using UART only one time, then closing it? (during app initialization, as indicated by "App_StackInitDoneHandler") 
    Or is App_StackInitDoneHandler called multiple times?

    My assumption was that mainThreadUart would access the UART (open then read/write), then when it is done, close UART.
    And that this happens more than once.