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.

LAUNCHXL-CC2650: Porting from CC2650Launchpad (RGZ) to custom board (CC2650F128RSM)

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

I am new to TI platform and have only a couple of days of experience using a launchpad. I have a CC2650 Launchpad Rev1.3 where I uploaded the Simple BLE Peripheral Code using SmartRF Flash Programmer, by uploading the stack and then the app hex code. It broadcasted fine and it showed up on NRFConnect and TI SimpleLink Starter App. Going through some examples and tutorials, I have been able to control the onboard LEDs using buttons and also by writing to SimpleProfile_Char3 by sending a command from the app, I could toggle the LED.

Now, we have a custom board designed using 4mm*4mm CC2650F128 RSM chipset, where I uploaded the same code using 2 pin JTAG from the Launchpad's onboard XDS110 debugger. For some reason, the custom board is not broadcasting any Bluetooth signal when I check the NRFConnect or Simplelink App.

When I revert back to the stock SImple BLE Peripheral Code, the chipset broadcasts a Bluetooth signal similar to the Launchpad, but I cannot connect to the board and so I cannot read or write anything. It just shows connection failed.

From troubleshooting through previous issues and forum responses, I presume it is because of the packaging issue, where LP uses RGZ and custom board uses RSM chipset. I followed the steps to make all the DIO beyond DIO_9 as unassigned and even tried creating MYBOARD by duplicating the CC2650_LAUNCHXL board, but nothing worked. https://software-dl.ti.com/simplelink/esd/simplelink_cc2640r2_sdk/2.40.00.32/exports/docs/ble5stack/ble_user_guide/html/ble-stack-5.x/custom-hardware.html

Sorry for the trouble, as I am a newbie and am having a hard time understanding what needs to be done. Could anyone provide me some easy go-to steps for porting my project from launchpad (CC2650F128 RGZ) to CC2650F128RSM. Many of the links are for different CC2640R2 chipset and I still can't figure out how to make the custom board work.

