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: How to toggle BT peripheral mode

Part Number:

Dear TI members,

As far as I understand:

The APIs BLEAppUtil_advStart() and BLEAppUtil_advStop() can be used to start and stop peripheral, respectively.

My question is:

When I invoked BLEAppUtil_advStop() to stop peripheral, the system would stock in abort() loop.

Here's the call stack:

So, how can I actually toggle (start/stop) peripheral mode?

Should we have to do extra settings/configurations before using BLEAppUtil_advStart() and BLEAppUtil_advStop()? 

The table below is my current building environment:

Software

Version

Code Composer Studio

12.4.0.202306011800

SimpleLink SDK

7.20.1.10

XDCtools

3.62.1.16_core

  • Hello Zach,

    Thanks for reaching out.

    Could you please point out how (where in the code) are you calling the BLEAppUtil_advStart() and BLEAppUtil_advStop() functions?

    For example, this is how it is being used inside the app_peripheral.c in Peripheral_GAPConnEventHandler() to enable advertising until the amount of new formed connections has been reached.

    oid Peripheral_GAPConnEventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData)
    {
        switch(event)
        {
            case BLEAPPUTIL_LINK_ESTABLISHED_EVENT:
            {
                /* Check if we reach the maximum allowed number of connections */
                if(linkDB_NumActive() < linkDB_NumConns())
                {
                    /* Start advertising since there is room for more connections */
                    BLEAppUtil_advStart(peripheralAdvHandle_1, &advSetStartParamsSet_1);
                }
                else
                {
                    /* Stop advertising since there is no room for more connections */
                    BLEAppUtil_advStop(peripheralAdvHandle_1);
                }
                break;
            }
    

    BR,

    David.

  • Hi David,

        Our implementation receives a set of commands from UART and then invokes specific functions based on those commands.

    Regarding this problem, the function 'toggle_bt_peripheral()' is performed when the relevant command arrives.

    This function toggles the peripheral mode:

    bStatus_t toggle_bt_peripheral(int on) {
        if (on && !is_bt_peripheral_enable) {  // When peripheral mode is disabled
            return BLEAppUtil_advStart(peripheralAdvHandle_1, &advSetStartParamsSet_1);
        } else if (!on && is_bt_peripheral_enable) {  // When peripheral mode is enabled
            return BLEAppUtil_advStop(peripheralAdvHandle_1);
        }
        return SUCCESS;
    }

    However, each time the system invokes toggle_bt_peripheral(), it gets stuck in an abort() loop.

    Best regards,

    Zach

    bStatus_t toggle_bt_peripheral(int on) {
        if (on && !is_bt_peripheral_enable) {  // When peripheral mode is disabled
            return BLEAppUtil_advStart(peripheralAdvHandle_1, &advSetStartParamsSet_1);
        } else if (!on && is_bt_peripheral_enable) {  // When peripheral mode is enabled
            return BLEAppUtil_advStop(peripheralAdvHandle_1);
        }
        return SUCCESS;
    }

  • Hello Zach,

    Understood.

    Where/How are you calling the toggle_bt_peripheral() function? Is it inside the UART callback function?

    Based on your next answer, I would suggest using BLEAppUtil_invokeFunctionNoData() to invoke the toggling function. This function receives a callback and data and switches the context in order to call the callback from the BLE App Util module context.

    BR,

    David.

  • Hi David,

        First, we create a thread to read data from the UART:

    void UART_read_task(void)
    {
        bStatus_t status_read  = UART2_STATUS_SUCCESS;
        bStatus_t status_write = UART2_STATUS_SUCCESS;
        bStatus_t status_send  = UART2_STATUS_SUCCESS;
        uint16 buffer_len   = 128;
        // size_t bytesRead;
        size_t bytesWrite;
        // int8 ret            = 0;
        struct ble_pdu *pdu;
        char success[]      = "SUCCESS: Sent data to App";
        char error[]        = "ERROR: Failed to send data to App!!";
        char *buf;
        int retry_count     = 0;
        if (wnc_uart_init() < 0) {
            WNC_DBG("UART INIT failed");
            return;
        }
    
        while (1) {
            pdu = (struct ble_pdu *) malloc(sizeof(struct ble_pdu));
            if (pdu == NULL) {
                WNC_DBG("malloc failed");
                retry_count++;
                if ( retry_count > 10 ) {
                    WNC_DBG("HW RESET......");
                    SystemReset();
                }
                continue;
            }
    retry:
            memset(pdu, 0, sizeof(struct ble_pdu));
    
            if (UART2_read(uartHandle, pdu->buf, sizeof(pdu->buf), &(pdu->len)) != UART2_STATUS_SUCCESS) {
                WNC_DBG("UART2_read() failed: status_read:%d, bytesRead: %d", status_read, pdu->len);
                goto retry;
            }
    
            if ( (pdu->buf[0] == 'O') || (pdu->buf[0] == 'C') ) {
                if ( pdu->buf[7] == 0x00 && ble_cmd(pdu->buf) == 0) {
                        goto retry;
                }
            }
            else if (pdu->buf[0] == 'S' && pdu->buf[1] == 'T')
            {
                /* Got "Stop!" to terminate heater control
                 * send something like below in sdx62 adb shell
                 * printf "\x53\x54\x4F\x50\x00" > /dev/ttyMSM1
                 */
                Terminate_heat_control();
            }
            else if (pdu->buf[0] == 'F' && pdu->buf[1] == 'O')
            {
                // Close watchdog
                Watchdog_close(watchdogHandle);
                WNC_DBG("Turn Off HW watchdog !");
                GPIO_write(CONFIG_GPIO_HEATER, 0);
                WNC_DBG("Turn Off Heater !");
            }
            else if (pdu->buf[0] == 'B' && pdu->buf[1] == 'T')
            {
                parsing_bt_cmd(pdu->buf);
    
                goto retry;
            }
    
            /* If you want to send temperature to CC2340 manually */
    #ifdef SEND_TEMPERATURE
            else if ( pdu->buf[0] == 'T' && pdu->buf[1] == 'E' ) {
                temperature_tmp = atoi(pdu->buf + 2);
            }
            /*
             * send something like below in sdx62 adb shell
             * e.g. "TE-25" means -25 degree C
             * printf "\x54\x45\x2D\x32\x35\x00" > /dev/ttyMSM1
             */
    #endif
    
            else if ( pdu->buf[0] == 'I' && pdu->buf[1] == 'D' ) {
    //            printf "\x49\x44\x00" > /dev/ttyMSM1
    //            SendIDtoSDX62();
                char BTID[10];
                memcpy(BTID, advSetInitParamsSet_1.scanRespData + 2, 10 * sizeof(char));
                WNC_DBG("BTID : %d", sizeof(*BTID));
    
                UART2_write(uartHandle, BTID, sizeof(BTID), &bytesWrite);
            }
    
            BLEAppUtil_invokeFunction((InvokeFromBLEAppUtilContext_t)SendUARTOverBLE, (char*)pdu);
        }
    }
    

    When the data matches our built-in commands, it triggers the related behavior. In the context of this issue, toggle_bt_peripheral() will be invoked.

    By the way, should I use BLEAppUtil_invokeFunction() instead of BLEAppUtil_invokeFunctionNoData() ?

    Since the function takes one argument.

    Thanks,

    Zach

  • Hi David,

    Update information:

    Below is a pseudo code :

    static int set_bt_rf_status(int flag) {
    
        int status = 0;
        int tmp;
    
    #if defined( HOST_CONFIG ) && ( HOST_CONFIG & ( PERIPHERAL_CFG ) )
        tmp = flag & 0x4;
        if ((status = BLEAppUtil_invokeFunction((InvokeFromBLEAppUtilContext_t)toggle_bt_peripheral, (char*)&tmp)) != SUCCESS) {
            return status;
        }
    #endif
    
        return status;
    }

    Is my understanding correct?

    Thanks,

    Zach

  • Hello Zach,

    If your variable is a global one, then you can use the BLEAppUtil_invokeFunctionNoData().

    After trying this (not sure if it is the first or second code-snippet), do you still get the error?

    BR,

    David.

  • Hi David,

        Thanks for your response. The problem has been solved, but I'm also curious about the mechanism behind it.

    Can you explain why this solution works or where can I find related documentation regarding the TI BLE Stack?

    Many thanks,

    Zach

  • Hello Zach,

    Sure thing. This function changes the context in order to call the callback function (toggle_bt_peripheral in your case) from the BLE App Util module context where you can actually use BLEAppUtil_advStart() and BLEAppUtil_advStop() functions.

    Hope this helps.

    David.