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/CC2640R2F: BLE stack hang or crash

Part Number: CC2640R2F
Other Parts Discussed in Thread: BLE-STACK, , CC2640

Tool/software: TI-RTOS

Hi All,

I am using BLE Stack 3.1.1 with CC2640R2 SDK 1.50.00.58 in my project.

I am clearing the watchdog from my application.

i am using off-chip OAD.

During the OAD randomly the BLE stack hang so no BLE activity or BLE Crash which creates watchdog reset.

This is a random behaviour when we do the stress test.

could you please guide me how to find the issue or fix?

Or please share if you have any known issues like this.

Thanks

with Regards,

Thangaraj.P

  • Hi,

    I have not seen this issue before. When it hangs, does it go into the exception handler? Can you try decoding the exception following the steps here:
    software-dl.ti.com/.../cpu_exceptions.html

    Best wishes
  • Hello,

    Can you additionally verify that the device is not out of heap memory when the issue occurs, see the debugging section of the BLE-Stack User's guide that Zahid linked you to.

    Update: Also be sure that you are accounting for flash erase time when calculating your watchdog timeout.

  • Hi ,

    i checked heap is available.
    I Just downloading the from Dongle to cc2640R2F. But we are not writing to external flash. Just to rule out the SPI and external flash driver issue. only watchdog is running from application.
    Its a random behavior.
    1 out of 10 times the watchdog reset is happening.Its not reproducing always.
    so some how in between the FOTA downloading the stack hangs which causes wachdog reset.

    Please provide any suggestion what needs to be checked at stack side.

  • Hi ,

    Any Update on this
  • Have you profiled how long the user application is blocked for while running an OAD? You can profile this using a GPIO toggle.

    Since OAD is flooding the stack with messages there is likely a lot of processing to be done.

    I would find out the time for which the user application is blocked at make your watchdog timeout that value + ~25% for safety.

  • Even if we are running the OAD also watchdog feeding is happening.
    sometimes when the block send by central is not reaching to OAD call back(our assumption is stack hang) but we have our application SW timer which will reset back to noramal application flow. But this tinme teh SW clock is not expired so we are not able to reume our application. But wacthdog feeding is happening backaround.
  • Hi,

    The actual Problem is when we disconnect from central device we are nor getting the GAPROLE_WAITING or GAPROLE_WAITING_AFTER_TIMEOUT event from the stack. we have a timer to terminate the connection in case if we miss the events. ut during this scenario even the clock also not triggering. whats the link between the stack an dthe util clock. ?
    This is a very random behaviour.

    we need to fix this is very high priority.

    kindly support.

    Thanks.
  • Hello,

    Clock timeout handlers are scheduled based on SWIs.

    If you are not receiving a clock timer expiry (assuming the clock is setup correctly) then it is likely that the user application is blocked by a critical section in the stack.

    Please provide steps to reproduce on a TI LaunchPad based on a SDK sample application with the minimum number of modifications done.

  • No need to change anything . If you connect and disconnect your peripheral from central in a loop for more than 4 to 5 hours then GAPROLE_WAITING or GAPROLE_WAITING_AFTER_TIMEOUT will not get to application . so that advertsing will stop. Only reset will recover the device.
  • The issue takes more than 4 hours to reproduce?
    How frequently are the devices connected/reconnected? More information is needed.
  • full_log.zipHi,

    Its a random behaviour. some times within 30 mins some times more than 4 hours.

    Every 2sec we are connecting and disconnecting the BLE.

    Here i am attaching sniffer log. . we gave the disconnect from central. But its not received to our Application . The end of the log is during this issue. After this no advertisement and also Application timers also not triggering. from the log end it shoes some non connectable adv and error.

    Please analyze the log and Update that what went wrong. Also how can we recover the system in case if this issue happenes.

  • Hi,

    Any input on this?
  • Hi All,

    This is a blocker issue for us.

    kindly provide your input asap.

  • Hello,

    At the time of the lock up is are there any heap allocation failures (note I asked this before, but specifically I want to be sure that you have measured at the time of the failure). Are there any other failures observed when scanning the ROV. What is the state of the GAP Role Task, what is its callstacks. Has an exception or abort occurred?

    You mention that your clock is not firing, can you determine if SWIs are disabled at this time?

  • Hi,
    No heap failure at the moment. GapRole state is connected . No exception or abort.
    yes. SWIs are enabled at this time. but one query here is even ifs disabled also when enabling the SWI the clock should trigger the interrupt. Am i right?
    One more thing is basically the system is not crashed . background my application is running. because of that watchdog is running and no reset.
    only during that time GAPROLE_WAITING event not reached to application. the same time the application supervision timer is also not expired.

    During that time if you see the log the device giving NON_CONNECTABLE Advertising suddenly.
    you can have the better understanding what could make the system to give NON_CONNECTABLE Advertising suddenly.

    may be this info will be helpful for your support

    Thanks.

    Please feedback asap.

    Thangaraj.P
  • Hi Thangaraj,

    As discussed, the capture shows that the ADV_NONCONN_IND are coming from a device with a different address type, specifically a Random address (private)  which is not the device that you are using, (public address). See screencap below

    The best case would be to run the heap manager metrics (HEAPMGR_METRICS) on the connect/disconnect test bed and observer the heapmgrMemFail variable at the time of failure. If you wish to assert during a heap failure you can also use MEM_ALLOC_ASSERT (note this required a HAL Assert handler to be plugged).

    Additionally, it would be helpful to consider porting the test to TI LaunchPads. If it can be reproduced in this form, we can easily aide in debugging.

  • /******************************************************************************
    
     @file       simple_peripheral.c
    
     @brief This file contains the Simple Peripheral sample application for use
            with the CC2650 Bluetooth Low Energy Protocol Stack.
    
     Group: CMCU, SCS
     Target Device: CC2640R2
    
     ******************************************************************************
     
     Copyright (c) 2013-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.
    
     ******************************************************************************
     Release Name: simplelink_cc2640r2_sdk_01_50_00_58
     Release Date: 2017-10-17 18:09:51
     *****************************************************************************/
    
    /*********************************************************************
     * INCLUDES
     */
    #include <string.h>
    
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/knl/Event.h>
    #include <ti/sysbios/knl/Queue.h>
    #include <ti/display/Display.h>
    
    #if defined( USE_FPGA ) || defined( DEBUG_SW_TRACE )
    #include <driverlib/ioc.h>
    #endif // USE_FPGA | DEBUG_SW_TRACE
    
    #include <icall.h>
    #include "util.h"
    /* This Header file contains all BLE API and icall structure definition */
    #include "icall_ble_api.h"
    
    #include "devinfoservice.h"
    #include "simple_gatt_profile.h"
    #include "ll_common.h"
    
    #include "peripheral.h"
    
    #ifdef USE_RCOSC
    #include "rcosc_calibration.h"
    #endif //USE_RCOSC
    
    #include "board_key.h"
    
    #include "board.h"
    #include <ti/sysbios/hal/Hwi.h>
    #include "simple_peripheral.h"
    #include "ti/drivers/Watchdog.h"
    /*********************************************************************
     * CONSTANTS
     */
    static Watchdog_Handle watchdogHandle;   /**< variable to store the handle of watchdogTimer0*/
    /* functions declaration*/
    static void WatchdogTimerCallback(UArg a0);
    // Advertising interval when device is discoverable (units of 625us, 160=100ms)
    #define DEFAULT_ADVERTISING_INTERVAL          160
    
    // General discoverable mode: advertise indefinitely
    #define DEFAULT_DISCOVERABLE_MODE             GAP_ADTYPE_FLAGS_GENERAL
    
    // Minimum connection interval (units of 1.25ms, 80=100ms) for automatic
    // parameter update request
    #define DEFAULT_DESIRED_MIN_CONN_INTERVAL     80
    
    // Maximum connection interval (units of 1.25ms, 800=1000ms) for automatic
    // parameter update request
    #define DEFAULT_DESIRED_MAX_CONN_INTERVAL     800
    
    // Slave latency to use for automatic parameter update request
    #define DEFAULT_DESIRED_SLAVE_LATENCY         0
    
    // Supervision timeout value (units of 10ms, 1000=10s) for automatic parameter
    // update request
    #define DEFAULT_DESIRED_CONN_TIMEOUT          1000
    
    // After the connection is formed, the peripheral waits until the central
    // device asks for its preferred connection parameters
    #define DEFAULT_ENABLE_UPDATE_REQUEST         GAPROLE_LINK_PARAM_UPDATE_WAIT_REMOTE_PARAMS
    
    // Connection Pause Peripheral time value (in seconds)
    #define DEFAULT_CONN_PAUSE_PERIPHERAL         6
    
    // How often to perform periodic event (in msec)
    #define SBP_PERIODIC_EVT_PERIOD               10000
    
    // Application specific event ID for HCI Connection Event End Events
    #define SBP_HCI_CONN_EVT_END_EVT              0x0001
    
    // Type of Display to open
    #if !defined(Display_DISABLE_ALL)
      #if defined(BOARD_DISPLAY_USE_LCD) && (BOARD_DISPLAY_USE_LCD!=0)
        #define SBP_DISPLAY_TYPE Display_Type_LCD
      #elif defined (BOARD_DISPLAY_USE_UART) && (BOARD_DISPLAY_USE_UART!=0)
        #define SBP_DISPLAY_TYPE Display_Type_UART
      #else // !BOARD_DISPLAY_USE_LCD && !BOARD_DISPLAY_USE_UART
        #define SBP_DISPLAY_TYPE 0 // Option not supported
      #endif // BOARD_DISPLAY_USE_LCD && BOARD_DISPLAY_USE_UART
    #else // BOARD_DISPLAY_USE_LCD && BOARD_DISPLAY_USE_UART
      #define SBP_DISPLAY_TYPE 0 // No Display
    #endif // !Display_DISABLE_ALL
    
    // Task configuration
    #define SBP_TASK_PRIORITY                     1
    
    #ifndef SBP_TASK_STACK_SIZE
    #define SBP_TASK_STACK_SIZE                   644
    #endif
    
    // Application events
    #define SBP_STATE_CHANGE_EVT                  0x0001
    #define SBP_CHAR_CHANGE_EVT                   0x0002
    #define SBP_PAIRING_STATE_EVT                 0x0004
    #define SBP_PASSCODE_NEEDED_EVT               0x0008
    #define SBP_WATCHDOG_FEED_EVT                 0x0010
    
    
    // Internal Events for RTOS application
    #define SBP_ICALL_EVT                         ICALL_MSG_EVENT_ID // Event_Id_31
    #define SBP_QUEUE_EVT                         UTIL_QUEUE_EVENT_ID // Event_Id_30
    #define SBP_PERIODIC_EVT                      Event_Id_00
    
    // Bitwise OR of all events to pend on
    #define SBP_ALL_EVENTS                        (SBP_ICALL_EVT        | \
                                                   SBP_QUEUE_EVT        | \
                                                   SBP_PERIODIC_EVT)
    
    /*********************************************************************
     * TYPEDEFS
     */
    
    // App event passed from profiles.
    typedef struct
    {
      appEvtHdr_t hdr;  // event header.
      uint8_t *pData;  // event data
    } sbpEvt_t;
    
    /*********************************************************************
     * GLOBAL VARIABLES
     */
    
    // Display Interface
    Display_Handle dispHandle = NULL;
    
    /*********************************************************************
     * LOCAL VARIABLES
     */
    
    // Entity ID globally used to check for source and/or destination of messages
    static ICall_EntityID selfEntity;
    
    // Event globally used to post local events and pend on system and
    // local events.
    static ICall_SyncHandle syncEvent;
    
    // Clock instances for internal periodic events.
    static Clock_Struct periodicClock;
    
    // Queue object used for app messages
    static Queue_Struct appMsg;
    static Queue_Handle appMsgQueue;
    
    // Task configuration
    Task_Struct sbpTask;
    Char sbpTaskStack[SBP_TASK_STACK_SIZE];
    
    // Scan response data (max size = 31 bytes)
    static uint8_t scanRspData[] =
    {
      // complete name
      0x14,   // length of this data
      GAP_ADTYPE_LOCAL_NAME_COMPLETE,
      'S',
      'i',
      'm',
      'p',
      'l',
      'e',
      'B',
      'L',
      'E',
      'P',
      'e',
      'r',
      'i',
      'p',
      'h',
      'e',
      'r',
      'a',
      'l',
    
      // connection interval range
      0x05,   // length of this data
      GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
      LO_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL),   // 100ms
      HI_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL),
      LO_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL),   // 1s
      HI_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL),
    
      // Tx power level
      0x02,   // length of this data
      GAP_ADTYPE_POWER_LEVEL,
      0       // 0dBm
    };
    
    // Advertisement data (max size = 31 bytes, though this is
    // best kept short to conserve power while advertising)
    static uint8_t advertData[] =
    {
      // Flags: this field sets the device to use general discoverable
      // mode (advertises indefinitely) instead of general
      // discoverable mode (advertise for 30 seconds at a time)
      0x02,   // length of this data
      GAP_ADTYPE_FLAGS,
      DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
    
      // service UUID, to notify central devices what services are included
      // in this peripheral
      0x03,   // length of this data
      GAP_ADTYPE_16BIT_MORE,      // some of the UUID's, but not all
      LO_UINT16(SIMPLEPROFILE_SERV_UUID),
      HI_UINT16(SIMPLEPROFILE_SERV_UUID)
    };
    
    // GAP GATT Attributes
    static uint8_t attDeviceName[GAP_DEVICE_NAME_LEN] = "Simple Peripheral";
    
    // Globals used for ATT Response retransmission
    static gattMsgEvent_t *pAttRsp = NULL;
    static uint8_t rspTxRetry = 0;
    
    /*********************************************************************
     * LOCAL FUNCTIONS
     */
    
    static void SimpleBLEPeripheral_init( void );
    static void SimpleBLEPeripheral_taskFxn(UArg a0, UArg a1);
    
    static uint8_t SimpleBLEPeripheral_processStackMsg(ICall_Hdr *pMsg);
    static uint8_t SimpleBLEPeripheral_processGATTMsg(gattMsgEvent_t *pMsg);
    static void SimpleBLEPeripheral_processAppMsg(sbpEvt_t *pMsg);
    static void SimpleBLEPeripheral_processStateChangeEvt(gaprole_States_t newState);
    static void SimpleBLEPeripheral_processCharValueChangeEvt(uint8_t paramID);
    static void SimpleBLEPeripheral_performPeriodicTask(void);
    static void SimpleBLEPeripheral_clockHandler(UArg arg);
    
    static void SimpleBLEPeripheral_sendAttRsp(void);
    static void SimpleBLEPeripheral_freeAttRsp(uint8_t status);
    
    static void SimpleBLEPeripheral_passcodeCB(uint8_t *deviceAddr, uint16_t connHandle,
                                               uint8_t uiInputs, uint8_t uiOutputs);
    static void SimpleBLEPeripheral_pairStateCB(uint16_t connHandle, uint8_t state,
                                             uint8_t status);
    static void SimpleBLEPeripheral_processPairState(uint8_t state, uint8_t status);
    static void SimpleBLEPeripheral_processPasscode(uint8_t uiOutputs);
    
    static void SimpleBLEPeripheral_stateChangeCB(gaprole_States_t newState);
    static void SimpleBLEPeripheral_charValueChangeCB(uint8_t paramID);
    static uint8_t SimpleBLEPeripheral_enqueueMsg(uint8_t event, uint8_t state,
                                                  uint8_t *pData);
    static uint8_t watchdogClearFlag = FALSE;
    
    /*********************************************************************
     * EXTERN FUNCTIONS
     */
    extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);
    
    /*********************************************************************
     * PROFILE CALLBACKS
     */
    
    // Peripheral GAPRole Callbacks
    static gapRolesCBs_t SimpleBLEPeripheral_gapRoleCBs =
    {
      SimpleBLEPeripheral_stateChangeCB     // GAPRole State Change Callbacks
    };
    
    // GAP Bond Manager Callbacks
    // These are set to NULL since they are not needed. The application
    // is set up to only perform justworks pairing.
    static gapBondCBs_t simpleBLEPeripheral_BondMgrCBs =
    {
      (pfnPasscodeCB_t) SimpleBLEPeripheral_passcodeCB, // Passcode callback
      SimpleBLEPeripheral_pairStateCB                   // Pairing / Bonding state Callback
    };
    
    // Simple GATT Profile Callbacks
    static simpleProfileCBs_t SimpleBLEPeripheral_simpleProfileCBs =
    {
      SimpleBLEPeripheral_charValueChangeCB // Simple GATT Characteristic value change callback
    };
    
    /*********************************************************************
     * PUBLIC FUNCTIONS
     */
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_createTask
     *
     * @brief   Task creation function for the Simple Peripheral.
     *
     * @param   None.
     *
     * @return  None.
     */
    void SimpleBLEPeripheral_createTask(void)
    {
      Task_Params taskParams;
    
      // Configure task
      Task_Params_init(&taskParams);
      taskParams.stack = sbpTaskStack;
      taskParams.stackSize = SBP_TASK_STACK_SIZE;
      taskParams.priority = SBP_TASK_PRIORITY;
    
      Task_construct(&sbpTask, SimpleBLEPeripheral_taskFxn, &taskParams, NULL);
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_init
     *
     * @brief   Called during initialization and contains application
     *          specific initialization (ie. hardware initialization/setup,
     *          table initialization, power up notification, etc), and
     *          profile initialization/setup.
     *
     * @param   None.
     *
     * @return  None.
     */
    static void SimpleBLEPeripheral_init(void)
    {
      // ******************************************************************
      // N0 STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp
      // ******************************************************************
      // Register the current thread as an ICall dispatcher application
      // so that the application can send and receive messages.
      ICall_registerApp(&selfEntity, &syncEvent);
    
    #ifdef USE_RCOSC
      RCOSC_enableCalibration();
    #endif // USE_RCOSC
    
    #if defined( USE_FPGA )
      // configure RF Core SMI Data Link
      IOCPortConfigureSet(IOID_12, IOC_PORT_RFC_GPO0, IOC_STD_OUTPUT);
      IOCPortConfigureSet(IOID_11, IOC_PORT_RFC_GPI0, IOC_STD_INPUT);
    
      // configure RF Core SMI Command Link
      IOCPortConfigureSet(IOID_10, IOC_IOCFG0_PORT_ID_RFC_SMI_CL_OUT, IOC_STD_OUTPUT);
      IOCPortConfigureSet(IOID_9, IOC_IOCFG0_PORT_ID_RFC_SMI_CL_IN, IOC_STD_INPUT);
    
      // configure RF Core tracer IO
      IOCPortConfigureSet(IOID_8, IOC_PORT_RFC_TRC, IOC_STD_OUTPUT);
    #else // !USE_FPGA
      #if defined( DEBUG_SW_TRACE )
        // configure RF Core tracer IO
        IOCPortConfigureSet(IOID_8, IOC_PORT_RFC_TRC, IOC_STD_OUTPUT | IOC_CURRENT_4MA | IOC_SLEW_ENABLE);
      #endif // DEBUG_SW_TRACE
    #endif // USE_FPGA
    
      // Create an RTOS queue for message from profile to be sent to app.
      appMsgQueue = Util_constructQueue(&appMsg);
    
      // Create one-shot clocks for internal periodic events.
      Util_constructClock(&periodicClock, SimpleBLEPeripheral_clockHandler,
                          SBP_PERIODIC_EVT_PERIOD, 0, false, SBP_PERIODIC_EVT);
    
      dispHandle = Display_open(SBP_DISPLAY_TYPE, NULL);
    
      // Set GAP Parameters: After a connection was established, delay in seconds
      // before sending when GAPRole_SetParameter(GAPROLE_PARAM_UPDATE_ENABLE,...)
      // uses GAPROLE_LINK_PARAM_UPDATE_INITIATE_BOTH_PARAMS or
      // GAPROLE_LINK_PARAM_UPDATE_INITIATE_APP_PARAMS
      // For current defaults, this has no effect.
      GAP_SetParamValue(TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL);
    
      // Setup the Peripheral GAPRole Profile. For more information see the User's
      // Guide:
      // http://software-dl.ti.com/lprf/sdg-latest/html/
      {
        // Device starts advertising upon initialization of GAP
        uint8_t initialAdvertEnable = TRUE;
    
        // By setting this to zero, the device will go into the waiting state after
        // being discoverable for 30.72 second, and will not being advertising again
        // until re-enabled by the application
        uint16_t advertOffTime = 0;
    
        uint8_t enableUpdateRequest = DEFAULT_ENABLE_UPDATE_REQUEST;
        uint16_t desiredMinInterval = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
        uint16_t desiredMaxInterval = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
        uint16_t desiredSlaveLatency = DEFAULT_DESIRED_SLAVE_LATENCY;
        uint16_t desiredConnTimeout = DEFAULT_DESIRED_CONN_TIMEOUT;
    
        // Set the Peripheral GAPRole Parameters
        GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
                             &initialAdvertEnable);
        GAPRole_SetParameter(GAPROLE_ADVERT_OFF_TIME, sizeof(uint16_t),
                             &advertOffTime);
    
        GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData),
                             scanRspData);
        GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);
    
        GAPRole_SetParameter(GAPROLE_PARAM_UPDATE_ENABLE, sizeof(uint8_t),
                             &enableUpdateRequest);
        GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16_t),
                             &desiredMinInterval);
        GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16_t),
                             &desiredMaxInterval);
        GAPRole_SetParameter(GAPROLE_SLAVE_LATENCY, sizeof(uint16_t),
                             &desiredSlaveLatency);
        GAPRole_SetParameter(GAPROLE_TIMEOUT_MULTIPLIER, sizeof(uint16_t),
                             &desiredConnTimeout);
      }
    
      // Set the Device Name characteristic in the GAP GATT Service
      // For more information, see the section in the User's Guide:
      // http://software-dl.ti.com/lprf/sdg-latest/html
      GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);
    
      // Set GAP Parameters to set the advertising interval
      // For more information, see the GAP section of the User's Guide:
      // http://software-dl.ti.com/lprf/sdg-latest/html
      {
        // Use the same interval for general and limited advertising.
        // Note that only general advertising will occur based on the above configuration
        uint16_t advInt = DEFAULT_ADVERTISING_INTERVAL;
    
        GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MIN, advInt);
        GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MAX, advInt);
        GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, advInt);
        GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, advInt);
      }
    
      // Setup the GAP Bond Manager. For more information see the section in the
      // User's Guide:
      // http://software-dl.ti.com/lprf/sdg-latest/html/
      {
        // Don't send a pairing request after connecting; the peer device must
        // initiate pairing
        uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
        // Use authenticated pairing: require passcode.
        uint8_t mitm = TRUE;
        // This device only has display capabilities. Therefore, it will display the
        // passcode during pairing. However, since the default passcode is being
        // used, there is no need to display anything.
        uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
        // Request bonding (storing long-term keys for re-encryption upon subsequent
        // connections without repairing)
        uint8_t bonding = TRUE;
    
        GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode);
        GAPBondMgr_SetParameter(GAPBOND_MITM_PROTECTION, sizeof(uint8_t), &mitm);
        GAPBondMgr_SetParameter(GAPBOND_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
        GAPBondMgr_SetParameter(GAPBOND_BONDING_ENABLED, sizeof(uint8_t), &bonding);
      }
    
      // Initialize GATT attributes
      GGS_AddService(GATT_ALL_SERVICES);           // GAP GATT Service
      GATTServApp_AddService(GATT_ALL_SERVICES);   // GATT Service
      DevInfo_AddService();                        // Device Information Service
      SimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile
    
      // Setup the SimpleProfile Characteristic Values
      // For more information, see the sections in the User's Guide:
      // http://software-dl.ti.com/lprf/sdg-latest/html/
      {
        uint8_t charValue1 = 1;
        uint8_t charValue2 = 2;
        uint8_t charValue3 = 3;
        uint8_t charValue4 = 4;
        uint8_t charValue5[SIMPLEPROFILE_CHAR5_LEN] = { 1, 2, 3, 4, 5 };
    
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR1, sizeof(uint8_t),
                                   &charValue1);
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR2, sizeof(uint8_t),
                                   &charValue2);
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR3, sizeof(uint8_t),
                                   &charValue3);
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, sizeof(uint8_t),
                                   &charValue4);
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR5, SIMPLEPROFILE_CHAR5_LEN,
                                   charValue5);
      }
    
      // Register callback with SimpleGATTprofile
      SimpleProfile_RegisterAppCBs(&SimpleBLEPeripheral_simpleProfileCBs);
    
      // Start the Device
      VOID GAPRole_StartDevice(&SimpleBLEPeripheral_gapRoleCBs);
    
      // Start Bond Manager and register callback
      VOID GAPBondMgr_Register(&simpleBLEPeripheral_BondMgrCBs);
    
      // Register with GAP for HCI/Host messages. This is needed to receive HCI
      // events. For more information, see the section in the User's Guide:
      // http://software-dl.ti.com/lprf/sdg-latest/html
      GAP_RegisterForMsgs(selfEntity);
    
      // Register for GATT local events and ATT Responses pending for transmission
      GATT_RegisterForMsgs(selfEntity);
    
      //Set default values for Data Length Extension
      {
        //Set initial values to maximum, RX is set to max. by default(251 octets, 2120us)
        #define APP_SUGGESTED_PDU_SIZE 251 //default is 27 octets(TX)
        #define APP_SUGGESTED_TX_TIME 2120 //default is 328us(TX)
    
        //This API is documented in hci.h
        //See the LE Data Length Extension section in the BLE-Stack User's Guide for information on using this command:
        //http://software-dl.ti.com/lprf/sdg-latest/html/cc2640/index.html
        //HCI_LE_WriteSuggestedDefaultDataLenCmd(APP_SUGGESTED_PDU_SIZE, APP_SUGGESTED_TX_TIME);
      }
    
    #if !defined (USE_LL_CONN_PARAM_UPDATE)
      // Get the currently set local supported LE features
      // The HCI will generate an HCI event that will get received in the main
      // loop
      HCI_LE_ReadLocalSupportedFeaturesCmd();
    #endif // !defined (USE_LL_CONN_PARAM_UPDATE)
       Watchdog_Params watchdogInitParams;
      Watchdog_init();
    
        /*Initialize the watchdog with configuration parameters see: comment in watchdog.h file*/
        Watchdog_Params_init(&watchdogInitParams);
    
        watchdogInitParams.callbackFxn    = (Watchdog_Callback)WatchdogTimerCallback;
        watchdogInitParams.debugStallMode = Watchdog_DEBUG_STALL_ON;
        watchdogInitParams.resetMode      = Watchdog_RESET_ON;
    
        watchdogHandle = Watchdog_open((unsigned int)Board_WATCHDOG0, &watchdogInitParams);
      Display_print0(dispHandle, 0, 0, "BLE Peripheral");
    }
    
    
    static void WatchdogTimerCallback(UArg a0)
    {
    	
    
        if(watchdogClearFlag == false)
        {
            Watchdog_clear(watchdogHandle);
            watchdogClearFlag = true;
            SimpleBLEPeripheral_enqueueMsg(SBP_WATCHDOG_FEED_EVT, 0, 0);
            
           
        }
    }
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_taskFxn
     *
     * @brief   Application task entry point for the Simple Peripheral.
     *
     * @param   a0, a1 - not used.
     *
     * @return  None.
     */
    static void SimpleBLEPeripheral_taskFxn(UArg a0, UArg a1)
    {
      // Initialize application
      SimpleBLEPeripheral_init();
    
      // Application main loop
      for (;;)
      {
        uint32_t events;
    
        // Waits for an event to be posted associated with the calling thread.
        // Note that an event associated with a thread is posted when a
        // message is queued to the message receive queue of the thread
        events = Event_pend(syncEvent, Event_Id_NONE, SBP_ALL_EVENTS,
                            ICALL_TIMEOUT_FOREVER);
    
        if (events)
        {
          ICall_EntityID dest;
          ICall_ServiceEnum src;
          ICall_HciExtEvt *pMsg = NULL;
    
          // Fetch any available messages that might have been sent from the stack
          if (ICall_fetchServiceMsg(&src, &dest,
                                    (void **)&pMsg) == ICALL_ERRNO_SUCCESS)
          {
            uint8 safeToDealloc = TRUE;
    
            if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == selfEntity))
            {
              ICall_Stack_Event *pEvt = (ICall_Stack_Event *)pMsg;
    
              // Check for BLE stack events first
              if (pEvt->signature == 0xffff)
              {
                // The GATT server might have returned a blePending as it was trying
                // to process an ATT Response. Now that we finished with this
                // connection event, let's try sending any remaining ATT Responses
                // on the next connection event.
                if (pEvt->event_flag & SBP_HCI_CONN_EVT_END_EVT)
                {
                  // Try to retransmit pending ATT Response (if any)
                  SimpleBLEPeripheral_sendAttRsp();
                }
              }
              else
              {
                // Process inter-task message
                safeToDealloc = SimpleBLEPeripheral_processStackMsg((ICall_Hdr *)pMsg);
              }
            }
    
            if (pMsg && safeToDealloc)
            {
              ICall_freeMsg(pMsg);
            }
          }
    
          // If RTOS queue is not empty, process app message.
          if (events & SBP_QUEUE_EVT)
          {
            while (!Queue_empty(appMsgQueue))
            {
              sbpEvt_t *pMsg = (sbpEvt_t *)Util_dequeueMsg(appMsgQueue);
              if (pMsg)
              {
                // Process message.
                SimpleBLEPeripheral_processAppMsg(pMsg);
    
                // Free the space from the message.
                ICall_free(pMsg);
              }
            }
          }
    
        
        }
      }
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_processStackMsg
     *
     * @brief   Process an incoming stack message.
     *
     * @param   pMsg - message to process
     *
     * @return  TRUE if safe to deallocate incoming message, FALSE otherwise.
     */
    static uint8_t SimpleBLEPeripheral_processStackMsg(ICall_Hdr *pMsg)
    {
      uint8_t safeToDealloc = TRUE;
    
      switch (pMsg->event)
      {
        case GATT_MSG_EVENT:
          // Process GATT message
          safeToDealloc = SimpleBLEPeripheral_processGATTMsg((gattMsgEvent_t *)pMsg);
          break;
    
        case HCI_GAP_EVENT_EVENT:
          {
    
            // Process HCI message
            switch(pMsg->status)
            {
              case HCI_COMMAND_COMPLETE_EVENT_CODE:
                // Process HCI Command Complete Event
                {
    
    #if !defined (USE_LL_CONN_PARAM_UPDATE)
                  // This code will disable the use of the LL_CONNECTION_PARAM_REQ
                  // control procedure (for connection parameter updates, the
                  // L2CAP Connection Parameter Update procedure will be used
                  // instead). To re-enable the LL_CONNECTION_PARAM_REQ control
                  // procedures, define the symbol USE_LL_CONN_PARAM_UPDATE
                  // The L2CAP Connection Parameter Update procedure is used to
                  // support a delta between the minimum and maximum connection
                  // intervals required by some iOS devices.
    
                  // Parse Command Complete Event for opcode and status
                  hciEvt_CmdComplete_t* command_complete = (hciEvt_CmdComplete_t*) pMsg;
                  uint8_t   pktStatus = command_complete->pReturnParam[0];
    
                  //find which command this command complete is for
                  switch (command_complete->cmdOpcode)
                  {
                    case HCI_LE_READ_LOCAL_SUPPORTED_FEATURES:
                      {
                        if (pktStatus == SUCCESS)
                        {
                          uint8_t featSet[8];
    
                          // Get current feature set from received event (bits 1-9
                          // of the returned data
                          memcpy( featSet, &command_complete->pReturnParam[1], 8 );
    
                          // Clear bit 1 of byte 0 of feature set to disable LL
                          // Connection Parameter Updates
                          CLR_FEATURE_FLAG( featSet[0], LL_FEATURE_CONN_PARAMS_REQ );
    
                          // Update controller with modified features
                          HCI_EXT_SetLocalSupportedFeaturesCmd( featSet );
                        }
                      }
                      break;
    
                    default:
                      //do nothing
                      break;
                  }
    #endif // !defined (USE_LL_CONN_PARAM_UPDATE)
    
                }
                break;
    
              case HCI_BLE_HARDWARE_ERROR_EVENT_CODE:
                AssertHandler(HAL_ASSERT_CAUSE_HARDWARE_ERROR,0);
                break;
    
              default:
                break;
            }
          }
          break;
    
          default:
            // do nothing
            break;
    
        }
    
      return (safeToDealloc);
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_processGATTMsg
     *
     * @brief   Process GATT messages and events.
     *
     * @return  TRUE if safe to deallocate incoming message, FALSE otherwise.
     */
    static uint8_t SimpleBLEPeripheral_processGATTMsg(gattMsgEvent_t *pMsg)
    {
      // See if GATT server was unable to transmit an ATT response
      if (pMsg->hdr.status == blePending)
      {
        // No HCI buffer was available. Let's try to retransmit the response
        // on the next connection event.
        if (HCI_EXT_ConnEventNoticeCmd(pMsg->connHandle, selfEntity,
                                       SBP_HCI_CONN_EVT_END_EVT) == SUCCESS)
        {
          // First free any pending response
          SimpleBLEPeripheral_freeAttRsp(FAILURE);
    
          // Hold on to the response message for retransmission
          pAttRsp = pMsg;
    
          // Don't free the response message yet
          return (FALSE);
        }
      }
      else if (pMsg->method == ATT_FLOW_CTRL_VIOLATED_EVENT)
      {
        // ATT request-response or indication-confirmation flow control is
        // violated. All subsequent ATT requests or indications will be dropped.
        // The app is informed in case it wants to drop the connection.
    
        // Display the opcode of the message that caused the violation.
        Display_print1(dispHandle, 5, 0, "FC Violated: %d", pMsg->msg.flowCtrlEvt.opcode);
      }
      else if (pMsg->method == ATT_MTU_UPDATED_EVENT)
      {
        // MTU size updated
        Display_print1(dispHandle, 5, 0, "MTU Size: %d", pMsg->msg.mtuEvt.MTU);
      }
    
      // Free message payload. Needed only for ATT Protocol messages
      GATT_bm_free(&pMsg->msg, pMsg->method);
    
      // It's safe to free the incoming message
      return (TRUE);
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_sendAttRsp
     *
     * @brief   Send a pending ATT response message.
     *
     * @param   none
     *
     * @return  none
     */
    static void SimpleBLEPeripheral_sendAttRsp(void)
    {
      // See if there's a pending ATT Response to be transmitted
      if (pAttRsp != NULL)
      {
        uint8_t status;
    
        // Increment retransmission count
        rspTxRetry++;
    
        // Try to retransmit ATT response till either we're successful or
        // the ATT Client times out (after 30s) and drops the connection.
        status = GATT_SendRsp(pAttRsp->connHandle, pAttRsp->method, &(pAttRsp->msg));
        if ((status != blePending) && (status != MSG_BUFFER_NOT_AVAIL))
        {
          // Disable connection event end notice
          HCI_EXT_ConnEventNoticeCmd(pAttRsp->connHandle, selfEntity, 0);
    
          // We're done with the response message
          SimpleBLEPeripheral_freeAttRsp(status);
        }
        else
        {
          // Continue retrying
          Display_print1(dispHandle, 5, 0, "Rsp send retry: %d", rspTxRetry);
        }
      }
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_freeAttRsp
     *
     * @brief   Free ATT response message.
     *
     * @param   status - response transmit status
     *
     * @return  none
     */
    static void SimpleBLEPeripheral_freeAttRsp(uint8_t status)
    {
      // See if there's a pending ATT response message
      if (pAttRsp != NULL)
      {
        // See if the response was sent out successfully
        if (status == SUCCESS)
        {
          Display_print1(dispHandle, 5, 0, "Rsp sent retry: %d", rspTxRetry);
        }
        else
        {
          // Free response payload
          GATT_bm_free(&pAttRsp->msg, pAttRsp->method);
    
          Display_print1(dispHandle, 5, 0, "Rsp retry failed: %d", rspTxRetry);
        }
    
        // Free response message
        ICall_freeMsg(pAttRsp);
    
        // Reset our globals
        pAttRsp = NULL;
        rspTxRetry = 0;
      }
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_processAppMsg
     *
     * @brief   Process an incoming callback from a profile.
     *
     * @param   pMsg - message to process
     *
     * @return  None.
     */
    static void SimpleBLEPeripheral_processAppMsg(sbpEvt_t *pMsg)
    {
      switch (pMsg->hdr.event)
      {
        case SBP_STATE_CHANGE_EVT:
          {
            SimpleBLEPeripheral_processStateChangeEvt((gaprole_States_t)pMsg->
                                                    hdr.state);
          }
          break;
    
        case SBP_CHAR_CHANGE_EVT:
          {
            SimpleBLEPeripheral_processCharValueChangeEvt(pMsg->hdr.state);
          }
          break;
    
        // Pairing event
        case SBP_PAIRING_STATE_EVT:
          {
            SimpleBLEPeripheral_processPairState(pMsg->hdr.state, *pMsg->pData);
    
            ICall_free(pMsg->pData);
            break;
          }
    
        // Passcode event
        case SBP_PASSCODE_NEEDED_EVT:
          {
            SimpleBLEPeripheral_processPasscode(*pMsg->pData);
    
            ICall_free(pMsg->pData);
            break;
          }
        case SBP_WATCHDOG_FEED_EVT:
          {
              /*clear the ISR flag in critical region*/
              uint32_t  key = Hwi_disable();
    
            /**
              * clear the flag watchdogClearFlag set from watchdog isr to
              * make sure that application is working fine without any hang
            * */
              watchdogClearFlag = false;
    
              Hwi_restore(key);
          }
        break;
    
        default:
          // Do nothing.
          break;
      }
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_stateChangeCB
     *
     * @brief   Callback from GAP Role indicating a role state change.
     *
     * @param   newState - new state
     *
     * @return  None.
     */
    static void SimpleBLEPeripheral_stateChangeCB(gaprole_States_t newState)
    {
      SimpleBLEPeripheral_enqueueMsg(SBP_STATE_CHANGE_EVT, newState, 0);
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_processStateChangeEvt
     *
     * @brief   Process a pending GAP Role state change event.
     *
     * @param   newState - new state
     *
     * @return  None.
     */
    static void SimpleBLEPeripheral_processStateChangeEvt(gaprole_States_t newState)
    {
    #ifdef PLUS_BROADCASTER
      static bool firstConnFlag = false;
    #endif // PLUS_BROADCASTER
    
      switch ( newState )
      {
        case GAPROLE_STARTED:
          {
            uint8_t ownAddress[B_ADDR_LEN];
            uint8_t systemId[DEVINFO_SYSTEM_ID_LEN];
    
            GAPRole_GetParameter(GAPROLE_BD_ADDR, ownAddress);
    
            // use 6 bytes of device address for 8 bytes of system ID value
            systemId[0] = ownAddress[0];
            systemId[1] = ownAddress[1];
            systemId[2] = ownAddress[2];
    
            // set middle bytes to zero
            systemId[4] = 0x00;
            systemId[3] = 0x00;
    
            // shift three bytes up
            systemId[7] = ownAddress[5];
            systemId[6] = ownAddress[4];
            systemId[5] = ownAddress[3];
    
            DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId);
    
            // Display device address
            Display_print0(dispHandle, 1, 0, Util_convertBdAddr2Str(ownAddress));
            Display_print0(dispHandle, 2, 0, "Initialized");
          }
          break;
    
        case GAPROLE_ADVERTISING:
          Display_print0(dispHandle, 2, 0, "Advertising");
          break;
    
    #ifdef PLUS_BROADCASTER
        // After a connection is dropped, a device in PLUS_BROADCASTER will continue
        // sending non-connectable advertisements and shall send this change of
        // state to the application.  These are then disabled here so that sending
        // connectable advertisements can resume.
        case GAPROLE_ADVERTISING_NONCONN:
          {
            uint8_t advertEnabled = FALSE;
    
            // Disable non-connectable advertising.
            GAPRole_SetParameter(GAPROLE_ADV_NONCONN_ENABLED, sizeof(uint8_t),
                               &advertEnabled);
    
            advertEnabled = TRUE;
    
            // Enabled connectable advertising.
            GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
                                 &advertEnabled);
    
            // Reset flag for next connection.
            firstConnFlag = false;
    
            SimpleBLEPeripheral_freeAttRsp(bleNotConnected);
          }
          break;
    #endif //PLUS_BROADCASTER
    
        case GAPROLE_CONNECTED:
          {
            linkDBInfo_t linkInfo;
            uint8_t numActive = 0;
    
            Util_startClock(&periodicClock);
    
            numActive = linkDB_NumActive();
    
            // Use numActive to determine the connection handle of the last
            // connection
            if ( linkDB_GetInfo( numActive - 1, &linkInfo ) == SUCCESS )
            {
              Display_print1(dispHandle, 2, 0, "Num Conns: %d", (uint16_t)numActive);
              Display_print0(dispHandle, 3, 0, Util_convertBdAddr2Str(linkInfo.addr));
            }
            else
            {
              uint8_t peerAddress[B_ADDR_LEN];
    
              GAPRole_GetParameter(GAPROLE_CONN_BD_ADDR, peerAddress);
    
              Display_print0(dispHandle, 2, 0, "Connected");
              Display_print0(dispHandle, 3, 0, Util_convertBdAddr2Str(peerAddress));
            }
    
            #ifdef PLUS_BROADCASTER
              // Only turn advertising on for this state when we first connect
              // otherwise, when we go from connected_advertising back to this state
              // we will be turning advertising back on.
              if (firstConnFlag == false)
              {
                uint8_t advertEnabled = FALSE; // Turn on Advertising
    
                // Disable connectable advertising.
                GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
                                     &advertEnabled);
    
                // Set to true for non-connectable advertising.
                advertEnabled = TRUE;
    
                // Enable non-connectable advertising.
                GAPRole_SetParameter(GAPROLE_ADV_NONCONN_ENABLED, sizeof(uint8_t),
                                     &advertEnabled);
                firstConnFlag = true;
              }
            #endif // PLUS_BROADCASTER
          }
          break;
    
        case GAPROLE_CONNECTED_ADV:
          Display_print0(dispHandle, 2, 0, "Connected Advertising");
          break;
    
        case GAPROLE_WAITING:
          Util_stopClock(&periodicClock);
          SimpleBLEPeripheral_freeAttRsp(bleNotConnected);
    
          Display_print0(dispHandle, 2, 0, "Disconnected");
    
          // Clear remaining lines
          Display_clearLines(dispHandle, 3, 5);
          break;
    
        case GAPROLE_WAITING_AFTER_TIMEOUT:
           Util_stopClock(&periodicClock);
          SimpleBLEPeripheral_freeAttRsp(bleNotConnected);
    
          Display_print0(dispHandle, 2, 0, "Timed Out");
    
          // Clear remaining lines
          Display_clearLines(dispHandle, 3, 5);
    
          #ifdef PLUS_BROADCASTER
            // Reset flag for next connection.
            firstConnFlag = false;
          #endif // PLUS_BROADCASTER
          break;
    
        case GAPROLE_ERROR:
          Display_print0(dispHandle, 2, 0, "Error");
          break;
    
        default:
          Display_clearLine(dispHandle, 2);
          break;
      }
    
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_charValueChangeCB
     *
     * @brief   Callback from Simple Profile indicating a characteristic
     *          value change.
     *
     * @param   paramID - parameter ID of the value that was changed.
     *
     * @return  None.
     */
    static void SimpleBLEPeripheral_charValueChangeCB(uint8_t paramID)
    {
      SimpleBLEPeripheral_enqueueMsg(SBP_CHAR_CHANGE_EVT, paramID, 0);
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_processCharValueChangeEvt
     *
     * @brief   Process a pending Simple Profile characteristic value change
     *          event.
     *
     * @param   paramID - parameter ID of the value that was changed.
     *
     * @return  None.
     */
    static void SimpleBLEPeripheral_processCharValueChangeEvt(uint8_t paramID)
    {
      uint8_t newValue;
    
      switch(paramID)
      {
        case SIMPLEPROFILE_CHAR1:
          SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR1, &newValue);
    
          Display_print1(dispHandle, 4, 0, "Char 1: %d", (uint16_t)newValue);
          break;
    
        case SIMPLEPROFILE_CHAR3:
          SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR3, &newValue);
    
          Display_print1(dispHandle, 4, 0, "Char 3: %d", (uint16_t)newValue);
          break;
    
        default:
          // should not reach here!
          break;
      }
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_performPeriodicTask
     *
     * @brief   Perform a periodic application task. This function gets called
     *          every five seconds (SBP_PERIODIC_EVT_PERIOD). In this example,
     *          the value of the third characteristic in the SimpleGATTProfile
     *          service is retrieved from the profile, and then copied into the
     *          value of the the fourth characteristic.
     *
     * @param   None.
     *
     * @return  None.
     */
    static void SimpleBLEPeripheral_performPeriodicTask(void)
    {
      uint8_t valueToCopy;
    
      // Call to retrieve the value of the third characteristic in the profile
      if (SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR3, &valueToCopy) == SUCCESS)
      {
        // Call to set that value of the fourth characteristic in the profile.
        // Note that if notifications of the fourth characteristic have been
        // enabled by a GATT client device, then a notification will be sent
        // every time this function is called.
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, sizeof(uint8_t),
                                   &valueToCopy);
      }
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_pairStateCB
     *
     * @brief   Pairing state callback.
     *
     * @return  none
     */
    static void SimpleBLEPeripheral_pairStateCB(uint16_t connHandle, uint8_t state,
                                                uint8_t status)
    {
      uint8_t *pData;
    
      // Allocate space for the event data.
      if ((pData = ICall_malloc(sizeof(uint8_t))))
      {
        *pData = status;
    
        // Queue the event.
        SimpleBLEPeripheral_enqueueMsg(SBP_PAIRING_STATE_EVT, state, pData);
      }
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_processPairState
     *
     * @brief   Process the new paring state.
     *
     * @return  none
     */
    static void SimpleBLEPeripheral_processPairState(uint8_t state, uint8_t status)
    {
      if (state == GAPBOND_PAIRING_STATE_STARTED)
      {
        Display_print0(dispHandle, 2, 0, "Pairing started");
      }
      else if (state == GAPBOND_PAIRING_STATE_COMPLETE)
      {
        if (status == SUCCESS)
        {
          Display_print0(dispHandle, 2, 0, "Pairing success");
        }
        else
        {
          Display_print1(dispHandle, 2, 0, "Pairing fail: %d", status);
        }
      }
      else if (state == GAPBOND_PAIRING_STATE_BONDED)
      {
        if (status == SUCCESS)
        {
          Display_print0(dispHandle, 2, 0, "Bonding success");
        }
      }
      else if (state == GAPBOND_PAIRING_STATE_BOND_SAVED)
      {
        if (status == SUCCESS)
        {
          Display_print0(dispHandle, 2, 0, "Bond save success");
        }
        else
        {
          Display_print1(dispHandle, 2, 0, "Bond save failed: %d", status);
        }
      }
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_passcodeCB
     *
     * @brief   Passcode callback.
     *
     * @return  none
     */
    static void SimpleBLEPeripheral_passcodeCB(uint8_t *deviceAddr, uint16_t connHandle,
                                               uint8_t uiInputs, uint8_t uiOutputs)
    {
      uint8_t *pData;
    
      // Allocate space for the passcode event.
      if ((pData = ICall_malloc(sizeof(uint8_t))))
      {
        *pData = uiOutputs;
    
        // Enqueue the event.
        SimpleBLEPeripheral_enqueueMsg(SBP_PASSCODE_NEEDED_EVT, 0, pData);
      }
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_processPasscode
     *
     * @brief   Process the Passcode request.
     *
     * @return  none
     */
    static void SimpleBLEPeripheral_processPasscode(uint8_t uiOutputs)
    {
      // This app uses a default passcode. A real-life scenario would handle all
      // pairing scenarios and likely generate this randomly.
      uint32_t passcode = B_APP_DEFAULT_PASSCODE;
    
      // Display passcode to user
      if (uiOutputs != 0)
      {
        Display_print1(dispHandle, 4, 0, "Passcode: %d", passcode);
      }
    
      uint16_t connectionHandle;
      GAPRole_GetParameter(GAPROLE_CONNHANDLE, &connectionHandle);
    
      // Send passcode response
      GAPBondMgr_PasscodeRsp(connectionHandle, SUCCESS, passcode);
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_clockHandler
     *
     * @brief   Handler function for clock timeouts.
     *
     * @param   arg - event type
     *
     * @return  None.
     */
    static void SimpleBLEPeripheral_clockHandler(UArg arg)
    {
      // Wake up the application.
     //uint8_t initialAdvertEnable
      //Event_post(syncEvent, arg);
      	(void) GAPRole_TerminateConnection();
             
      
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_enqueueMsg
     *
     * @brief   Creates a message and puts the message in RTOS queue.
     *
     * @param   event - message event.
     * @param   state - message state.
     * @param   pData - message data pointer.
     *
     * @return  TRUE or FALSE
     */
    static uint8_t SimpleBLEPeripheral_enqueueMsg(uint8_t event, uint8_t state,
                                               uint8_t *pData)
    {
      sbpEvt_t *pMsg = ICall_malloc(sizeof(sbpEvt_t));
    
      // Create dynamic pointer to message.
      if (pMsg)
      {
        pMsg->hdr.event = event;
        pMsg->hdr.state = state;
        pMsg->pData = pData;
    
        // Enqueue the message.
        return Util_enqueueMsg(appMsgQueue, syncEvent, (uint8_t *)pMsg);
      }
    
      return FALSE;
    }
    /*********************************************************************
    *********************************************************************/
    
    Hi sean,

    As per our discussion i added the watchdog implementation with the simpleBle example code.

    And we are observing the same issue. After 5 hours continuous BLe  connect and disconnect the issue observed.

    I attached the file which is modified by us.

    i will work on the other points assert and head failure.

    Meanwhile you can check with this code in your TI Lanchpad.

    Thanks.

  • Hi Thangaraj,

    Thanks for providing the source file, I will work to reproduce your test.

    To do so I will need to script the central side of the connection.

    Can you provide some more information about the connection?

     - What connection parameters did you use? ( connection interval, slave latency, super vision timeout, etc)

     - Did you send any data or control packets during the connection?

    Or do you simply connection to the device, wait for link established event and then disconnect?

    Is the sniffer capture that you sent previous acceptable discerning this? (i.e. use same parameters as listed in capture)

  • we are making the connection using the parameters with following values

    minimum connection interval(7.5ms),maximunconnectioninterval(10ms),supervisiontimeout(256) and slave latency(0).

    then simply connect to device and wait for the link established event and then disconnect.
  • Hi ,
    I have done all the experiment from our side
    1. Enabled the HEAPMGR_METRICS and monitored the variable heapmgrMemFail during the issue. Its value is zero during that time. Which means no heap failure during that time.
    2. Also i plugged the HAL Assert handler to check any assertion happened or not. This also not happened.

    I hope you can able to reproduce the issue with the simpleperipheral.c file with watchdog functionality which i already provided.

    one more observation is with our software without watchdog this test is working fine.

    waiting for your solution or input or suggestion to handle the watchdog




    Thanks.


    With Regards,
    Thangaraj.P
  • Hi Sean,

    Any Update from your side?

    Are you able to simulate the issue?

    -Thangaraj
  • Thangaraj,

    The test will take some time to setup the central side. 

    I will provide an update next week.

  • Hi Sean2,

    Please Update as soon as possible.
    Because customer waiting for the fix.

    one more thing as i already mentioned that if we disable the watchdog then its working fine.

    can you check in that file the watchdog implementation is proper as per your guidelines or you feel which needs any improvement.
    Please check that point also.

    with Regards,
    Thangaraj.P
  • Hi,

    Hope i will be getting the repsponse monday ealier
  • Thangaraj,

    First I would like to provide some feedback on the code snippet provided. Thanks for sharing by the way.

    - The function invoked by the watchdog is infact a non maskable interrupt (NMI) and will execute at the highest priority in the system.
    - You are allocating a message in that function which uses malloc(...), this is a non deterministic call and can take a long time if the heap is fragmented
    - It also appears that the design is that you expect the watchdog to timeout, then you set an event and set a flag to clear the dog
    - If the flag is set, you will clear the dog.

    Some observations:

    - This makes your effective watchdog period 2x the value you set.
    - If you miss a single event you do not get the callback, the device will reset.
    - The function will allocate memory which can take a long time or worse yet fail in the extreme case

    My recommendations for implementing a watchdog.

    1. Use a software a TI-RTOS clock at period = critical peroid
    2. Create a dedicated semaphore or event for clearing the watchdog.
    3. In the clock timeout function, set the event or semaphone
    4. In the main loop of your application task context, call watchdog clear.
    5. Use the watchdog timeout function to attempt to recover the system, clear memory, log an error message, etc


    Can you please review my suggestions and run the test again with a new watchdog implementation.
    To set the proper expectations, it will take TI one week to implement, run, and analyze the results once we have the issue reproduced on the above suggested watchdog implementation.
  • Ok. I will analyze and get back you.
    But whether the issue reproduced at your end with the code sent by us.

    can you share your sample code with that your watchdog proposal?


    Thanks.
  • Hi Sean,

    having studied TI docs a bit more, for servicing (feeding) the Watchdog Timer WDT we are now considering to following a different approach:

    By editing file cc2640_r2_csdk.cfg we're adding a function in the Idle task (before the uC is put to Standby)

    This way, we're avoiding any h/w irpt + ISR with malloc() (by an expiring WDT, as we have been doing it so far) or s/w irpt + ISR (by an expiring clock, as you suggest).

    Please let us have your comments on the planned approach. What are the cons of doing so?

    Many thanks in advance for your help!

    BR.
    Frank.

  • Hi Frank, Thangaraj,

    The idle task is another good approach.
    The key thing here is understanding that the watchdog timeout must be set proportional to the worst case sleep/wakeup of the device.

    For example:
    - The idle task runs and the power policy decides that there is time to put the device into standby.
    - The device wakes up, which takes some time (handled in the power policy),
    - The stack task will run if necessary (highest priority),
    - The application task runs if necessary

    After this above sequence is complete the idle task will run and the watchdog will be cleared.
    If you are able to profile the worst case time for this and set the watchdog timer appropriately, then it should be a good solution.
  • Hi Sean,
    As we already Updated we are feeding the watchdog clear from idle Task hook function. so the above mentioned problem got resolved.
    But the problem is we are not able to debug as like our friends already following up with another thread.
    e2e.ti.com/.../2477789


    but some other thread mentioned that watchdog should disable in debug mode.
    But it should work with watchdog enabled also.

    Thats why we have Watchdog_DEBUG_STALL_ON in our code also.

    Other projects running same CC2640R2F dont face such problems..

    what was conclusion for this thread?
    e2e.ti.com/.../2333748

    Please Update.
    Thanks

    -Thangaraj.P