Note: The same custom board was previously flashed by another person in my lab and that used to work, but I do not have access to those code, so I am kind of stuck! Any help is appreciated!! Thank you!

  • Hi,

    Share your board file code changes.

    -kel

  • Thanks for the quick response. I tried the stock code (Simple BLE Peripheral) for cc2650lp from the BLE SDK example. That was also not connecting to the NRFConnect app, even though it was broadcasting a BT signal.

    The modified code however was not broadcasting at all from the custom board, could be the pin configuration issue.

    I have attached both the stock example code and the modified code. In the modified code, I have some pinconfig added to control the LEDs and the buttons and conditional statements added to SimpleBLEPeripheral_processCharValueChangeEvt.

    Thanks once again and sorry for these questions.

    /******************************************************************************
    
     @file  simple_peripheral.c
    
     @brief This file contains the Simple BLE Peripheral sample application for use
            with the CC2650 Bluetooth Low Energy Protocol Stack.
    
     Group: WCS, BTS
     Target Device: CC2650, CC2640
    
     ******************************************************************************
     
     Copyright (c) 2013-2021, 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: ble_sdk_2_02_02_
     Release Date: 2021-12-01 09:07:53
     *****************************************************************************/
    
    /*********************************************************************
     * INCLUDES
     */
    #include <string.h>
    
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/knl/Semaphore.h>
    #include <ti/sysbios/knl/Queue.h>
    
    #include "hci_tl.h"
    #include "gatt.h"
    #include "linkdb.h"
    #include "gapgattserver.h"
    #include "gattservapp.h"
    #include "devinfoservice.h"
    #include "simple_gatt_profile.h"
    
    
    //
    #if defined(FEATURE_OAD) || defined(IMAGE_INVALIDATE)
    #include "oad_target.h"
    #include "oad.h"
    #endif //FEATURE_OAD || IMAGE_INVALIDATE
    
    #include "peripheral.h"
    #include "gapbondmgr.h"
    
    #include "osal_snv.h"
    #include "icall_apimsg.h"
    
    #include "util.h"
    
    #ifdef USE_RCOSC
    #include "rcosc_calibration.h"
    #endif //USE_RCOSC
    
    #include <ti/mw/display/Display.h>
    #include "board_key.h"
    
    #include "board.h"
    
    #include "simple_peripheral.h"
    
    #if defined( USE_FPGA ) || defined( DEBUG_SW_TRACE )
    #include <driverlib/ioc.h>
    #endif // USE_FPGA | DEBUG_SW_TRACE
    
    /*********************************************************************
     * CONSTANTS
     */
    
    // Advertising interval when device is discoverable (units of 625us, 160=100ms)
    #define DEFAULT_ADVERTISING_INTERVAL          160
    
    // Limited discoverable mode advertises for 30.72s, and then stops
    // General discoverable mode advertises indefinitely
    #define DEFAULT_DISCOVERABLE_MODE             GAP_ADTYPE_FLAGS_GENERAL
    
    #ifndef FEATURE_OAD
    // Minimum connection interval (units of 1.25ms, 80=100ms) if automatic
    // parameter update request is enabled
    #define DEFAULT_DESIRED_MIN_CONN_INTERVAL     80
    
    // Maximum connection interval (units of 1.25ms, 800=1000ms) if automatic
    // parameter update request is enabled
    #define DEFAULT_DESIRED_MAX_CONN_INTERVAL     800
    #else //!FEATURE_OAD
    // Minimum connection interval (units of 1.25ms, 8=10ms) if automatic
    // parameter update request is enabled
    #define DEFAULT_DESIRED_MIN_CONN_INTERVAL     8
    
    // Maximum connection interval (units of 1.25ms, 8=10ms) if automatic
    // parameter update request is enabled
    #define DEFAULT_DESIRED_MAX_CONN_INTERVAL     8
    #endif // FEATURE_OAD
    
    // Slave latency to use if automatic parameter update request is enabled
    #define DEFAULT_DESIRED_SLAVE_LATENCY         0
    
    // Supervision timeout value (units of 10ms, 1000=10s) if automatic parameter
    // update request is enabled
    #define DEFAULT_DESIRED_CONN_TIMEOUT          1000
    
    // Whether to enable automatic parameter update request when a connection is
    // formed
    #define DEFAULT_ENABLE_UPDATE_REQUEST         GAPROLE_LINK_PARAM_UPDATE_INITIATE_BOTH_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               5000
    
    #ifdef FEATURE_OAD
    // The size of an OAD packet.
    #define OAD_PACKET_SIZE                       ((OAD_BLOCK_SIZE) + 2)
    #endif // FEATURE_OAD
    
    // Task configuration
    #define SBP_TASK_PRIORITY                     1
    
    
    #ifndef SBP_TASK_STACK_SIZE
    #define SBP_TASK_STACK_SIZE                   644
    #endif
    
    // Internal Events for RTOS application
    #define SBP_STATE_CHANGE_EVT                  0x0001
    #define SBP_CHAR_CHANGE_EVT                   0x0002
    #define SBP_PERIODIC_EVT                      0x0004
    #define SBP_CONN_EVT_END_EVT                  0x0008
    
    /*********************************************************************
     * TYPEDEFS
     */
    
    // App event passed from profiles.
    typedef struct
    {
      appEvtHdr_t hdr;  // event header.
    } 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;
    
    // Semaphore globally used to post events to the application thread
    static ICall_Semaphore sem;
    
    // Clock instances for internal periodic events.
    static Clock_Struct periodicClock;
    
    // Queue object used for app messages
    static Queue_Struct appMsg;
    static Queue_Handle appMsgQueue;
    
    #if defined(FEATURE_OAD)
    // Event data from OAD profile.
    static Queue_Struct oadQ;
    static Queue_Handle hOadQ;
    #endif //FEATURE_OAD
    
    // events flag for internal application events.
    static uint16_t events;
    
    // Task configuration
    Task_Struct sbpTask;
    Char sbpTaskStack[SBP_TASK_STACK_SIZE];
    
    // Profile state and parameters
    //static gaprole_States_t gapProfileState = GAPROLE_INIT;
    
    // GAP - SCAN RSP 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',
    ///SamG commented out
      // 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
      ///SamG
    };
    
    // GAP - Advertisement data (max size = 31 bytes, though this is
    // best kept short to conserve power while advertisting)
    static uint8_t advertData[] =
    {
      // Flags; this sets the device to use limited discoverable
      // mode (advertises for 30 seconds at a time) instead of general
      // discoverable mode (advertises indefinitely)
      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
    #if !defined(FEATURE_OAD) || defined(FEATURE_OAD_ONCHIP)
      0x03,   // length of this data
    #else //OAD for external flash
      0x05,  // lenght of this data
    #endif //FEATURE_OAD
    
      //SamG commented out for test
    //  GAP_ADTYPE_16BIT_MORE,      // some of the UUID's, but not all
    //#ifdef FEATURE_OAD
    //  LO_UINT16(OAD_SERVICE_UUID),
    //  HI_UINT16(OAD_SERVICE_UUID),
    //#endif //FEATURE_OAD
    //#ifndef FEATURE_OAD_ONCHIP
    //  LO_UINT16(SIMPLEPROFILE_SERV_UUID),
    //  HI_UINT16(SIMPLEPROFILE_SERV_UUID)
    //#endif //FEATURE_OAD_ONCHIP
    
      ///SamG
    };
    
    // GAP GATT Attributes
    static uint8_t attDeviceName[GAP_DEVICE_NAME_LEN] = "Simple BLE 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_stateChangeCB(gaprole_States_t newState);
    #ifndef FEATURE_OAD_ONCHIP
    static void SimpleBLEPeripheral_charValueChangeCB(uint8_t paramID);
    #endif //!FEATURE_OAD_ONCHIP
    static void SimpleBLEPeripheral_enqueueMsg(uint8_t event, uint8_t state);
    
    #ifdef FEATURE_OAD
    void SimpleBLEPeripheral_processOadWriteCB(uint8_t event, uint16_t connHandle,
                                               uint8_t *pData);
    #endif //FEATURE_OAD
    
    /*********************************************************************
     * EXTERN FUNCTIONS
     */
    extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);
    
    /*********************************************************************
     * PROFILE CALLBACKS
     */
    
    // GAP Role Callbacks
    static gapRolesCBs_t SimpleBLEPeripheral_gapRoleCBs =
    {
      SimpleBLEPeripheral_stateChangeCB     // Profile State Change Callbacks
    };
    
    // GAP Bond Manager Callbacks
    static gapBondCBs_t simpleBLEPeripheral_BondMgrCBs =
    {
      NULL, // Passcode callback (not used by application)
      NULL  // Pairing / Bonding state Callback (not used by application)
    };
    
    // Simple GATT Profile Callbacks
    #ifndef FEATURE_OAD_ONCHIP
    static simpleProfileCBs_t SimpleBLEPeripheral_simpleProfileCBs =
    {
      SimpleBLEPeripheral_charValueChangeCB // Characteristic value change callback
    };
    #endif //!FEATURE_OAD_ONCHIP
    
    #ifdef FEATURE_OAD
    static oadTargetCBs_t simpleBLEPeripheral_oadCBs =
    {
      SimpleBLEPeripheral_processOadWriteCB // Write Callback.
    };
    #endif //FEATURE_OAD
    
    /*********************************************************************
     * PUBLIC FUNCTIONS
     */
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_createTask
     *
     * @brief   Task creation function for the Simple BLE 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, &sem);
    
    
    #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(Display_Type_LCD, NULL);
    
      // Setup the GAP
      GAP_SetParamValue(TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL);
    
      // Setup the GAP Peripheral Role Profile
      {
        // For all hardware platforms, device starts advertising upon initialization
        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 the enabler is set back to TRUE
        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 GAP Role 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 GAP Characteristics
      GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);
    
      // Set advertising interval
      {
        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
      {
        uint32_t passkey = 0; // passkey "000000"
        uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
        uint8_t mitm = TRUE;
        uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
        uint8_t bonding = TRUE;
    
        GAPBondMgr_SetParameter(GAPBOND_DEFAULT_PASSCODE, sizeof(uint32_t),
                                &passkey);
        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
      GATTServApp_AddService(GATT_ALL_SERVICES);   // GATT attributes
      DevInfo_AddService();                        // Device Information Service
    
    #ifndef FEATURE_OAD_ONCHIP
      SimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile
    #endif //!FEATURE_OAD_ONCHIP
    
    #ifdef FEATURE_OAD
      VOID OAD_addService();                 // OAD Profile
      OAD_register((oadTargetCBs_t *)&simpleBLEPeripheral_oadCBs);
      hOadQ = Util_constructQueue(&oadQ);
    #endif //FEATURE_OAD
    
    #ifdef IMAGE_INVALIDATE
      Reset_addService();
    #endif //IMAGE_INVALIDATE
    
    
    #ifndef FEATURE_OAD_ONCHIP
      // Setup the SimpleProfile Characteristic Values
      {
        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);
    #endif //!FEATURE_OAD_ONCHIP
    
      // Start the Device
      VOID GAPRole_StartDevice(&SimpleBLEPeripheral_gapRoleCBs);
    
      // Start Bond Manager
      VOID GAPBondMgr_Register(&simpleBLEPeripheral_BondMgrCBs);
    
      // Register with GAP for HCI/Host messages
      GAP_RegisterForMsgs(selfEntity);
    
      // Register for GATT local events and ATT Responses pending for transmission
      GATT_RegisterForMsgs(selfEntity);
    
      HCI_LE_ReadMaxDataLenCmd();
    
    #if defined FEATURE_OAD
    #if defined (HAL_IMAGE_A)
      Display_print0(dispHandle, 0, 0, "BLE Peripheral A");
    #else
      Display_print0(dispHandle, 0, 0, "BLE Peripheral B");
    #endif // HAL_IMAGE_A
    #else
      Display_print0(dispHandle, 0, 0, "BLE Peripheral");
    #endif // FEATURE_OAD
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_taskFxn
     *
     * @brief   Application task entry point for the Simple BLE Peripheral.
     *
     * @param   a0, a1 - not used.
     *
     * @return  None.
     */
    static void SimpleBLEPeripheral_taskFxn(UArg a0, UArg a1)
    {
      // Initialize application
      SimpleBLEPeripheral_init();
    
      // Application main loop
      for (;;)
      {
        // Waits for a signal to the semaphore associated with the calling thread.
        // Note that the semaphore associated with a thread is signaled when a
        // message is queued to the message receive queue of the thread or when
        // ICall_signal() function is called onto the semaphore.
        ICall_Errno errno = ICall_wait(ICALL_TIMEOUT_FOREVER);
    
        if (errno == ICALL_ERRNO_SUCCESS)
        {
          ICall_EntityID dest;
          ICall_ServiceEnum src;
          ICall_HciExtEvt *pMsg = NULL;
    
          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)
              {
                if (pEvt->event_flag & SBP_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.
          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);
            }
          }
        }
    
        if (events & SBP_PERIODIC_EVT)
        {
          events &= ~SBP_PERIODIC_EVT;
    
          Util_startClock(&periodicClock);
    
          // Perform periodic application task
          SimpleBLEPeripheral_performPeriodicTask();
        }
    
    #ifdef FEATURE_OAD
        while (!Queue_empty(hOadQ))
        {
          oadTargetWrite_t *oadWriteEvt = Queue_get(hOadQ);
    
          // Identify new image.
          if (oadWriteEvt->event == OAD_WRITE_IDENTIFY_REQ)
          {
            OAD_imgIdentifyWrite(oadWriteEvt->connHandle, oadWriteEvt->pData);
          }
          // Write a next block request.
          else if (oadWriteEvt->event == OAD_WRITE_BLOCK_REQ)
          {
            OAD_imgBlockWrite(oadWriteEvt->connHandle, oadWriteEvt->pData);
          }
    
          // Free buffer.
          ICall_free(oadWriteEvt);
        }
    #endif //FEATURE_OAD
      }
    }
    
    /*********************************************************************
     * @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
                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_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;
    
        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);
    }
    
    /*********************************************************************
     * @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 sending 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-connectabel 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:
          {
            uint8_t advertReEnable = TRUE;
          
            Util_stopClock(&periodicClock);
            SimpleBLEPeripheral_freeAttRsp(bleNotConnected);
    
            // Clear remaining lines
            Display_clearLines(dispHandle, 3, 5);
    
            GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &advertReEnable);
            Display_print0(dispHandle, 2, 0, "Advertising");
          }
          break;
    
        case GAPROLE_WAITING_AFTER_TIMEOUT:
          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 //#ifdef (PLUS_BROADCASTER)
          break;
    
        case GAPROLE_ERROR:
          Display_print0(dispHandle, 2, 0, "Error");
          break;
    
        default:
          Display_clearLine(dispHandle, 2);
          break;
      }
    
      // Update the state
      //gapProfileState = newState;
    }
    
    #ifndef FEATURE_OAD_ONCHIP
    /*********************************************************************
     * @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);
    }
    #endif //!FEATURE_OAD_ONCHIP
    
    /*********************************************************************
     * @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)
    {
    #ifndef FEATURE_OAD_ONCHIP
      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;
      }
    #endif //!FEATURE_OAD_ONCHIP
    }
    
    /*********************************************************************
     * @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)
    {
    #ifndef FEATURE_OAD_ONCHIP
      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);
      }
    #endif //!FEATURE_OAD_ONCHIP
    }
    
    
    #ifdef FEATURE_OAD
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_processOadWriteCB
     *
     * @brief   Process a write request to the OAD profile.
     *
     * @param   event      - event type:
     *                       OAD_WRITE_IDENTIFY_REQ
     *                       OAD_WRITE_BLOCK_REQ
     * @param   connHandle - the connection Handle this request is from.
     * @param   pData      - pointer to data for processing and/or storing.
     *
     * @return  None.
     */
    void SimpleBLEPeripheral_processOadWriteCB(uint8_t event, uint16_t connHandle,
                                               uint8_t *pData)
    {
      oadTargetWrite_t *oadWriteEvt = ICall_malloc( sizeof(oadTargetWrite_t) + \
                                                 sizeof(uint8_t) * OAD_PACKET_SIZE);
    
      if ( oadWriteEvt != NULL )
      {
        oadWriteEvt->event = event;
        oadWriteEvt->connHandle = connHandle;
    
        oadWriteEvt->pData = (uint8_t *)(&oadWriteEvt->pData + 1);
        memcpy(oadWriteEvt->pData, pData, OAD_PACKET_SIZE);
    
        Queue_put(hOadQ, (Queue_Elem *)oadWriteEvt);
    
        // Post the application's semaphore.
        Semaphore_post(sem);
      }
      else
      {
        // Fail silently.
      }
    }
    #endif //FEATURE_OAD
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_clockHandler
     *
     * @brief   Handler function for clock timeouts.
     *
     * @param   arg - event type
     *
     * @return  None.
     */
    static void SimpleBLEPeripheral_clockHandler(UArg arg)
    {
      // Store the event.
      events |= arg;
    
      // Wake up the application.
      Semaphore_post(sem);
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_enqueueMsg
     *
     * @brief   Creates a message and puts the message in RTOS queue.
     *
     * @param   event - message event.
     * @param   state - message state.
     *
     * @return  None.
     */
    static void SimpleBLEPeripheral_enqueueMsg(uint8_t event, uint8_t state)
    {
      sbpEvt_t *pMsg;
    
      // Create dynamic pointer to message.
      if ((pMsg = ICall_malloc(sizeof(sbpEvt_t))))
      {
        pMsg->hdr.event = event;
        pMsg->hdr.state = state;
    
        // Enqueue the message.
        Util_enqueueMsg(appMsgQueue, sem, (uint8*)pMsg);
      }
    }
    
    /*********************************************************************
    *********************************************************************/
    
    /******************************************************************************
    
     @file  simple_peripheral.c
    
     @brief This file contains the Simple BLE Peripheral sample application for use
            with the CC2650 Bluetooth Low Energy Protocol Stack.
    
     Group: WCS, BTS
     Target Device: CC2650, CC2640
    
     ******************************************************************************
     
     Copyright (c) 2013-2021, 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: ble_sdk_2_02_02_
     Release Date: 2021-12-01 09:07:53
     *****************************************************************************/
    
    /*********************************************************************
     * INCLUDES
     */
    #include <string.h>
    
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/knl/Semaphore.h>
    #include <ti/sysbios/knl/Queue.h>
    
    #include "hci_tl.h"
    #include "gatt.h"
    #include "linkdb.h"
    #include "gapgattserver.h"
    #include "gattservapp.h"
    #include "devinfoservice.h"
    #include "simple_gatt_profile.h"
    
    #if defined(FEATURE_OAD) || defined(IMAGE_INVALIDATE)
    #include "oad_target.h"
    #include "oad.h"
    #endif //FEATURE_OAD || IMAGE_INVALIDATE
    
    #include "peripheral.h"
    #include "gapbondmgr.h"
    
    #include "osal_snv.h"
    #include "icall_apimsg.h"
    
    #include "util.h"
    
    #ifdef USE_RCOSC
    #include "rcosc_calibration.h"
    #endif //USE_RCOSC
    
    #include <ti/mw/display/Display.h>
    #include "board_key.h"
    
    #include "board.h"
    
    #include "simple_peripheral.h"
    
    #if defined( USE_FPGA ) || defined( DEBUG_SW_TRACE )
    #include <driverlib/ioc.h>
    #endif // USE_FPGA | DEBUG_SW_TRACE
    
    /*********************************************************************
     * CONSTANTS
     */
    
    // Advertising interval when device is discoverable (units of 625us, 160=100ms)
    #define DEFAULT_ADVERTISING_INTERVAL          160
    
    // Limited discoverable mode advertises for 30.72s, and then stops
    // General discoverable mode advertises indefinitely
    #define DEFAULT_DISCOVERABLE_MODE             GAP_ADTYPE_FLAGS_GENERAL
    
    #ifndef FEATURE_OAD
    // Minimum connection interval (units of 1.25ms, 80=100ms) if automatic
    // parameter update request is enabled
    #define DEFAULT_DESIRED_MIN_CONN_INTERVAL     80
    
    // Maximum connection interval (units of 1.25ms, 800=1000ms) if automatic
    // parameter update request is enabled
    #define DEFAULT_DESIRED_MAX_CONN_INTERVAL     160
    #else //!FEATURE_OAD
    // Minimum connection interval (units of 1.25ms, 8=10ms) if automatic
    // parameter update request is enabled
    #define DEFAULT_DESIRED_MIN_CONN_INTERVAL     80
    
    // Maximum connection interval (units of 1.25ms, 8=10ms) if automatic
    // parameter update request is enabled
    #define DEFAULT_DESIRED_MAX_CONN_INTERVAL     160
    #endif // FEATURE_OAD
    
    // Slave latency to use if automatic parameter update request is enabled
    #define DEFAULT_DESIRED_SLAVE_LATENCY         0
    
    // Supervision timeout value (units of 10ms, 1000=10s) if automatic parameter
    // update request is enabled
    #define DEFAULT_DESIRED_CONN_TIMEOUT          1000
    
    // Whether to enable automatic parameter update request when a connection is
    // formed
    #define DEFAULT_ENABLE_UPDATE_REQUEST         GAPROLE_LINK_PARAM_UPDATE_INITIATE_BOTH_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               5000
    
    #ifdef FEATURE_OAD
    // The size of an OAD packet.
    #define OAD_PACKET_SIZE                       ((OAD_BLOCK_SIZE) + 2)
    #endif // FEATURE_OAD
    
    // Task configuration
    #define SBP_TASK_PRIORITY                     1
    
    
    #ifndef SBP_TASK_STACK_SIZE
    #define SBP_TASK_STACK_SIZE                   644
    #endif
    
    // Internal Events for RTOS application
    #define SBP_STATE_CHANGE_EVT                  0x0001
    #define SBP_CHAR_CHANGE_EVT                   0x0002
    #define SBP_PERIODIC_EVT                      0x0004
    #define SBP_CONN_EVT_END_EVT                  0x0008
    
    /*********************************************************************
     * TYPEDEFS
     */
    
    // App event passed from profiles.
    typedef struct
    {
      appEvtHdr_t hdr;  // event header.
    } 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;
    
    // Semaphore globally used to post events to the application thread
    static ICall_Semaphore sem;
    
    // Clock instances for internal periodic events.
    static Clock_Struct periodicClock;
    
    // Queue object used for app messages
    static Queue_Struct appMsg;
    static Queue_Handle appMsgQueue;
    
    #if defined(FEATURE_OAD)
    // Event data from OAD profile.
    static Queue_Struct oadQ;
    static Queue_Handle hOadQ;
    #endif //FEATURE_OAD
    
    // events flag for internal application events.
    static uint16_t events;
    
    // Task configuration
    Task_Struct sbpTask;
    Char sbpTaskStack[SBP_TASK_STACK_SIZE];
    
    // Profile state and parameters
    //static gaprole_States_t gapProfileState = GAPROLE_INIT;
    
    // GAP - SCAN RSP 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',
    
      'A',
      'M',
      'L',
      '2',
      '0',
      '2',
      '3',
      'B',
      'L',
      'E',
      'T',
      'e',
      's',
      't',
      '1',
      '_',
      'S',
      'a',
      'm',
    
      ///SamG commented out for test
    
      // 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
    
      ///SamG
    };
    
    // GAP - Advertisement data (max size = 31 bytes, though this is
    // best kept short to conserve power while advertisting)
    static uint8_t advertData[] =
    {
      // Flags; this sets the device to use limited discoverable
      // mode (advertises for 30 seconds at a time) instead of general
      // discoverable mode (advertises indefinitely)
      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
    #if !defined(FEATURE_OAD) || defined(FEATURE_OAD_ONCHIP)
      0x03,   // length of this data
    #else //OAD for external flash
      0x05,  // lenght of this data
    #endif //FEATURE_OAD
      GAP_ADTYPE_16BIT_MORE,      // some of the UUID's, but not all
    #ifdef FEATURE_OAD
      LO_UINT16(OAD_SERVICE_UUID),
      HI_UINT16(OAD_SERVICE_UUID),
    #endif //FEATURE_OAD
    #ifndef FEATURE_OAD_ONCHIP
      LO_UINT16(SIMPLEPROFILE_SERV_UUID),
      HI_UINT16(SIMPLEPROFILE_SERV_UUID)
    #endif //FEATURE_OAD_ONCHIP
    };
    
    // GAP GATT Attributes
    //static uint8_t attDeviceName[GAP_DEVICE_NAME_LEN] = "Simple BLE Peripheral";
    static uint8_t attDeviceName[GAP_DEVICE_NAME_LEN] = "AML2023BLETEST1_SAM";
    
    // Globals used for ATT Response retransmission
    static gattMsgEvent_t *pAttRsp = NULL;
    static uint8_t rspTxRetry = 0;
    
    
    
    /////SamG
    //
    static PIN_Handle dio0PinHandle;
    static PIN_State dio0PinState;
    
    // Pin configuration table for DIO_0
    PIN_Config dio0PinTable[] = {
      Board_DIO0 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX,
      PIN_TERMINATE
    };
    
    
    ///* Pin driver handles */
    static PIN_Handle buttonPinHandle;
    static PIN_Handle ledPinHandle;
    //
    ///* Global memory storage for a PIN_Config table */
    static PIN_State buttonPinState;
    static PIN_State ledPinState;
    //
    ///*
    // * Initial LED pin configuration table
    // *   - LEDs Board_LED0 & Board_LED1 are off.
    // */
    PIN_Config ledPinTable[] = {
      Board_LED0 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX,
      Board_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
      PIN_TERMINATE
    };
    //PIN_Config ledPinTable[] = {
    //  PIN_ID(6) | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX, // Works!
    //  PIN_ID(7) | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    //  PIN_TERMINATE
    //};
    ///*
    // * Application button pin configuration table:
    // *   - Buttons interrupts are configured to trigger on falling edge.
    // */
    PIN_Config buttonPinTable[] = {
        Board_BUTTON0 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
        Board_BUTTON1 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
        PIN_TERMINATE
    };
    
    void buttonCallbackFxn(PIN_Handle handle, PIN_Id pinId) {
        uint32_t currVal = 0;
    
        /* Debounce logic, only toggle if the button is still pushed (low) */
        CPUdelay(8000*50);
        if (!PIN_getInputValue(pinId)) {
            /* Toggle LED based on the button pressed */
            switch (pinId) {
                case Board_BUTTON0:
                    currVal =  PIN_getOutputValue(Board_LED0);
                    PIN_setOutputValue(ledPinHandle, Board_LED0, !currVal);
                    break;
    
                case Board_BUTTON1:
                    currVal =  PIN_getOutputValue(Board_LED1);
                    PIN_setOutputValue(ledPinHandle, Board_LED1, !currVal);
                    break;
    
                default:
                    /* Do nothing */
                    break;
            }
        }
    }
    //
    /////SamG
    /*********************************************************************
     * 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_stateChangeCB(gaprole_States_t newState);
    #ifndef FEATURE_OAD_ONCHIP
    static void SimpleBLEPeripheral_charValueChangeCB(uint8_t paramID);
    #endif //!FEATURE_OAD_ONCHIP
    static void SimpleBLEPeripheral_enqueueMsg(uint8_t event, uint8_t state);
    
    #ifdef FEATURE_OAD
    void SimpleBLEPeripheral_processOadWriteCB(uint8_t event, uint16_t connHandle,
                                               uint8_t *pData);
    #endif //FEATURE_OAD
    
    /*********************************************************************
     * EXTERN FUNCTIONS
     */
    extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);
    
    /*********************************************************************
     * PROFILE CALLBACKS
     */
    
    // GAP Role Callbacks
    static gapRolesCBs_t SimpleBLEPeripheral_gapRoleCBs =
    {
      SimpleBLEPeripheral_stateChangeCB     // Profile State Change Callbacks
    };
    
    // GAP Bond Manager Callbacks
    static gapBondCBs_t simpleBLEPeripheral_BondMgrCBs =
    {
      NULL, // Passcode callback (not used by application)
      NULL  // Pairing / Bonding state Callback (not used by application)
    };
    
    // Simple GATT Profile Callbacks
    #ifndef FEATURE_OAD_ONCHIP
    static simpleProfileCBs_t SimpleBLEPeripheral_simpleProfileCBs =
    {
      SimpleBLEPeripheral_charValueChangeCB // Characteristic value change callback
    };
    #endif //!FEATURE_OAD_ONCHIP
    
    #ifdef FEATURE_OAD
    static oadTargetCBs_t simpleBLEPeripheral_oadCBs =
    {
      SimpleBLEPeripheral_processOadWriteCB // Write Callback.
    };
    #endif //FEATURE_OAD
    
    /*********************************************************************
     * PUBLIC FUNCTIONS
     */
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_createTask
     *
     * @brief   Task creation function for the Simple BLE 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, &sem);
    //  /// SamG
    //
    //  // Open LED pins
    
        ledPinHandle = PIN_open(&ledPinState, ledPinTable);
        buttonPinHandle = PIN_open(&buttonPinState, buttonPinTable);
        if (PIN_registerIntCb(buttonPinHandle, &buttonCallbackFxn) != 0) {
    
            }
        // Open the DIO_0 pin
            dio0PinHandle = PIN_open(&dio0PinState, dio0PinTable);
    //
    //  ///SamG
    #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(Display_Type_LCD, NULL);
    
      // Setup the GAP
      GAP_SetParamValue(TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL);
    
      // Setup the GAP Peripheral Role Profile
      {
        // For all hardware platforms, device starts advertising upon initialization
        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 the enabler is set back to TRUE
        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 GAP Role 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 GAP Characteristics
      GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);
    
      // Set advertising interval
      {
        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
      {
        uint32_t passkey = 0; // passkey "000000"
        uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
        uint8_t mitm = TRUE;
        uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
        uint8_t bonding = TRUE;
    
        GAPBondMgr_SetParameter(GAPBOND_DEFAULT_PASSCODE, sizeof(uint32_t),
                                &passkey);
        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
    
      ///SamG
    //  GGS_AddService(GATT_SERVICE_HANDLE);  // Add GATT service
    //  // Add your custom service
    //  uint8_t uuid[ATT_BT_UUID_SIZE] = { 0xAA, 0xBB, 0xCC, 0xDD };
    //  uint16_t handle;
    //  GATTServApp_AddService(GATT_SERVICE_HANDLE, uuid, &handle);
    ///SamG
      GATTServApp_AddService(GATT_ALL_SERVICES);   // GATT attributes
      DevInfo_AddService();                        // Device Information Service
    
    #ifndef FEATURE_OAD_ONCHIP
      SimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile
    #endif //!FEATURE_OAD_ONCHIP
    
    #ifdef FEATURE_OAD
      VOID OAD_addService();                 // OAD Profile
      OAD_register((oadTargetCBs_t *)&simpleBLEPeripheral_oadCBs);
      hOadQ = Util_constructQueue(&oadQ);
    #endif //FEATURE_OAD
    
    #ifdef IMAGE_INVALIDATE
      Reset_addService();
    #endif //IMAGE_INVALIDATE
    
    
    #ifndef FEATURE_OAD_ONCHIP
      // Setup the SimpleProfile Characteristic Values
      {
        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);
    #endif //!FEATURE_OAD_ONCHIP
    
      // Start the Device
      VOID GAPRole_StartDevice(&SimpleBLEPeripheral_gapRoleCBs);
    
      // Start Bond Manager
      VOID GAPBondMgr_Register(&simpleBLEPeripheral_BondMgrCBs);
    
      // Register with GAP for HCI/Host messages
      GAP_RegisterForMsgs(selfEntity);
    
      // Register for GATT local events and ATT Responses pending for transmission
      GATT_RegisterForMsgs(selfEntity);
    
      HCI_LE_ReadMaxDataLenCmd();
    
    #if defined FEATURE_OAD
    #if defined (HAL_IMAGE_A)
      Display_print0(dispHandle, 0, 0, "BLE Peripheral A");
    #else
      Display_print0(dispHandle, 0, 0, "BLE Peripheral B");
    #endif // HAL_IMAGE_A
    #else
      Display_print0(dispHandle, 0, 0, "BLE Peripheral");
    #endif // FEATURE_OAD
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_taskFxn
     *
     * @brief   Application task entry point for the Simple BLE Peripheral.
     *
     * @param   a0, a1 - not used.
     *
     * @return  None.
     */
    static void SimpleBLEPeripheral_taskFxn(UArg a0, UArg a1)
    {
      // Initialize application
      SimpleBLEPeripheral_init();
      SimpleBLEPeripheral_performPeriodicTask();
      // Application main loop
      for (;;)
      {
        // Waits for a signal to the semaphore associated with the calling thread.
        // Note that the semaphore associated with a thread is signaled when a
        // message is queued to the message receive queue of the thread or when
        // ICall_signal() function is called onto the semaphore.
        ICall_Errno errno = ICall_wait(ICALL_TIMEOUT_FOREVER);
    
        if (errno == ICALL_ERRNO_SUCCESS)
        {
          ICall_EntityID dest;
          ICall_ServiceEnum src;
          ICall_HciExtEvt *pMsg = NULL;
    
          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)
              {
                if (pEvt->event_flag & SBP_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.
          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);
            }
          }
        }
    
        if (events & SBP_PERIODIC_EVT)
        {
          events &= ~SBP_PERIODIC_EVT;
    
          Util_startClock(&periodicClock);
    
          // Perform periodic application task
          SimpleBLEPeripheral_performPeriodicTask();
    
        }
    
    #ifdef FEATURE_OAD
        while (!Queue_empty(hOadQ))
        {
          oadTargetWrite_t *oadWriteEvt = Queue_get(hOadQ);
    
          // Identify new image.
          if (oadWriteEvt->event == OAD_WRITE_IDENTIFY_REQ)
          {
            OAD_imgIdentifyWrite(oadWriteEvt->connHandle, oadWriteEvt->pData);
          }
          // Write a next block request.
          else if (oadWriteEvt->event == OAD_WRITE_BLOCK_REQ)
          {
            OAD_imgBlockWrite(oadWriteEvt->connHandle, oadWriteEvt->pData);
          }
    
          // Free buffer.
          ICall_free(oadWriteEvt);
        }
    #endif //FEATURE_OAD
      }
    }
    
    /*********************************************************************
     * @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
                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_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;
    
        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);
    }
    
    /*********************************************************************
     * @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 sending 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-connectabel 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:
          {
            uint8_t advertReEnable = TRUE;
          
            Util_stopClock(&periodicClock);
            SimpleBLEPeripheral_freeAttRsp(bleNotConnected);
    
            // Clear remaining lines
            Display_clearLines(dispHandle, 3, 5);
    
            GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &advertReEnable);
            Display_print0(dispHandle, 2, 0, "Advertising");
          }
          break;
    
        case GAPROLE_WAITING_AFTER_TIMEOUT:
          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 //#ifdef (PLUS_BROADCASTER)
          break;
    
        case GAPROLE_ERROR:
          Display_print0(dispHandle, 2, 0, "Error");
          break;
    
        default:
          Display_clearLine(dispHandle, 2);
          break;
      }
    
      // Update the state
      //gapProfileState = newState;
    }
    
    #ifndef FEATURE_OAD_ONCHIP
    /*********************************************************************
     * @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);
    }
    #endif //!FEATURE_OAD_ONCHIP
    
    /*********************************************************************
     * @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)
    {
    #ifndef FEATURE_OAD_ONCHIP
      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);
    //      SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR5, sizeof(uint16_t), &newValue);
          ///SamG
          //The below function toggles the LED1 for any change in value
    //      uint32_t currVal = 0;
    //      currVal =  PIN_getOutputValue(Board_LED1);
    //      PIN_setOutputValue(ledPinHandle, Board_LED1, !currVal);
          //The below function toggles the LED1 for conditional change in value, 0 turns OFF, 1 turns on, 2 toggles
          if((uint16_t)newValue==1)
          {
            PIN_setOutputValue(ledPinHandle, Board_LED1, 1);
          }else if((uint16_t)newValue==0)
          {
            PIN_setOutputValue(ledPinHandle, Board_LED1, 0);
          }else if((uint16_t)newValue==2)
          {
              PIN_setOutputValue(dio0PinHandle, Board_DIO0, !PIN_getOutputValue(Board_DIO0));
          }
    
          ///SamG
          Display_print1(dispHandle, 4, 0, "Char 3: %d", (uint16_t)newValue);
          break;
          ///SamG
    //    case SIMPLEPROFILE_CUSTOM_CHAR:
    //            {
    //                // Handle changes to the custom characteristic value
    //                uint8_t value = pValue[0]; // Get the new value
    //
    //                if (value == 1)
    //                {
    //                    // Turn on the LED
    //                    PIN_setOutputValue(ledPinHandle, Board_PIN_LED0, 1);
    //                }
    //                else
    //                {
    //                    // Turn off the LED
    //                    PIN_setOutputValue(ledPinHandle, Board_PIN_LED0, 0);
    //                }
    //            }
    //            break;
    
          ///SamG
        default:
          // should not reach here!
          break;
      }
    #endif //!FEATURE_OAD_ONCHIP
    }
    
    /*********************************************************************
     * @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)
    {
    
        ///SamG
    
    
        ///SamG uncomment the below code
    #ifndef FEATURE_OAD_ONCHIP
    //  uint8_t valueToCopy;
      ///SamG
    
      uint32_t currVal = 0;
      currVal =  PIN_getOutputValue(Board_LED0);
      PIN_setOutputValue(ledPinHandle, Board_LED0, !currVal);
      ///SamG
    
    
    //  // 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);
    //  }
    
    
    #endif //!FEATURE_OAD_ONCHIP
    }
    
    
    #ifdef FEATURE_OAD
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_processOadWriteCB
     *
     * @brief   Process a write request to the OAD profile.
     *
     * @param   event      - event type:
     *                       OAD_WRITE_IDENTIFY_REQ
     *                       OAD_WRITE_BLOCK_REQ
     * @param   connHandle - the connection Handle this request is from.
     * @param   pData      - pointer to data for processing and/or storing.
     *
     * @return  None.
     */
    void SimpleBLEPeripheral_processOadWriteCB(uint8_t event, uint16_t connHandle,
                                               uint8_t *pData)
    {
      oadTargetWrite_t *oadWriteEvt = ICall_malloc( sizeof(oadTargetWrite_t) + \
                                                 sizeof(uint8_t) * OAD_PACKET_SIZE);
    
      if ( oadWriteEvt != NULL )
      {
        oadWriteEvt->event = event;
        oadWriteEvt->connHandle = connHandle;
    
        oadWriteEvt->pData = (uint8_t *)(&oadWriteEvt->pData + 1);
        memcpy(oadWriteEvt->pData, pData, OAD_PACKET_SIZE);
    
        Queue_put(hOadQ, (Queue_Elem *)oadWriteEvt);
    
        // Post the application's semaphore.
        Semaphore_post(sem);
      }
      else
      {
        // Fail silently.
      }
    }
    #endif //FEATURE_OAD
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_clockHandler
     *
     * @brief   Handler function for clock timeouts.
     *
     * @param   arg - event type
     *
     * @return  None.
     */
    static void SimpleBLEPeripheral_clockHandler(UArg arg)
    {
      // Store the event.
      events |= arg;
    
      // Wake up the application.
      Semaphore_post(sem);
    }
    
    /*********************************************************************
     * @fn      SimpleBLEPeripheral_enqueueMsg
     *
     * @brief   Creates a message and puts the message in RTOS queue.
     *
     * @param   event - message event.
     * @param   state - message state.
     *
     * @return  None.
     */
    static void SimpleBLEPeripheral_enqueueMsg(uint8_t event, uint8_t state)
    {
      sbpEvt_t *pMsg;
    
      // Create dynamic pointer to message.
      if ((pMsg = ICall_malloc(sizeof(sbpEvt_t))))
      {
        pMsg->hdr.event = event;
        pMsg->hdr.state = state;
    
        // Enqueue the message.
        Util_enqueueMsg(appMsgQueue, sem, (uint8*)pMsg);
      }
    }
    
    /*********************************************************************
    *********************************************************************/
    

  • Hi,

    Debug your code from main() and see where it hangs.

    -kel

  • Hi Kel,

    I haven't been able to flash or debug from CCS. It always pops up with a message saying Firmware update is needed and then when I confirm, it shows this error: A router subpath could not be accessed. The board configuration file is probably incorrect. (Emulation package 8.1.0.00012) 

    I am very new to all this, so, as a workaround I found in the forum, after building the example code, I use the SmartRF Flash Programmer 2 to program the stack and app hex files. Could that be an issue? The code works for the launchpad flawlessly but doesn't connect to the RSM package chipset. Could the issue be due to the board type?

    Is there a readily available CC2650F128 RSM board file available somewhere that makes this porting seamless?

    -Sam

  • Hi,

    You should use CCSv7 or CCSv8. If for example you can debug using the launchpad and not your custom board then the issue is with your custom board. If SmartRF Flash Programmer 2 can not detect your custom board then you have an issue with your custom board.

    Is there a readily available CC2650F128 RSM board file available somewhere that makes this porting seamless?

    No. Porting to from CC2650 Launchpad to another custom board is just following a set of procedures. You just need to get familiar with it.

    -kel

  • Hi Kel,

    Thanks for the response. I am using CCSV8. Neither the launchpad, nor the custom board is getting flashed using CCS, both showing the same error.  But using the Flash Programmer, both LP and custom board are being detected and code is being uploaded using the hex files generated after the build. Not sure if its an issue with the XDS debugger onboard the LP, as I am using it for uploading both to the LP and the custom board.

    For porting from launchpad to the smaller 4mm*4mm RSM footprint, could you please guide me through some steps that I can follow? The issue is me not being familiar with TI systems at all and trying to frantically search for CC2650 porting steps for 7*7 to 4*4 package migration.

  • Neither the launchpad, nor the custom board is getting flashed using CCS, both showing the same error.

    Not sure the cause. But, can you try CCSv9 and see if it works. Also use SmartRF Flash Programmer 2 version 1.8.0.

    Porting guide below.

    I am using CCSv8.2 and BLE Stack 2.2. Import simple peripheral to your workspace and make sure you have ARM Compiler 5.2.8 or 5.2.9 installed. Set ARM Compiler version at stack and app project, see below. Rebuild all stack then app there should be no errors.

    Delete the board.c at Startup folder.

    Create a new folder "Boards" and copy the 3 board files from this folder location "C:\ti\simplelink\ble_sdk_2_02_07_06\src\boards\CC2650_LAUNCHXL". The reason for this is you would not want the original board files modified.

    Set the include path for the new folder "Boards". Go to project properties->Build->ARM Compiler->Include options and set path to the new folder. You can do this by pressing the + button and set variable PROJECT_LOC and select extend -> Boards. Rebuild all app project.

    Go to CC2650_LAUNCHXL.h and set the correct define for RF Front End Mode and Bias Configuration. for CC2650 Launchpad it is CC2650EM_7ID. If you set this wrong you will have problems with your Bluetooth.

    You can find the defines at ble_user_config.h.

    Go to CC2650_LAUNCHXL.c and comment out the entries at BoardGpioInitTable[]

    Rebuild all app. Flash the stack hex and app hex to your custom board. You should see it advertising using your app. At this point you have a basic Bluetooth application running at your custom board.

    Going back to the board files Board.h, CC2650_LAUNCHXL.c, CC2650_LAUNCHXL.h. These board files are set to work for your CC2650 Launchpad. You need to modify it to work for your custom board. 

    -kel

  • Hi Kel,

    Thank you so much for your detailed response. I followed the steps as you suggested and additionally, made the pins unassigned in CC2650_LAUNCHXL.h.

    I can see the SimpleBLEPeripheral connection being advertised when I check the NRFConnect app, but I still cannot connect to the device or bond to the device at all. I can just see the connection being advertised and its RSSI plot.

    I am confused about editing the board files and am not sure if I am doing something wrong there. Just to get it to connect, I am happy to unassign most of the pins, but I am not sure if I am doing it correctly. I have the board files attached here, where I unassigned the pins and also the GPIO config table as you suggested.

    6014.Board.h

    /*
     * Copyright (c) 2016, 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.
     */
    
    /*
     *  ====================== CC2650_LAUNCHXL.c ===================================
     *  This file is responsible for setting up the board specific items for the
     *  CC2650 LaunchPad.
     */
    
    
    /*
     *  ====================== Includes ============================================
     */
    #include <xdc/std.h>
    #include <xdc/runtime/System.h>
    
    #include <ti/sysbios/family/arm/m3/Hwi.h>
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/pin/PINCC26XX.h>
    #include <ti/drivers/PWM.h>
    #include <ti/drivers/pwm/PWMTimerCC26XX.h>
    #include <ti/drivers/timer/GPTimerCC26XX.h>
    #include <ti/drivers/Power.h>
    #include <ti/drivers/power/PowerCC26XX.h>
    
    #include <inc/hw_memmap.h>
    #include <inc/hw_ints.h>
    #include <driverlib/ioc.h>
    #include <driverlib/udma.h>
    
    #include "Board.h"
    
    /*
     *  ========================= IO driver initialization =========================
     *  From main, PIN_init(BoardGpioInitTable) should be called to setup safe
     *  settings for this board.
     *  When a pin is allocated and then de-allocated, it will revert to the state
     *  configured in this table.
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(BoardGpioInitTable, ".const:BoardGpioInitTable")
    #pragma DATA_SECTION(PINCC26XX_hwAttrs, ".const:PINCC26XX_hwAttrs")
    #endif
    
    const PIN_Config BoardGpioInitTable[] = {
    
    //    Board_RLED   | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,         /* LED initially off             */
    //    Board_GLED   | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,         /* LED initially off             */
    //    Board_BTN1   | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,            /* Button is active low          */
    //    Board_BTN2   | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,            /* Button is active low          */
    //    Board_SPI_FLASH_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MIN,  /* External flash chip select    */
    //    Board_UART_RX | PIN_INPUT_EN | PIN_PULLDOWN,                                              /* UART RX via debugger back channel */
    //    Board_UART_TX | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,                        /* UART TX via debugger back channel */
    //    Board_SPI0_MOSI | PIN_INPUT_EN | PIN_PULLDOWN,                                            /* SPI master out - slave in */
    //    Board_SPI0_MISO | PIN_INPUT_EN | PIN_PULLDOWN,                                            /* SPI master in - slave out */
    //    Board_SPI0_CLK | PIN_INPUT_EN | PIN_PULLDOWN,                                             /* SPI clock */
    
        PIN_TERMINATE
    };
    
    const PINCC26XX_HWAttrs PINCC26XX_hwAttrs = {
        .intPriority = ~0,
        .swiPriority = 0
    };
    /*============================================================================*/
    
    /*
     *  ============================= Power begin ==================================
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(PowerCC26XX_config, ".const:PowerCC26XX_config")
    #endif
    const PowerCC26XX_Config PowerCC26XX_config = {
        .policyInitFxn      = NULL,
        .policyFxn          = &PowerCC26XX_standbyPolicy,
        .calibrateFxn       = &PowerCC26XX_calibrate,
        .enablePolicy       = TRUE,
        .calibrateRCOSC_LF  = TRUE,
        .calibrateRCOSC_HF  = TRUE,
    };
    /*
     *  ============================= Power end ====================================
     */
    
    /*
     *  ============================= UART begin ===================================
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(UART_config, ".const:UART_config")
    #pragma DATA_SECTION(uartCC26XXHWAttrs, ".const:uartCC26XXHWAttrs")
    #endif
    
    /* Include drivers */
    #include <ti/drivers/UART.h>
    #include <ti/drivers/uart/UARTCC26XX.h>
    
    /* UART objects */
    UARTCC26XX_Object uartCC26XXObjects[CC2650_LAUNCHXL_UARTCOUNT];
    
    /* UART hardware parameter structure, also used to assign UART pins */
    const UARTCC26XX_HWAttrsV2 uartCC26XXHWAttrs[CC2650_LAUNCHXL_UARTCOUNT] = {
        {
            .baseAddr       = UART0_BASE,
            .powerMngrId    = PowerCC26XX_PERIPH_UART0,
            .intNum         = INT_UART0_COMB,
            .intPriority    = ~0,
            .swiPriority    = 0,
            .txPin          = Board_UART_TX,
            .rxPin          = Board_UART_RX,
            .ctsPin         = PIN_UNASSIGNED,
            .rtsPin         = PIN_UNASSIGNED
        }
    };
    
    /* UART configuration structure */
    const UART_Config UART_config[] = {
        {
            .fxnTablePtr = &UARTCC26XX_fxnTable,
            .object      = &uartCC26XXObjects[0],
            .hwAttrs     = &uartCC26XXHWAttrs[0]
        },
        {NULL, NULL, NULL}
    };
    /*
     *  ============================= UART end =====================================
     */
    
    /*
     *  ============================= UDMA begin ===================================
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(UDMACC26XX_config, ".const:UDMACC26XX_config")
    #pragma DATA_SECTION(udmaHWAttrs, ".const:udmaHWAttrs")
    #endif
    
    /* Include drivers */
    #include <ti/drivers/dma/UDMACC26XX.h>
    
    /* UDMA objects */
    UDMACC26XX_Object udmaObjects[CC2650_LAUNCHXL_UDMACOUNT];
    
    /* UDMA configuration structure */
    const UDMACC26XX_HWAttrs udmaHWAttrs[CC2650_LAUNCHXL_UDMACOUNT] = {
        {
            .baseAddr    = UDMA0_BASE,
            .powerMngrId = PowerCC26XX_PERIPH_UDMA,
            .intNum      = INT_DMA_ERR,
            .intPriority = ~0
        }
    };
    
    /* UDMA configuration structure */
    const UDMACC26XX_Config UDMACC26XX_config[] = {
        {
             .object  = &udmaObjects[0],
             .hwAttrs = &udmaHWAttrs[0]
        },
        {NULL, NULL}
    };
    /*
     *  ============================= UDMA end =====================================
     */
    
    /*
     *  ========================== SPI DMA begin ===================================
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(SPI_config, ".const:SPI_config")
    #pragma DATA_SECTION(spiCC26XXDMAHWAttrs, ".const:spiCC26XXDMAHWAttrs")
    #endif
    
    /* Include drivers */
    #include <ti/drivers/spi/SPICC26XXDMA.h>
    
    /* SPI objects */
    SPICC26XXDMA_Object spiCC26XXDMAObjects[CC2650_LAUNCHXL_SPICOUNT];
    
    /* SPI configuration structure, describing which pins are to be used */
    const SPICC26XXDMA_HWAttrsV1 spiCC26XXDMAHWAttrs[CC2650_LAUNCHXL_SPICOUNT] = {
        {
            .baseAddr           = SSI0_BASE,
            .intNum             = INT_SSI0_COMB,
            .intPriority        = ~0,
            .swiPriority        = 0,
            .powerMngrId        = PowerCC26XX_PERIPH_SSI0,
            .defaultTxBufValue  = 0,
            .rxChannelBitMask   = 1<<UDMA_CHAN_SSI0_RX,
            .txChannelBitMask   = 1<<UDMA_CHAN_SSI0_TX,
            .mosiPin            = Board_SPI0_MOSI,
            .misoPin            = Board_SPI0_MISO,
            .clkPin             = Board_SPI0_CLK,
            .csnPin             = Board_SPI0_CSN
        },
        {
            .baseAddr           = SSI1_BASE,
            .intNum             = INT_SSI1_COMB,
            .intPriority        = ~0,
            .swiPriority        = 0,
            .powerMngrId        = PowerCC26XX_PERIPH_SSI1,
            .defaultTxBufValue  = 0,
            .rxChannelBitMask   = 1<<UDMA_CHAN_SSI1_RX,
            .txChannelBitMask   = 1<<UDMA_CHAN_SSI1_TX,
            .mosiPin            = Board_SPI1_MOSI,
            .misoPin            = Board_SPI1_MISO,
            .clkPin             = Board_SPI1_CLK,
            .csnPin             = Board_SPI1_CSN
        }
    };
    
    /* SPI configuration structure */
    const SPI_Config SPI_config[] = {
        {
             .fxnTablePtr = &SPICC26XXDMA_fxnTable,
             .object      = &spiCC26XXDMAObjects[0],
             .hwAttrs     = &spiCC26XXDMAHWAttrs[0]
        },
        {
             .fxnTablePtr = &SPICC26XXDMA_fxnTable,
             .object      = &spiCC26XXDMAObjects[1],
             .hwAttrs     = &spiCC26XXDMAHWAttrs[1]
        },
        {NULL, NULL, NULL}
    };
    /*
     *  ========================== SPI DMA end =====================================
    */
    
    
    /*
     *  ============================= I2C Begin=====================================
    */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(I2C_config, ".const:I2C_config")
    #pragma DATA_SECTION(i2cCC26xxHWAttrs, ".const:i2cCC26xxHWAttrs")
    #endif
    
    /* Include drivers */
    #include <ti/drivers/i2c/I2CCC26XX.h>
    
    /* I2C objects */
    I2CCC26XX_Object i2cCC26xxObjects[CC2650_LAUNCHXL_I2CCOUNT];
    
    /* I2C configuration structure, describing which pins are to be used */
    const I2CCC26XX_HWAttrsV1 i2cCC26xxHWAttrs[CC2650_LAUNCHXL_I2CCOUNT] = {
        {
            .baseAddr = I2C0_BASE,
            .powerMngrId = PowerCC26XX_PERIPH_I2C0,
            .intNum = INT_I2C_IRQ,
            .intPriority = ~0,
            .swiPriority = 0,
            .sdaPin = Board_I2C0_SDA0,
            .sclPin = Board_I2C0_SCL0,
        }
    };
    
    /* I2C configuration structure */
    const I2C_Config I2C_config[] = {
        {
            .fxnTablePtr = &I2CCC26XX_fxnTable,
            .object = &i2cCC26xxObjects[0],
            .hwAttrs = &i2cCC26xxHWAttrs[0]
        },
        {NULL, NULL, NULL}
    };
    /*
     *  ========================== I2C end =========================================
     */
    
    /*
     *  ========================== Crypto begin ====================================
     *  NOTE: The Crypto implementation should be considered experimental
     *        and not validated!
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(CryptoCC26XX_config, ".const:CryptoCC26XX_config")
    #pragma DATA_SECTION(cryptoCC26XXHWAttrs, ".const:cryptoCC26XXHWAttrs")
    #endif
    
    /* Include drivers */
    #include <ti/drivers/crypto/CryptoCC26XX.h>
    
    /* Crypto objects */
    CryptoCC26XX_Object cryptoCC26XXObjects[CC2650_LAUNCHXL_CRYPTOCOUNT];
    
    /* Crypto configuration structure, describing which pins are to be used */
    const CryptoCC26XX_HWAttrs cryptoCC26XXHWAttrs[CC2650_LAUNCHXL_CRYPTOCOUNT] = {
        {
            .baseAddr       = CRYPTO_BASE,
            .powerMngrId    = PowerCC26XX_PERIPH_CRYPTO,
            .intNum         = INT_CRYPTO_RESULT_AVAIL_IRQ,
            .intPriority    = ~0,
        }
    };
    
    /* Crypto configuration structure */
    const CryptoCC26XX_Config CryptoCC26XX_config[] = {
        {
             .object  = &cryptoCC26XXObjects[0],
             .hwAttrs = &cryptoCC26XXHWAttrs[0]
        },
        {NULL, NULL}
    };
    /*
     *  ========================== Crypto end ======================================
     */
    
    
    /*
     *  ========================= RF driver begin ==================================
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(RFCC26XX_hwAttrs, ".const:RFCC26XX_hwAttrs")
    #endif
    
    /* Include drivers */
    #include <ti/drivers/rf/RF.h>
    
    /* RF hwi and swi priority */
    const RFCC26XX_HWAttrs RFCC26XX_hwAttrs = {
        .hwiCpe0Priority = ~0,
        .hwiHwPriority   = ~0,
        .swiCpe0Priority =  5,
        .swiHwPriority   =  5,
    };
    
    /*
     *  ========================== RF driver end ===================================
     */
    
    /*
     *  ========================= Display begin ====================================
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(Display_config, ".const:Display_config")
    #pragma DATA_SECTION(displaySharpHWattrs, ".const:displaySharpHWattrs")
    #pragma DATA_SECTION(displayUartHWAttrs, ".const:displayUartHWAttrs")
    #endif
    
    #include <ti/mw/display/Display.h>
    #include <ti/mw/display/DisplaySharp.h>
    #include <ti/mw/display/DisplayUart.h>
    
    /* Structures for UartPlain Blocking */
    DisplayUart_Object        displayUartObject;
    
    #ifndef BOARD_DISPLAY_UART_STRBUF_SIZE
    #define BOARD_DISPLAY_UART_STRBUF_SIZE    128
    #endif
    static char uartStringBuf[BOARD_DISPLAY_UART_STRBUF_SIZE];
    
    const DisplayUart_HWAttrs displayUartHWAttrs = {
        .uartIdx      = Board_UART,
        .baudRate     =     115200,
        .mutexTimeout = BIOS_WAIT_FOREVER,
        .strBuf = uartStringBuf,
        .strBufLen = BOARD_DISPLAY_UART_STRBUF_SIZE,
    };
    
    /* Structures for SHARP */
    DisplaySharp_Object displaySharpObject;
    
    #ifndef BOARD_DISPLAY_SHARP_SIZE
    #define BOARD_DISPLAY_SHARP_SIZE    96 // 96->96x96 is the most common board, alternative is 128->128x128.
    #endif
    static uint8_t sharpDisplayBuf[BOARD_DISPLAY_SHARP_SIZE * BOARD_DISPLAY_SHARP_SIZE / 8];
    
    const DisplaySharp_HWAttrs displaySharpHWattrs = {
        .spiIndex    = Board_SPI0,
        .csPin       = Board_LCD_CS,
        .extcominPin = Board_LCD_EXTCOMIN,
        .powerPin    = Board_LCD_POWER,
        .enablePin   = Board_LCD_ENABLE,
        .pixelWidth  = BOARD_DISPLAY_SHARP_SIZE,
        .pixelHeight = BOARD_DISPLAY_SHARP_SIZE,
        .displayBuf  = sharpDisplayBuf,
    };
    
    /* Array of displays */
    const Display_Config Display_config[] = {
    #if !defined(BOARD_DISPLAY_EXCLUDE_UART)
        {
            .fxnTablePtr = &DisplayUart_fxnTable,
            .object      = &displayUartObject,
            .hwAttrs     = &displayUartHWAttrs,
        },
    #endif
    #if !defined(BOARD_DISPLAY_EXCLUDE_LCD)
        {
            .fxnTablePtr = &DisplaySharp_fxnTable,
            .object      = &displaySharpObject,
            .hwAttrs     = &displaySharpHWattrs
        },
    #endif
        { NULL, NULL, NULL } // Terminator
    };
    
    /*
     *  ========================= Display end ======================================
     */
    
    /*
     *  ============================ GPTimer begin =================================
     *  Remove unused entries to reduce flash usage both in Board.c and Board.h
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(GPTimerCC26XX_config, ".const:GPTimerCC26XX_config")
    #pragma DATA_SECTION(gptimerCC26xxHWAttrs, ".const:gptimerCC26xxHWAttrs")
    #endif
    
    /* GPTimer hardware attributes, one per timer part (Timer 0A, 0B, 1A, 1B..) */
    const GPTimerCC26XX_HWAttrs gptimerCC26xxHWAttrs[CC2650_LAUNCHXL_GPTIMERPARTSCOUNT] = {
        { .baseAddr = GPT0_BASE, .intNum = INT_GPT0A, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT0, .pinMux = GPT_PIN_0A, },
        { .baseAddr = GPT0_BASE, .intNum = INT_GPT0B, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT0, .pinMux = GPT_PIN_0B, },
        { .baseAddr = GPT1_BASE, .intNum = INT_GPT1A, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT1, .pinMux = GPT_PIN_1A, },
        { .baseAddr = GPT1_BASE, .intNum = INT_GPT1B, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT1, .pinMux = GPT_PIN_1B, },
        { .baseAddr = GPT2_BASE, .intNum = INT_GPT2A, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT2, .pinMux = GPT_PIN_2A, },
        { .baseAddr = GPT2_BASE, .intNum = INT_GPT2B, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT2, .pinMux = GPT_PIN_2B, },
        { .baseAddr = GPT3_BASE, .intNum = INT_GPT3A, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT3, .pinMux = GPT_PIN_3A, },
        { .baseAddr = GPT3_BASE, .intNum = INT_GPT3B, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT3, .pinMux = GPT_PIN_3B, },
    };
    
    /*  GPTimer objects, one per full-width timer (A+B) (Timer 0, Timer 1..) */
    GPTimerCC26XX_Object gptimerCC26XXObjects[CC2650_LAUNCHXL_GPTIMERCOUNT];
    
    /* GPTimer configuration (used as GPTimer_Handle by driver and application) */
    const GPTimerCC26XX_Config GPTimerCC26XX_config[CC2650_LAUNCHXL_GPTIMERPARTSCOUNT] = {
        { &gptimerCC26XXObjects[0], &gptimerCC26xxHWAttrs[0], GPT_A },
        { &gptimerCC26XXObjects[0], &gptimerCC26xxHWAttrs[1], GPT_B },
        { &gptimerCC26XXObjects[1], &gptimerCC26xxHWAttrs[2], GPT_A },
        { &gptimerCC26XXObjects[1], &gptimerCC26xxHWAttrs[3], GPT_B },
        { &gptimerCC26XXObjects[2], &gptimerCC26xxHWAttrs[4], GPT_A },
        { &gptimerCC26XXObjects[2], &gptimerCC26xxHWAttrs[5], GPT_B },
        { &gptimerCC26XXObjects[3], &gptimerCC26xxHWAttrs[6], GPT_A },
        { &gptimerCC26XXObjects[3], &gptimerCC26xxHWAttrs[7], GPT_B },
    };
    
    /*
     *  ============================ GPTimer end ===================================
     */
    
    
    
    /*
     *  ============================= PWM begin ====================================
     *  Remove unused entries to reduce flash usage both in Board.c and Board.h
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(PWM_config, ".const:PWM_config")
    #pragma DATA_SECTION(pwmtimerCC26xxHWAttrs, ".const:pwmtimerCC26xxHWAttrs")
    #endif
    
    /* PWM configuration, one per PWM output.   */
    PWMTimerCC26XX_HwAttrs pwmtimerCC26xxHWAttrs[CC2650_LAUNCHXL_PWMCOUNT] = {
        { .pwmPin = Board_PWMPIN0, .gpTimerUnit = Board_GPTIMER0A },
        { .pwmPin = Board_PWMPIN1, .gpTimerUnit = Board_GPTIMER0B },
        { .pwmPin = Board_PWMPIN2, .gpTimerUnit = Board_GPTIMER1A },
        { .pwmPin = Board_PWMPIN3, .gpTimerUnit = Board_GPTIMER1B },
        { .pwmPin = Board_PWMPIN4, .gpTimerUnit = Board_GPTIMER2A },
        { .pwmPin = Board_PWMPIN5, .gpTimerUnit = Board_GPTIMER2B },
        { .pwmPin = Board_PWMPIN6, .gpTimerUnit = Board_GPTIMER3A },
        { .pwmPin = Board_PWMPIN7, .gpTimerUnit = Board_GPTIMER3B },
    };
    
    /* PWM object, one per PWM output */
    PWMTimerCC26XX_Object pwmtimerCC26xxObjects[CC2650_LAUNCHXL_PWMCOUNT];
    
    extern const PWM_FxnTable PWMTimerCC26XX_fxnTable;
    
    /* PWM configuration (used as PWM_Handle by driver and application) */
    const PWM_Config PWM_config[CC2650_LAUNCHXL_PWMCOUNT + 1] = {
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[0], &pwmtimerCC26xxHWAttrs[0] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[1], &pwmtimerCC26xxHWAttrs[1] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[2], &pwmtimerCC26xxHWAttrs[2] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[3], &pwmtimerCC26xxHWAttrs[3] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[4], &pwmtimerCC26xxHWAttrs[4] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[5], &pwmtimerCC26xxHWAttrs[5] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[6], &pwmtimerCC26xxHWAttrs[6] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[7], &pwmtimerCC26xxHWAttrs[7] },
        { NULL,                NULL,                 NULL                 }
    };
    
    
    /*
     *  ============================= PWM end ======================================
     */
    
    /*
     *  ========================== ADCBuf begin =========================================
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(ADCBuf_config, ".const:ADCBuf_config")
    #pragma DATA_SECTION(adcBufCC26xxHWAttrs, ".const:adcBufCC26xxHWAttrs")
    #pragma DATA_SECTION(ADCBufCC26XX_adcChannelLut, ".const:ADCBufCC26XX_adcChannelLut")
    #endif
    
    /* Include drivers */
    #include <ti/drivers/ADCBuf.h>
    #include <ti/drivers/adcbuf/ADCBufCC26XX.h>
    
    /* ADCBuf objects */
    ADCBufCC26XX_Object adcBufCC26xxObjects[CC2650_LAUNCHXL_ADCBufCOUNT];
    
    /*
     *  This table converts a virtual adc channel into a dio and internal analogue input signal.
     *  This table is necessary for the functioning of the adcBuf driver.
     *  Comment out unused entries to save flash.
     *  Dio and internal signal pairs are hardwired. Do not remap them in the table. You may reorder entire entries though.
     *  The mapping of dio and internal signals is package dependent.
     */
    const ADCBufCC26XX_AdcChannelLutEntry ADCBufCC26XX_adcChannelLut[] = {
        {PIN_UNASSIGNED, ADC_COMPB_IN_VDDS},
        {PIN_UNASSIGNED, ADC_COMPB_IN_DCOUPL},
        {PIN_UNASSIGNED, ADC_COMPB_IN_VSS},
        {Board_DIO23_ANALOG, ADC_COMPB_IN_AUXIO7},
        {Board_DIO24_ANALOG, ADC_COMPB_IN_AUXIO6},
        {Board_DIO25_ANALOG, ADC_COMPB_IN_AUXIO5},
        {Board_DIO26_ANALOG, ADC_COMPB_IN_AUXIO4},
        {Board_DIO27_ANALOG, ADC_COMPB_IN_AUXIO3},
        {Board_DIO28_ANALOG, ADC_COMPB_IN_AUXIO2},
        {Board_DIO29_ANALOG, ADC_COMPB_IN_AUXIO1},
        {Board_DIO30_ANALOG, ADC_COMPB_IN_AUXIO0},
    };
    
    const ADCBufCC26XX_HWAttrs adcBufCC26xxHWAttrs[CC2650_LAUNCHXL_ADCBufCOUNT] = {
        {
            .intPriority = ~0,
            .swiPriority = 0,
            .adcChannelLut = ADCBufCC26XX_adcChannelLut,
            .gpTimerUnit = Board_GPTIMER0A,
            .gptDMAChannelMask = 1 << UDMA_CHAN_TIMER0_A,
        }
    };
    
    const ADCBuf_Config ADCBuf_config[] = {
        {&ADCBufCC26XX_fxnTable, &adcBufCC26xxObjects[0], &adcBufCC26xxHWAttrs[0]},
        {NULL, NULL, NULL},
    };
    /*
     *  ========================== ADCBuf end =========================================
     */
    
    
    
    /*
     *  ========================== ADC begin =========================================
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(ADC_config, ".const:ADC_config")
    #pragma DATA_SECTION(adcCC26xxHWAttrs, ".const:adcCC26xxHWAttrs")
    #endif
    
    /* Include drivers */
    #include <ti/drivers/ADC.h>
    #include <ti/drivers/adc/ADCCC26XX.h>
    
    /* ADC objects */
    ADCCC26XX_Object adcCC26xxObjects[CC2650_LAUNCHXL_ADCCOUNT];
    
    
    const ADCCC26XX_HWAttrs adcCC26xxHWAttrs[CC2650_LAUNCHXL_ADCCOUNT] = {
        {
            .adcDIO = Board_DIO23_ANALOG,
            .adcCompBInput = ADC_COMPB_IN_AUXIO7,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = Board_DIO24_ANALOG,
            .adcCompBInput = ADC_COMPB_IN_AUXIO6,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = Board_DIO25_ANALOG,
            .adcCompBInput = ADC_COMPB_IN_AUXIO5,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = Board_DIO26_ANALOG,
            .adcCompBInput = ADC_COMPB_IN_AUXIO4,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = Board_DIO27_ANALOG,
            .adcCompBInput = ADC_COMPB_IN_AUXIO3,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = Board_DIO28_ANALOG,
            .adcCompBInput = ADC_COMPB_IN_AUXIO2,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = Board_DIO29_ANALOG,
            .adcCompBInput = ADC_COMPB_IN_AUXIO1,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = Board_DIO30_ANALOG,
            .adcCompBInput = ADC_COMPB_IN_AUXIO0,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_10P9_MS,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = PIN_UNASSIGNED,
            .adcCompBInput = ADC_COMPB_IN_DCOUPL,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = PIN_UNASSIGNED,
            .adcCompBInput = ADC_COMPB_IN_VSS,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = PIN_UNASSIGNED,
            .adcCompBInput = ADC_COMPB_IN_VDDS,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        }
    };
    
    const ADC_Config ADC_config[] = {
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[0], &adcCC26xxHWAttrs[0]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[1], &adcCC26xxHWAttrs[1]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[2], &adcCC26xxHWAttrs[2]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[3], &adcCC26xxHWAttrs[3]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[4], &adcCC26xxHWAttrs[4]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[5], &adcCC26xxHWAttrs[5]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[6], &adcCC26xxHWAttrs[6]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[7], &adcCC26xxHWAttrs[7]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[8], &adcCC26xxHWAttrs[8]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[9], &adcCC26xxHWAttrs[9]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[10], &adcCC26xxHWAttrs[10]},
        {NULL, NULL, NULL},
    };
    
    /*
     *  ========================== ADC end =========================================
     */
    
    /*
     *  ========================= TRNG begin ====================================
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(TRNGCC26XX_config, ".const:TRNGCC26XX_config")
    #pragma DATA_SECTION(TRNGCC26XXHWAttrs, ".const:TRNGCC26XXHWAttrs")
    #endif
    
    /* Include drivers */
    #include <TRNGCC26XX.h>
    
    /* TRNG objects */
    TRNGCC26XX_Object trngCC26XXObjects[CC2650_LAUNCHXL_TRNGCOUNT];
    
    /* TRNG configuration structure, describing which pins are to be used */
    const TRNGCC26XX_HWAttrs TRNGCC26XXHWAttrs[CC2650_LAUNCHXL_TRNGCOUNT] = {
        {
            .powerMngrId    = PowerCC26XX_PERIPH_TRNG,
        }
    };
    
    /* TRNG configuration structure */
    const TRNGCC26XX_Config TRNGCC26XX_config[] = {
        {
             .object  = &trngCC26XXObjects[0],
             .hwAttrs = &TRNGCC26XXHWAttrs[0]
        },
        {NULL, NULL}
    };
    
    /*
     *  ========================= TRNG end ====================================
     */
    
    7446.CC2650_LAUNCHXL.h

    Another thing is, regarding the RF settings, the launchpad is CC2650EM_7ID, but not sure about the custom board. Here is the schematic of the RF side, ID)where I can see it is differential, but not sure if it would be the same (CC2650EM_ 7ID) or CC2650EM_ 4ID/ CC2650EM_ 4XD, both of which are not included in ble_user_config.h

    Sorry for these stupid questions, I am probably missing out on something very simple. Thanks in advance!

  • I can see the SimpleBLEPeripheral connection being advertised when I check the NRFConnect app, but I still cannot connect to the device or bond to the device at all. I can just see the connection being advertised and its RSSI plot.

    This means you have a problem with your RF circuitry or other issues. I suggest your circuitry be reviewed by a TI Engineer. I refer you to TI

    Regarding the RF Front End Mode and Bias Configuration for example CC2650EM_ 7ID is for CC2650 Launchpad which is "Differential Output External Bias". You can refer to the CC2650 Launchpad schematic diagram.

    CC2650EM_7ID is a reference design https://www.ti.com/tool/CC2650EM-7ID-RD

    -kel

  • Hi Samannoy,

    You can submit your custom board design to SIMPLELINK-2-4GHZ-DESIGN-REVIEWS for further review.  SWRA640 addresses PCB design considerations and SWRU393 provides Board File details.

    Regards,
    Ryan

  • Hi Ryan,

    Thanks for the links. I can think of reaching out for design review. But, what I am confused is that the same board design used to work a couple of years back when an earlier lab member used it, but when I am trying to use it, it is not working (tried the code on multiple pcbs). This makes me wonder if it is at all a board design issue and not the board file issue. Would it be possible for you to review the modified board file codes I have attached in my earlier response and let me know if I am doing something wrong?

    Also, for both the board file and the RF configuration, is there any example that uses 4x4 board version that I can directly refer to, similar to the simple peripheral lp example for 7x7 as in CC2650EM_ 7ID?

    Thanks,

    Sam

  • I do not have a CC2640R2F RSM module with which to verify your file changes.  You should confirm that you are using all the correct dependencies as stated in the SDK Release Notes and obtain the CC2640R2DK_4XS Board Files provided in the Custom Hardware section of the latest BLE-Stack User's Guide.  There are also similar E2E threads you can reference.

    Regards,
    Ryan