Defining Application Behavior

The Sample Applications will often contain simple TI-RTOS tasks with a barebones messaging system between tasks. For more information on how the application tasks works in general, review Introduction.

Directed Advertisements as GATT Server

In BLE5-Stack 2.02.05.00, Privacy is always enabled. Most of the privacy features are handled by the GAP bond manager in the stack. To conserve flash memory, by default, the GAP bond manager does not enable GATT client features. The implication of these disabled GATT client features is that the GAP bond manager will not query the Central Address Resolution characteristic of the remote device.

In order to perform a directed advertisement when the initiator’s address is set to Private Resolvable Address, the peripheral device must read the Central Address Resolution characteristic of its remote device to make sure address resolution is supported. Failure to do so before sending directed advertisements violates the Bluetooth Core Specifications Version 5.2.

By default, sample applications such as simple_peripheral does not define GATT_NO_CLIENT but initializes the GATT Client as shown below:

/*
 * Initialize GATT Client, used by GAPBondMgr to look for RPAO
 * characteristic for network privacy
 */
GATT_InitClient();

Compiler Options

For BLE5-Stack projects, compiler options are generated by SysConfig and stored in the project’s Debug\syscfg folder. compiler.opt: contains a set of options (typically include options and preprocessor defines) to be passed to the compiler when compiling user source files. In the BLE5-Stack, SysConfig is used to generate compile time options to configure BLE5-Stack. For info on configurable SysConfig see BLE5-Stack SysConfig Features.

The .opt files are generated through SysConfig when the project is built. All Bluetooth LE example projects included in the SimpleLink CC13xx/CC26xx SDK come with SysConfig enabled by default (host_test’s SysConfig file is configured such that it cannot be used to make BLE configuration modifications).

The predefined symbols in the .opt files are prefixed with a -D, which is standard commandline prefix notation across all the supported toolchains. Of the predefined symbols in the .opt files, some of them are configurable and some are not. .opt files generated by SysConfig cannot be directly modified but instead must be modified through SysConfig. See Bluetooth Low Energy Application Configuration Parameters and Bluetooth Low Energy Stack Configuration Parameters for reference as to which options are configurable.

The convention to disable a symbol in the .opt files is to put an ‘x’ in front of the name. For example, to disable power management, change -DPOWER_SAVING to -DxPOWER_SAVING. It is also possible to disable a symbol by commenting it out via ‘C - style’ syntax (e.g. /* -DPOWER_SAVING */).

Warning

Changes in an .opt file may not be detected by the compiler/toolchain. It is best to rebuild the entire project when a define is changed.

Linker Options

Linker symbols may need to be set or adjusted at the project level in order to control the memory layout of the generated image. The following procedure describes how to access and modify linker symbols.

CCS

  1. Open Project Properties

  2. Navigate to Build -> ARM Linker -> Command File Preprocessing

  3. Use the buttons highlighted in Figure 107. to add, delete, or edit a linker symbol.

../_images/ccs_linker_opts.png

Figure 107. CCS Linker Symbols

IAR

  1. Open the Project’s Options and select the Linker Category.

  2. Open the Config tab.

  3. View the Configuration File symbol definitions box (see Figure 108.).

  4. Add or edit the preprocessor symbols.

../_images/iar_linker_opts.png

Figure 108. IAR Defined Symbols Box

Creating Additional ICall Enabled Tasks

The objective of this section is to familiarize the programmer with the process of adding an RTOS task that can communicate with the BLE5-Stack. Tasks that call functions within the BLE5-Stack must follow a few additional steps to register with ICall. These details are covered below:

  1. Follow all the steps detailed in Tasks to create a TI-RTOS task.

  2. Open SysConfig -> BLE -> Advanced Settings -> ICALL and add one to the “Max Number of Icall Enabled Tasks” entry.

  3. Modify the task’s init function to register with ICall (explained in ICall Initialization and Registration)

Listing 169. ICall Registration for custom task
1// ******************************************************************
2// N0 STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp
3// ******************************************************************
4// Register the current thread as an ICall dispatcher application
5// so that the application can send and receive messages.
6ICall_registerApp(&selfEntity, &syncEvent);
  1. Modify the task’s main function to pend on syncEvent (explained in ICall Thread Synchronization)

Listing 170. ICall Wait
 1static void NotificationTask_taskFxn(UArg a0, UArg a1)
 2{
 3  // Initialize application
 4  NotificationTask_init();
 5
 6  // Application main loop
 7  for (;;)
 8  {
 9      // Waits for an event to be posted associated with the calling thread.
10      // Note that an event associated with a thread is posted when a
11      // message is queued to the message receive queue of the thread
12      events = Event_pend(syncEvent, Event_Id_NONE, SP_ALL_EVENTS, ICALL_TIMEOUT_FOREVER);
13
14      //...
15  }
16  // ...
17}

Production and Direct Test Mode (PTM, DTM)

This page will describe Production Test Mode (PTM) which allows a CC13xx or CC26xx BLE application in a “single-chip” configuration to temporarily expose the host control interface (HCI) test commands over the serial interface when triggered externally to do so (e.g. holding a GPIO pin low during power up). This test mode allows the device to be connected to a Bluetooth RF Tester in order to run Direct Test Mode (DTM) commands on a production line using the final release firmware, while leaving the UART GPIO pins available for the application to use at all other times. Note that this page only considers UART, and not SPI, as the transport protocol since it uses the least amount of GPIO’s and throughput is not a factor for DTM.

Note

Note: DTM defines two interface methods for controlling the LE PHY: HCI and 2-wire UART. The TI Bluetooth Low Energy protocol stack only supports the HCI method for DTM and PTM.

Direct Test Mode (DTM)

DTM is a standard method for testing BLE devices using the DTM HCI commands. A number of wireless test equipment manufactures, including Anritsu (MT8852B), Keysight and Rhode and Schwarz, make BLE Testers that use this mode. It is very useful to use these testers during development or on the production line in order to verify the RF performance of a BLE system. Complementary to these testers, it is also possible to create your own PC application that sends these DTM commands over the serial link. DTM is very well described in the Bluetooth Core Specifications Version 5.2 Volume 6 Part F. All DTM commands as well as TI Vendor Specific modem test commands are accessible in embedded (single-device) application via API calls as well as over HCI in the Host_Test sample application. Refer to the TI Vendor Specific HCI Guide in the documents folder of the SimpleLink CC13xx/CC26xx SDK.

Production Test Mode (PTM)

One problem with DTM is that it relies on a certain stack configuration (network processor with HCI exposed over UART) in order to work with the testers, though many end-applications don’t use this configuration. This would require the customer, during production, to flash the wireless MCU with a network processor image (e.g., host_test) before testing, and then re-flash with the final product image. To circumvent this, the TI BLE-Stack has implemented a feature called Production Test Mode (PTM), which allows for an embedded software application to support direct test mode without exposing the HCI to the UART pins under normal operation. Note that the pins used for PTM can also be used for an application UART interface. In this case, it is necessary to ensure that the other device that is connected to the UART interface does not run at the same time that DTM is being exercised. If the device powers up and goes into PTM mode (by a GPIO being held high or low or some other stimulus), the UART will then be used for DTM commands. If the device powers up normally and does not go into PTM mode, then the UART can be initialized by the application and used to communicate with the other device. DTM commands can also be called by the embedded BLE application.

To add PTM to the simple_peripheral project follow the steps below:

  1. Open the SysConfig file (double-click on the simple_peripheral.sysconfig file)

  2. Open the BLE tab and enter Advanced Settings

  3. Check the PTM box

This is the only configuration required to enable PTM as checking the PTM box automatically increases the Max Number of ICall Enabled tasks to 4. If you want to enable the NPI packet flow control, this can be done in the NPI panel. The default settings when enabling PTM is shown in the figure below.

../_images/ptm_sysconfig_setup.png

Figure 109. Default settings when enabling PTM.

Tip

When adding PTM mode to the application, it is recommended to change the NPI task to use Task_create(...) as opposed to construct. In this way, the RAM needed by the NPI runtime task stack is consuming RAM that is not used in the application’s default behavior.

In order to determine if a command is accessible via PTM mode, users should refer to the translation tables created in icall_hci_tl.c under the define PTM_MODE.

Optimizing Bluetooth Low Energy Stack Memory Usage

Configuration of the Bluetooth Low Energy protocol stack is essential for maximizing the amount of RAM and flash memory available for the application. Refer to Stack Configurations to configure parameters that impact runtime RAM usage, such as the maximum allowable size and number of PDUs. The TI Bluetooth Low Energy protocol stack is implemented to use a small RAM footprint, and allow the application to control the behavior of the stack by using the runtime ICall heap. For example, an application that only sends one GATT notification per connection event must store only one PDU in the heap, whereas as an application that must send multiple notifications must enqueue multiple PDUs in the heap.

To increase the available flash memory allocated to the application project, minimize the flash usage of the protocol stack by including only Bluetooth Low Energy features required to implement the defined role of the device. The available protocol stack configurable features are described in Stack Configurations. Adding additional features to the protocol stack has the net effect of reducing the amount of flash memory to the application.

Flash optimization

The following tips may be useful for reducing the footprint of the BLE5-Stack. In general, there is a feature vs. flash footprint trade-off. Each of the improvements below offer a cost in terms of feature removal.

  • Verify that your application uses the optimize for flash size compiler optimization settings (default for TI projects).

  • Use only one page of SNV.

  • Remove or exclude debug DISPLAY, Two button menu or other unused drivers from your project.

  • Use the stack library options defined in build_config.opt to pull in the smallest part possible of the library for the given use case. In general, this means a library that implements only one role (e.g. peripheral) with no additional features enabled (i.e. L2CAP CoC). See Stack Configurations.

  • Remove HAL Asserts by removing the EXT_HAL_ASSERT define

RAM optimization

The following tips may be useful for reducing the RAM footprint of the BLE5-Stack. It is important to remember that often removing RAM results in reduced throughput or features, the tradeoffs listed below should be evaluated carefully.

  • If using L2CAP CoC, reference RAM Considerations for defines that may configure L2CAP CoC functionality and their RAM implications

  • Set MAX_NUM_PDU and MAX_PDU_SIZE to reduce the amount of packets that can be queued up by the stack at a time. This will reduce heap consumption.

  • Disable LE Secure Connections pairing if not needed. See LE Secure Connections on how to do this. This will save ECCROMCC26XX_NIST_P256_WORKZONE_LEN_IN_BYTES during pairing. Removing LESC also removes the requirement of having MAX_PDU_SIZE set to 69, this can be overriden in ble_user_config.h to as low as 27.

  • The LE Data Length Extension feature will default to an RX size of 251. If the peer device also supports DLE and a connMaxRxOctets value is negotiated > 27 (default) then the controller will allocate connMaxRxOctets*4. 4 is the number of receive buffers in the controller and is a fixed parameter of the stack. However, connMaxRxOctets can be limited by either disabling Data Length Extension or limiting the max of TX and RX octets. Trimming the values of TX and RX is covered in RAM Considerations when using DLE.

  • Carefully set MAX_NUM_BLE_CONNS. This define has a large affect on the amount of dynamic memory used by the stack. Below is a list of structures that the stack will alloc on initialization based on number of Connections. Each structure is multiplied by MAX_NUM_BLE_CONNS.

    • sizeof(linkDBItem_t) : Link data base entry for each connection

    • sizeof( l2capChannel_t ) : At least one signaling channel for each connection

    • sizeOfLlConnState : Structure to hold connection state

    • sizeOfAllExtConnParam: Structure to hold connection parameters

    • sizeof(dataQ_t) : Each connection’s TX data queue

    • linkParam_t : Central and Peripheral parameters for each connection

    • llCte_t : CTE for each connection if RTLS is used

    • ble5OpCmd_t : Radio operation command for connection

  • Check for heap failures by checking heapmgrMemFail from Debugging Common Heap Issues. If heap failures are occurring, attempt to tune stack build configuration using the features and defines above. See Stack Configurations for options that can be configured in the stack.

  • If heap failures still occur after optimizing the BLE-Stack build, the size of the heap can be increased by reducing the size of static allocation. Static allocation (.bss, .data) includes globally defined buffers, runtime task stacks, and other structures that are instantiated without the use of malloc.

    • Trim task stack sizes by inspecting them using Task –> Detailed view in TI-RTOS Object Viewer. If there is unused space their size can be decreased.

    • The system stack can be reduced in a similar way, its usage is shown under HWI –> Module view in ROV. Changing the system stack size is covered in System Stack.

Warning

The above RAM estimations may vary by release, and are not an exhaustive list. It is intended as a way to allow the developer to profile the RAM requirements based on the desired settings. The best way to estimate RAM usage is to measure it in the field using the techniques covered in Debugging Common Heap Issues

See Check System Flash and RAM Usage With Map File for the procedure to check the size of the configured protocol stack.

Decrease flash consumption of the examples project

The guidelines provided here are based on the simple_peripheral example but can be adapted to any example.

Remove the two buttons menu and display

By removing the two_btn_menu and the display from your project, you can significantly increase the remaining memory available on the device. The guidelines are provided for the simple_peripheral project but this is possible for all examples that use TBM and display.

Here are the guidelines:

  1. Import the simple_peripheral project

  2. Change the IO Capabilities (used for pairing/bonding) of your device. Using SysConfig, go to BLE > Bond Manager > IO Capabilities. Change IO Capabilities in No Display or Input Device

    ../_images/SysConfig_Change_BLE_IO_capabilities.png

    Figure 110. Change the IO capabilities of your device

  3. Modify main.c, simple_peripheral.c and simple_peripheral.h in order to not use the tbm (two buttons menu) and the display:

    • main.c

      • remove the #include of Display.h

      • remove the (extern) declaration of dispHandle

      • modify the AssertHandler() function in order to only spinlock

    • simple_peripheral.c

      • remove the #include of Display.h, board_key.h, two_btn_menu.h, simple_peripheral_menu.h

      • remove the declaration of dispHandle and all the code using it (especially the calls to Display_printf(), Display_clearLine() and Display_clearLines())

      • remove the functions SimplePeripheral_keyChangeHandler(), SimplePeripheral_handleKeys() and SimplePeripheral_menuSwitchCb(). Remove their call too.

      • remove all the calls to tbm_initTwoBtnMenu(), tbm_setItemStatus(), tbm_goTo()

    • simple_peripheral.h

      • remove the declaration of the functions SimplePeripheral_doSelectConn(), SimplePeripheral_doAutoConnect() and SimplePeripheral_doSetConnPhy()

    Here are the diff files (based on SDK 4.10), click the arrow to see all the changes:

    • main.c

      index e8fb465..0616489 100644
      @@ -73,8 +73,6 @@
       icall_userCfg_t user0Cfg = BLE_USER_CFG;
       #endif // USE_DEFAULT_USER_CFG
       
      -#include <ti/display/Display.h>
      -
       /*******************************************************************************
        * MACROS
        */
      @@ -101,8 +99,6 @@ icall_userCfg_t user0Cfg = BLE_USER_CFG;
       
       extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);
       
      -extern Display_Handle dispHandle;
      -
       /*******************************************************************************
        * @fn          Main
        *
      @@ -199,60 +195,7 @@ int main()
        */
       void AssertHandler(uint8 assertCause, uint8 assertSubcause)
       {
      -  // Open the display if the app has not already done so
      -  if ( !dispHandle )
      -  {
      -    dispHandle = Display_open(Display_Type_ANY, NULL);
      -  }
      -
      -  Display_print0(dispHandle, 0, 0, ">>>STACK ASSERT");
      -
      -  // check the assert cause
      -  switch (assertCause)
      -  {
      -    case HAL_ASSERT_CAUSE_OUT_OF_MEMORY:
      -      Display_print0(dispHandle, 0, 0, "***ERROR***");
      -      Display_print0(dispHandle, 2, 0, ">> OUT OF MEMORY!");
      -      break;
      -
      -    case HAL_ASSERT_CAUSE_INTERNAL_ERROR:
      -      // check the subcause
      -      if (assertSubcause == HAL_ASSERT_SUBCAUSE_FW_INERNAL_ERROR)
      -      {
      -        Display_print0(dispHandle, 0, 0, "***ERROR***");
      -        Display_print0(dispHandle, 2, 0, ">> INTERNAL FW ERROR!");
      -      }
      -      else
      -      {
      -        Display_print0(dispHandle, 0, 0, "***ERROR***");
      -        Display_print0(dispHandle, 2, 0, ">> INTERNAL ERROR!");
      -      }
      -      break;
      -
      -    case HAL_ASSERT_CAUSE_ICALL_ABORT:
      -      Display_print0(dispHandle, 0, 0, "***ERROR***");
      -      Display_print0(dispHandle, 2, 0, ">> ICALL ABORT!");
      -      HAL_ASSERT_SPINLOCK;
      -      break;
      -
      -    case HAL_ASSERT_CAUSE_ICALL_TIMEOUT:
      -      Display_print0(dispHandle, 0, 0, "***ERROR***");
      -      Display_print0(dispHandle, 2, 0, ">> ICALL TIMEOUT!");
      -      HAL_ASSERT_SPINLOCK;
      -      break;
      -
      -    case HAL_ASSERT_CAUSE_WRONG_API_CALL:
      -      Display_print0(dispHandle, 0, 0, "***ERROR***");
      -      Display_print0(dispHandle, 2, 0, ">> WRONG API CALL!");
      -      HAL_ASSERT_SPINLOCK;
      -      break;
      -
      -  default:
      -      Display_print0(dispHandle, 0, 0, "***ERROR***");
      -      Display_print0(dispHandle, 2, 0, ">> DEFAULT SPINLOCK!");
      -      HAL_ASSERT_SPINLOCK;
      -  }
      -
      +  HAL_ASSERT_SPINLOCK;
         return;
       }
       
      
    • simple_peripheral.c

      index b0af31a..db7c16c 100644
      @@ -55,8 +55,6 @@
       #include <ti/sysbios/knl/Event.h>
       #include <ti/sysbios/knl/Queue.h>
       
      -#include <ti/display/Display.h>
      -
       #if !(defined __TI_COMPILER_VERSION__)
       #include <intrinsics.h>
       #endif
      @@ -77,11 +75,7 @@
       #endif //USE_RCOSC
       
       #include <ti_drivers_config.h>
      -#include <board_key.h>
      -
      -#include <menu/two_btn_menu.h>
       
      -#include "simple_peripheral_menu.h"
       #include "simple_peripheral.h"
       #include "ti_ble_config.h"
       
      @@ -132,18 +126,6 @@
       // Size of string-converted device address ("0xXXXXXXXXXXXX")
       #define SP_ADDR_STR_SIZE     15
       
      -// Row numbers for two-button menu
      -#define SP_ROW_SEPARATOR_1   (TBM_ROW_APP + 0)
      -#define SP_ROW_STATUS_1      (TBM_ROW_APP + 1)
      -#define SP_ROW_STATUS_2      (TBM_ROW_APP + 2)
      -#define SP_ROW_CONNECTION    (TBM_ROW_APP + 3)
      -#define SP_ROW_ADVSTATE      (TBM_ROW_APP + 4)
      -#define SP_ROW_RSSI          (TBM_ROW_APP + 5)
      -#define SP_ROW_IDA           (TBM_ROW_APP + 6)
      -#define SP_ROW_RPA           (TBM_ROW_APP + 7)
      -#define SP_ROW_DEBUG         (TBM_ROW_APP + 8)
      -#define SP_ROW_AC            (TBM_ROW_APP + 9)
      -
       // For storing the active connections
       #define SP_RSSI_TRACK_CHNLS        1            // Max possible channels can be GAP_BONDINGS_MAX
       #define SP_MAX_RSSI_STORE_DEPTH    5
      @@ -245,9 +227,6 @@ typedef struct
        * GLOBAL VARIABLES
        */
       
      -// Display Interface
      -Display_Handle dispHandle = NULL;
      -
       // Task configuration
       Task_Struct spTask;
       #if defined __TI_COMPILER_VERSION__
      @@ -351,8 +330,6 @@ static void SimplePeripheral_processPairState(spPairStateData_t *pPairState);
       static void SimplePeripheral_processPasscode(spPasscodeData_t *pPasscodeData);
       static void SimplePeripheral_charValueChangeCB(uint8_t paramId);
       static status_t SimplePeripheral_enqueueMsg(uint8_t event, void *pData);
      -static void SimplePeripheral_keyChangeHandler(uint8 keys);
      -static void SimplePeripheral_handleKeys(uint8_t keys);
       static void SimplePeripheral_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg);
       static void SimplePeripheral_initPHYRSSIArray(void);
       static void SimplePeripheral_updatePHYStat(uint16_t eventCode, uint8_t *pMsg);
      @@ -366,8 +343,6 @@ static status_t SimplePeripheral_setPhy(uint16_t connHandle, uint8_t allPhys,
                                               uint8_t txPhy, uint8_t rxPhy,
                                               uint16_t phyOpts);
       static uint8_t SimplePeripheral_clearConnListEntry(uint16_t connHandle);
      -static void SimplePeripheral_menuSwitchCb(tbmMenuObj_t* pMenuObjCurr,
      -                                          tbmMenuObj_t* pMenuObjNext);
       static void SimplePeripheral_connEvtCB(Gap_ConnEventRpt_t *pReport);
       static void SimplePeripheral_processConnEvt(Gap_ConnEventRpt_t *pReport);
       #ifdef PTM_MODE
      @@ -499,10 +474,6 @@ void SimplePeripheral_createTask(void)
        */
       static void SimplePeripheral_init(void)
       {
      -  BLE_LOG_INT_TIME(0, BLE_LOG_MODULE_APP, "APP : ---- init ", SP_TASK_PRIORITY);
      -  // Create the menu
      -  SimplePeripheral_buildMenu();
      -
         // ******************************************************************
         // N0 STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp
         // ******************************************************************
      @@ -601,9 +572,6 @@ static void SimplePeripheral_init(void)
         // Initialize GATT Client
         GATT_InitClient();
       
      -  // Init key debouncer
      -  Board_initKeys(SimplePeripheral_keyChangeHandler);
      -
         // Initialize Connection List
         SimplePeripheral_clearConnListEntry(LINKDB_CONNHANDLE_ALL);
       
      @@ -614,17 +582,6 @@ static void SimplePeripheral_init(void)
         // Initialize array to store connection handle and RSSI values
         SimplePeripheral_initPHYRSSIArray();
       
      -  // The type of display is configured based on the BOARD_DISPLAY_USE...
      -  // preprocessor definitions
      -  dispHandle = Display_open(Display_Type_ANY, NULL);
      -
      -  // Initialize Two-Button Menu module
      -  TBM_SET_TITLE(&spMenuMain, "Simple Peripheral");
      -  tbm_setItemStatus(&spMenuMain, TBM_ITEM_NONE, TBM_ITEM_ALL);
      -
      -  tbm_initTwoBtnMenu(dispHandle, &spMenuMain, 5, SimplePeripheral_menuSwitchCb);
      -  Display_printf(dispHandle, SP_ROW_SEPARATOR_1, 0, "====================");
      -
       #ifdef PTM_MODE
         // Intercept NPI RX events.
         NPITask_registerIncomingRXEventAppCB(simple_peripheral_handleNPIRxInterceptEvent, INTERCEPT);
      @@ -764,17 +721,6 @@ static uint8_t SimplePeripheral_processStackMsg(ICall_Hdr *pMsg)
                 {
                   case HCI_LE_SET_PHY:
                   {
      -              if (pMyMsg->cmdStatus == HCI_ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE)
      -              {
      -                Display_printf(dispHandle, SP_ROW_STATUS_1, 0,
      -                        "PHY Change failure, peer does not support this");
      -              }
      -              else
      -              {
      -                Display_printf(dispHandle, SP_ROW_STATUS_1, 0,
      -                               "PHY Update Status Event: 0x%x",
      -                               pMyMsg->cmdStatus);
      -              }
       
                     SimplePeripheral_updatePHYStat(HCI_LE_SET_PHY, (uint8_t *)pMsg);
                     break;
      @@ -795,22 +741,6 @@ static uint8_t SimplePeripheral_processStackMsg(ICall_Hdr *pMsg)
                 // A Phy Update Has Completed or Failed
                 if (pPUC->BLEEventCode == HCI_BLE_PHY_UPDATE_COMPLETE_EVENT)
                 {
      -            if (pPUC->status != SUCCESS)
      -            {
      -              Display_printf(dispHandle, SP_ROW_STATUS_1, 0,
      -                             "PHY Change failure");
      -            }
      -            else
      -            {
      -              // Only symmetrical PHY is supported.
      -              // rxPhy should be equal to txPhy.
      -              Display_printf(dispHandle, SP_ROW_STATUS_2, 0,
      -                             "PHY Updated to %s",
      -                             (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_1M) ? "1M" :
      -                             (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_2M) ? "2M" :
      -                             (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_CODED) ? "CODED" : "Unexpected PHY Value");
      -            }
      -
                   SimplePeripheral_updatePHYStat(HCI_BLE_PHY_UPDATE_COMPLETE_EVENT, (uint8_t *)pMsg);
                 }
                 break;
      @@ -879,21 +809,6 @@ static uint8_t SimplePeripheral_processStackMsg(ICall_Hdr *pMsg)
        */
       static uint8_t SimplePeripheral_processGATTMsg(gattMsgEvent_t *pMsg)
       {
      -  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_printf(dispHandle, SP_ROW_STATUS_1, 0, "FC Violated: %d", pMsg->msg.flowCtrlEvt.opcode);
      -  }
      -  else if (pMsg->method == ATT_MTU_UPDATED_EVENT)
      -  {
      -    // MTU size updated
      -    Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "MTU Size: %d", pMsg->msg.mtuEvt.MTU);
      -  }
      -
         // Free message payload. Needed only for ATT Protocol messages
         GATT_bm_free(&pMsg->msg, pMsg->method);
       
      @@ -930,7 +845,6 @@ static void SimplePeripheral_processAppMsg(spEvt_t *pMsg)
             break;
       
           case SP_KEY_CHANGE_EVT:
      -      SimplePeripheral_handleKeys(*(uint8_t*)(pMsg->pData));
             break;
       
           case SP_ADV_EVT:
      @@ -1020,8 +934,6 @@ static void SimplePeripheral_processGapMessage(gapEventHdr_t *pMsg)
               // Set Device Info Service Parameter
               DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId);
       
      -        Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Initialized");
      -
               BLE_LOG_INT_TIME(0, BLE_LOG_MODULE_APP, "APP : ---- got GAP_DEVICE_INIT_DONE_EVENT", 0);
               // Setup and start Advertising
               // For more information, see the GAP section in the User's Guide:
      @@ -1075,11 +987,6 @@ static void SimplePeripheral_processGapMessage(gapEventHdr_t *pMsg)
               status = GapAdv_enable(advHandleLongRange, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
               SIMPLEPERIPHERAL_ASSERT(status == SUCCESS);
       
      -        // Display device address
      -        Display_printf(dispHandle, SP_ROW_IDA, 0, "%s Addr: %s",
      -                       (addrMode <= ADDRMODE_RANDOM) ? "Dev" : "ID",
      -                       Util_convertBdAddr2Str(pPkt->devAddr));
      -
               if (addrMode > ADDRMODE_RANDOM)
               {
                 SimplePeripheral_updateRPA();
      @@ -1089,7 +996,6 @@ static void SimplePeripheral_processGapMessage(gapEventHdr_t *pMsg)
                                     READ_RPA_PERIOD, 0, true,
                                     (UArg) &argRpaRead);
               }
      -        tbm_setItemStatus(&spMenuMain, SP_ITEM_AUTOCONNECT, TBM_ITEM_NONE);
             }
       
             break;
      @@ -1100,23 +1006,13 @@ static void SimplePeripheral_processGapMessage(gapEventHdr_t *pMsg)
             gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *)pMsg;
       
             BLE_LOG_INT_TIME(0, BLE_LOG_MODULE_APP, "APP : ---- got GAP_LINK_ESTABLISHED_EVENT", 0);
      -      // Display the amount of current connections
             uint8_t numActive = linkDB_NumActive();
      -      Display_printf(dispHandle, SP_ROW_STATUS_2, 0, "Num Conns: %d",
      -                     (uint16_t)numActive);
       
             if (pPkt->hdr.status == SUCCESS)
             {
               // Add connection to list and start RSSI
               SimplePeripheral_addConn(pPkt->connectionHandle);
       
      -        // Display the address of this connection
      -        Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Connected to %s",
      -                       Util_convertBdAddr2Str(pPkt->devAddr));
      -
      -        // Enable connection selection option
      -        tbm_setItemStatus(&spMenuMain, SP_ITEM_SELECT_CONN,SP_ITEM_AUTOCONNECT);
      -
               // Start Periodic Clock.
               Util_startClock(&clkPeriodic);
             }
      @@ -1139,11 +1035,7 @@ static void SimplePeripheral_processGapMessage(gapEventHdr_t *pMsg)
           {
             gapTerminateLinkEvent_t *pPkt = (gapTerminateLinkEvent_t *)pMsg;
       
      -      // Display the amount of current connections
             uint8_t numActive = linkDB_NumActive();
      -      Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Device Disconnected!");
      -      Display_printf(dispHandle, SP_ROW_STATUS_2, 0, "Num Conns: %d",
      -                     (uint16_t)numActive);
       
             // Remove the connection from the list and disable RSSI if needed
             SimplePeripheral_removeConn(pPkt->connectionHandle);
      @@ -1153,9 +1045,6 @@ static void SimplePeripheral_processGapMessage(gapEventHdr_t *pMsg)
             {
               // Stop periodic clock
               Util_stopClock(&clkPeriodic);
      -
      -        // Disable Connection Selection option
      -        tbm_setItemStatus(&spMenuMain, SP_ITEM_AUTOCONNECT, SP_ITEM_SELECT_CONN);
             }
       
             BLE_LOG_INT_STR(0, BLE_LOG_MODULE_APP, "APP : GAP msg: status=%d, opcode=%s\n", 0, "GAP_LINK_TERMINATED_EVENT");
      @@ -1163,9 +1052,6 @@ static void SimplePeripheral_processGapMessage(gapEventHdr_t *pMsg)
             GapAdv_enable(advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
             GapAdv_enable(advHandleLongRange, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
       
      -      // Clear remaining lines
      -      Display_clearLine(dispHandle, SP_ROW_CONNECTION);
      -
             break;
           }
       
      @@ -1207,20 +1093,6 @@ static void SimplePeripheral_processGapMessage(gapEventHdr_t *pMsg)
             linkDBInfo_t linkInfo;
             linkDB_GetInfo(pPkt->connectionHandle, &linkInfo);
       
      -      if(pPkt->status == SUCCESS)
      -      {
      -        // Display the address of the connection update
      -        Display_printf(dispHandle, SP_ROW_STATUS_2, 0, "Link Param Updated: %s",
      -                       Util_convertBdAddr2Str(linkInfo.addr));
      -      }
      -      else
      -      {
      -        // Display the address of the connection update failure
      -        Display_printf(dispHandle, SP_ROW_STATUS_2, 0,
      -                       "Link Param Update Failed 0x%x: %s", pPkt->opcode,
      -                       Util_convertBdAddr2Str(linkInfo.addr));
      -      }
      -
             // Check if there are any queued parameter updates
             spConnHandleEntry_t *connHandleEntry = (spConnHandleEntry_t *)List_get(&paramUpdateList);
             if (connHandleEntry != NULL)
      @@ -1236,7 +1108,6 @@ static void SimplePeripheral_processGapMessage(gapEventHdr_t *pMsg)
           }
       
           default:
      -      Display_clearLines(dispHandle, SP_ROW_STATUS_1, SP_ROW_STATUS_2);
             break;
         }
       }
      @@ -1282,14 +1153,10 @@ static void SimplePeripheral_processCharValueChangeEvt(uint8_t paramId)
         {
           case SIMPLEPROFILE_CHAR1:
             SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR1, &newValue);
      -
      -      Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Char 1: %d", (uint16_t)newValue);
             break;
       
           case SIMPLEPROFILE_CHAR3:
             SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR3, &newValue);
      -
      -      Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Char 3: %d", (uint16_t)newValue);
             break;
       
           default:
      @@ -1330,7 +1197,7 @@ static void SimplePeripheral_performPeriodicTask(void)
       /*********************************************************************
        * @fn      SimplePeripheral_updateRPA
        *
      - * @brief   Read the current RPA from the stack and update display
      + * @brief   Read the current RPA from the stack
        *          if the RPA has changed.
        *
        * @param   None.
      @@ -1347,8 +1214,6 @@ static void SimplePeripheral_updateRPA(void)
         if (memcmp(pRpaNew, rpa, B_ADDR_LEN))
         {
           // If the RPA has changed, update the display
      -    Display_printf(dispHandle, SP_ROW_RPA, 0, "RP Addr: %s",
      -                   Util_convertBdAddr2Str(pRpaNew));
           memcpy(rpa, pRpaNew, B_ADDR_LEN);
         }
       }
      @@ -1389,59 +1254,6 @@ static void SimplePeripheral_clockHandler(UArg arg)
        }
       }
       
      -/*********************************************************************
      - * @fn      SimplePeripheral_keyChangeHandler
      - *
      - * @brief   Key event handler function
      - *
      - * @param   keys - bitmap of pressed keys
      - *
      - * @return  none
      - */
      -static void SimplePeripheral_keyChangeHandler(uint8_t keys)
      -{
      -  uint8_t *pValue = ICall_malloc(sizeof(uint8_t));
      -
      -  if (pValue)
      -  {
      -    *pValue = keys;
      -
      -    if(SimplePeripheral_enqueueMsg(SP_KEY_CHANGE_EVT, pValue) != SUCCESS)
      -    {
      -      ICall_free(pValue);
      -    }
      -  }
      -}
      -
      -/*********************************************************************
      - * @fn      SimplePeripheral_handleKeys
      - *
      - * @brief   Handles all key events for this device.
      - *
      - * @param   keys - bit field for key events. Valid entries:
      - *                 KEY_LEFT
      - *                 KEY_RIGHT
      - */
      -static void SimplePeripheral_handleKeys(uint8_t keys)
      -{
      -  if (keys & KEY_LEFT)
      -  {
      -    // Check if the key is still pressed. Workaround for possible bouncing.
      -    if (PIN_getInputValue(CONFIG_PIN_BTN1) == 0)
      -    {
      -      tbm_buttonLeft();
      -    }
      -  }
      -  else if (keys & KEY_RIGHT)
      -  {
      -    // Check if the key is still pressed. Workaround for possible bouncing.
      -    if (PIN_getInputValue(CONFIG_PIN_BTN2) == 0)
      -    {
      -      tbm_buttonRight();
      -    }
      -  }
      -}
      -
       /*********************************************************************
        * @fn      SimplePeripheral_doSetConnPhy
        *
      @@ -1468,7 +1280,6 @@ bool SimplePeripheral_doSetConnPhy(uint8 index)
         uint8_t connIndex = SimplePeripheral_getConnIndex(menuConnHandle);
         if (connIndex >= MAX_NUM_BLE_CONNS)
         {
      -    Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Connection handle is not in the connList !!!");
           return FALSE;
         }
       
      @@ -1483,9 +1294,6 @@ bool SimplePeripheral_doSetConnPhy(uint8 index)
           SimplePeripheral_stopAutoPhyChange(connList[connIndex].connHandle);
       
           SimplePeripheral_setPhy(menuConnHandle, 0, phy[index], phy[index], 0);
      -
      -    Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "PHY preference: %s",
      -                   TBM_GET_ACTION_DESC(&spMenuConnPhy, index));
         }
         else
         {
      @@ -1531,13 +1339,9 @@ static void SimplePeripheral_processAdvEvent(spGapAdvEventData_t *pEventData)
         {
           case GAP_EVT_ADV_START_AFTER_ENABLE:
             BLE_LOG_INT_TIME(0, BLE_LOG_MODULE_APP, "APP : ---- GAP_EVT_ADV_START_AFTER_ENABLE", 0);
      -      Display_printf(dispHandle, SP_ROW_ADVSTATE, 0, "Adv Set %d Enabled",
      -                     *(uint8_t *)(pEventData->pBuf));
             break;
       
           case GAP_EVT_ADV_END_AFTER_DISABLE:
      -      Display_printf(dispHandle, SP_ROW_ADVSTATE, 0, "Adv Set %d Disabled",
      -                     *(uint8_t *)(pEventData->pBuf));
             break;
       
           case GAP_EVT_ADV_START:
      @@ -1547,15 +1351,7 @@ static void SimplePeripheral_processAdvEvent(spGapAdvEventData_t *pEventData)
             break;
       
           case GAP_EVT_ADV_SET_TERMINATED:
      -    {
      -#ifndef Display_DISABLE_ALL
      -      GapAdv_setTerm_t *advSetTerm = (GapAdv_setTerm_t *)(pEventData->pBuf);
      -
      -      Display_printf(dispHandle, SP_ROW_ADVSTATE, 0, "Adv Set %d disabled after conn %d",
      -                     advSetTerm->handle, advSetTerm->connHandle );
      -#endif
      -    }
      -    break;
      +      break;
       
           case GAP_EVT_SCAN_REQ_RECEIVED:
             break;
      @@ -1645,45 +1441,19 @@ static void SimplePeripheral_passcodeCb(uint8_t *pDeviceAddr,
       static void SimplePeripheral_processPairState(spPairStateData_t *pPairData)
       {
         uint8_t state = pPairData->state;
      -  uint8_t status = pPairData->status;
       
         switch (state)
         {
           case GAPBOND_PAIRING_STATE_STARTED:
      -      Display_printf(dispHandle, SP_ROW_CONNECTION, 0, "Pairing started");
             break;
       
           case GAPBOND_PAIRING_STATE_COMPLETE:
      -      if (status == SUCCESS)
      -      {
      -        Display_printf(dispHandle, SP_ROW_CONNECTION, 0, "Pairing success");
      -      }
      -      else
      -      {
      -        Display_printf(dispHandle, SP_ROW_CONNECTION, 0, "Pairing fail: %d", status);
      -      }
             break;
       
           case GAPBOND_PAIRING_STATE_ENCRYPTED:
      -      if (status == SUCCESS)
      -      {
      -        Display_printf(dispHandle, SP_ROW_CONNECTION, 0, "Encryption success");
      -      }
      -      else
      -      {
      -        Display_printf(dispHandle, SP_ROW_CONNECTION, 0, "Encryption failed: %d", status);
      -      }
             break;
       
           case GAPBOND_PAIRING_STATE_BOND_SAVED:
      -      if (status == SUCCESS)
      -      {
      -        Display_printf(dispHandle, SP_ROW_CONNECTION, 0, "Bond save success");
      -      }
      -      else
      -      {
      -        Display_printf(dispHandle, SP_ROW_CONNECTION, 0, "Bond save failed: %d", status);
      -      }
             break;
       
           default:
      @@ -1700,13 +1470,6 @@ static void SimplePeripheral_processPairState(spPairStateData_t *pPairData)
        */
       static void SimplePeripheral_processPasscode(spPasscodeData_t *pPasscodeData)
       {
      -  // Display passcode to user
      -  if (pPasscodeData->uiOutputs != 0)
      -  {
      -    Display_printf(dispHandle, SP_ROW_CONNECTION, 0, "Passcode: %d",
      -                   B_APP_DEFAULT_PASSCODE);
      -  }
      -
         // Send passcode response
         GAPBondMgr_PasscodeRsp(pPasscodeData->connHandle , SUCCESS,
                                B_APP_DEFAULT_PASSCODE);
      @@ -1740,12 +1503,6 @@ static void SimplePeripheral_processConnEvt(Gap_ConnEventRpt_t *pReport)
         // Get index from handle
         uint8_t connIndex = SimplePeripheral_getConnIndex(pReport->handle);
       
      -  if (connIndex >= MAX_NUM_BLE_CONNS)
      -  {
      -    Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Connection handle is not in the connList !!!");
      -    return;
      -  }
      -
         // If auto phy change is enabled
         if (connList[connIndex].isAutoPHYEnable == TRUE)
         {
      @@ -1782,29 +1539,6 @@ static status_t SimplePeripheral_enqueueMsg(uint8_t event, void *pData)
         return(bleMemAllocError);
       }
       
      -/*********************************************************************
      - * @fn      SimplePeripheral_doSelectConn
      - *
      - * @brief   Select a connection to communicate with
      - *
      - * @param   index - item index from the menu
      - *
      - * @return  always true
      - */
      -bool SimplePeripheral_doSelectConn(uint8_t index)
      -{
      -  menuConnHandle = connList[index].connHandle;
      -
      -  // Set the menu title and go to this connection's context
      -  TBM_SET_TITLE(&spMenuPerConn, TBM_GET_ACTION_DESC(&spMenuSelectConn, index));
      -
      -  // Clear non-connection-related message
      -  Display_clearLine(dispHandle, SP_ROW_CONNECTION);
      -
      -  tbm_goTo(&spMenuPerConn);
      -
      -  return (true);
      -}
       /*********************************************************************
        * @fn      SimplePeripheral_doAutoConnect
        *
      @@ -1832,7 +1566,6 @@ bool SimplePeripheral_doAutoConnect(uint8_t index)
               GapAdv_enable(advHandleLongRange, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
               autoConnect = AUTOCONNECT_GROUP_A;
             }	
      -	  Display_printf(dispHandle, SP_ROW_AC, 0, "AutoConnect enabled: Group A");
           }
           else if (index == 2)
           {
      @@ -1848,7 +1581,6 @@ bool SimplePeripheral_doAutoConnect(uint8_t index)
               GapAdv_enable(advHandleLongRange, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
               autoConnect = AUTOCONNECT_GROUP_B;
             } 
      -      Display_printf(dispHandle, SP_ROW_AC, 0, "AutoConnect enabled: Group B");
           }
           else
           {
      @@ -1864,9 +1596,7 @@ bool SimplePeripheral_doAutoConnect(uint8_t index)
               GapAdv_enable(advHandleLongRange, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
               autoConnect = AUTOCONNECT_DISABLE;
             } 
      -      Display_printf(dispHandle, SP_ROW_AC, 0, "AutoConnect disabled");
           }
      -    tbm_goTo(&spMenuMain);
           
           return (true);
       }
      @@ -2086,7 +1816,6 @@ static void SimplePeripheral_processParamUpdate(uint16_t connHandle)
         connIndex = SimplePeripheral_getConnIndex(connHandle);
         if (connIndex >= MAX_NUM_BLE_CONNS)
         {
      -    Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Connection handle is not in the connList !!!");
           return;
         }
       
      @@ -2146,7 +1875,6 @@ static void SimplePeripheral_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg)
               uint8_t index = SimplePeripheral_getConnIndex(handle);
               if (index >= MAX_NUM_BLE_CONNS)
               {
      -          Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Connection handle is not in the connList !!!");
                 return;
               }
       
      @@ -2234,24 +1962,12 @@ static void SimplePeripheral_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg)
                 } // end of if (connList[index].phyCngRq == FALSE)
               } // end of if (rssi != LL_RSSI_NOT_AVAILABLE)
       
      -        Display_printf(dispHandle, SP_ROW_RSSI, 0,
      -                       "RSSI:%d dBm, AVG RSSI:%d dBm",
      -                       (uint32_t)(rssi),
      -                       connList[index].rssiAvg);
      -
      -	  } // end of if (status == SUCCESS)
      +      } // end of if (status == SUCCESS)
             break;
           }
       
           case HCI_LE_READ_PHY:
      -    {
      -      if (status == SUCCESS)
      -      {
      -        Display_printf(dispHandle, SP_ROW_RSSI + 2, 0, "RXPh: %d, TXPh: %d",
      -                       pMsg->pReturnParam[3], pMsg->pReturnParam[4]);
      -      }
             break;
      -    }
       
           default:
             break;
      @@ -2451,79 +2167,5 @@ static void SimplePeripheral_updatePHYStat(uint16_t eventCode, uint8_t *pMsg)
         } // end of switch (eventCode)
       }
       
      -/*********************************************************************
      - * @fn      SimplePeripheral_menuSwitchCb
      - *
      - * @brief   Detect menu context switching
      - *
      - * @param   pMenuObjCurr - the current menu object
      - * @param   pMenuObjNext - the menu object the context is about to switch to
      - *
      - * @return  none
      - */
      -static void SimplePeripheral_menuSwitchCb(tbmMenuObj_t* pMenuObjCurr,
      -                                       tbmMenuObj_t* pMenuObjNext)
      -{
      -  uint8_t NUMB_ACTIVE_CONNS = linkDB_NumActive();
      -
      -  // interested in only the events of
      -  // entering scMenuConnect, spMenuSelectConn, and scMenuMain for now
      -  if (pMenuObjNext == &spMenuSelectConn)
      -  {
      -    static uint8_t* pAddrs;
      -    uint8_t* pAddrTemp;
      -
      -    if (pAddrs != NULL)
      -    {
      -      ICall_free(pAddrs);
      -    }
      -
      -    // Allocate buffer to display addresses
      -    pAddrs = ICall_malloc(NUMB_ACTIVE_CONNS * SP_ADDR_STR_SIZE);
      -
      -    if (pAddrs == NULL)
      -    {
      -      TBM_SET_NUM_ITEM(&spMenuSelectConn, 0);
      -    }
      -    else
      -    {
      -      uint8_t i;
      -
      -      TBM_SET_NUM_ITEM(&spMenuSelectConn, MAX_NUM_BLE_CONNS);
      -
      -      pAddrTemp = pAddrs;
      -
      -      // Add active connection info to the menu object
      -      for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
      -      {
      -        if (connList[i].connHandle != LINKDB_CONNHANDLE_INVALID)
      -        {
      -          // Get the address from the connection handle
      -          linkDBInfo_t linkInfo;
      -          linkDB_GetInfo(connList[i].connHandle, &linkInfo);
      -          // This connection is active. Set the corresponding menu item with
      -          // the address of this connection and enable the item.
      -          memcpy(pAddrTemp, Util_convertBdAddr2Str(linkInfo.addr),
      -                 SP_ADDR_STR_SIZE);
      -          TBM_SET_ACTION_DESC(&spMenuSelectConn, i, pAddrTemp);
      -          tbm_setItemStatus(&spMenuSelectConn, (1 << i), SP_ITEM_NONE);
      -          pAddrTemp += SP_ADDR_STR_SIZE;
      -        }
      -        else
      -        {
      -          // This connection is not active. Disable the corresponding menu item.
      -          tbm_setItemStatus(&spMenuSelectConn, SP_ITEM_NONE, (1 << i));
      -        }
      -      }
      -    }
      -  }
      -  else if (pMenuObjNext == &spMenuMain)
      -  {
      -    // Now we are not in a specific connection's context
      -
      -    // Clear connection-related message
      -    Display_clearLine(dispHandle, SP_ROW_CONNECTION);
      -  }
      -}
       /*********************************************************************
       *********************************************************************/
      
    • simple_peripheral.h

      index c5914a5..d5393fc 100644
      @@ -79,18 +79,6 @@ extern "C"
        */
       extern void SimplePeripheral_createTask(void);
       
      -/*
      - * Functions for menu action
      - */
      -/* Actions for Menu: Choose connection to work with */
      -bool SimplePeripheral_doSelectConn(uint8 index);
      -
      -/* Action for Menu: AutoConnect */
      -bool SimplePeripheral_doAutoConnect(uint8_t index);
      -
      -/* Actions for Menu: Set PHY - Select */
      -bool SimplePeripheral_doSetConnPhy(uint8 index);
      -
       /*********************************************************************
       *********************************************************************/
       
      
  4. [Optional] The following files can be removed from the Application folder:

    • board_key.c

    • board_key.h

    • simple_peripheral_menu.c

    • simple_peripheral_menu.h

    • two_btn_menu.c

    • two_btn_menu.h

  5. Test your code. It should still compile and work smoothly! It means you can still advertise, join a connection, pair with another device, etc…

Remove the #2 (long range) advertisement

By removing the secondary advertisement (sometimes called “long range” advertisement) from the simple_peripheral example you can significantly save power. The power consumption due to the secondary advertisement (generally long range advertisement) can represent up to 80% of the power consumption of the advertisement period. In addition, this helps you to save memory.

Here are the guidelines:

  1. Import the simple_peripheral project

  2. Using SysConfig, reduce the number of Advertisement Set to only 1 (this must be done in BLE > Broadcaster Configuration). This will raise a warning saying we need to update the application code… this is what we are going to do now :)

    ../_images/sysCfg_changeAdvSetNumber.png

    Figure 111. Change the number of advertisement sets of your device

    Note: It is perfectly normal and expected if the compilation of your project fails after this step… be patient and go to the next steps.

  3. Modify simple_peripheral.c to remove the code related to the #2 advertisement.

    • remove the declaration of the variable advHandleLongRange

    • remove all the code referencing the variable advHandleLongRange

    • remove all the code referencing the table advData2

    Here is simple_peripheral.c diff file (based on SDK 4.10), click the arrow to see the changes:

    index b0af31a..4884d0b 100644
    @@ -317,7 +317,6 @@ uint8_t autoConnect = AUTOCONNECT_DISABLE;
     
     // Advertising handles
     static uint8 advHandleLegacy;
    -static uint8 advHandleLongRange;
     
     // Address mode
     static GAP_Addr_Modes_t addrMode = DEFAULT_ADDRESS_MODE;
    @@ -1053,28 +1052,6 @@ static void SimplePeripheral_processGapMessage(gapEventHdr_t *pMsg)
             status = GapAdv_enable(advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
             SIMPLEPERIPHERAL_ASSERT(status == SUCCESS);
     
    -        BLE_LOG_INT_INT(0, BLE_LOG_MODULE_APP, "APP : ---- call GapAdv_create set=%d,%d\n", 1, 0);
    -        // Create Advertisement set #2 and assign handle
    -        status = GapAdv_create(&SimplePeripheral_advCallback, &advParams2,
    -                               &advHandleLongRange);
    -        SIMPLEPERIPHERAL_ASSERT(status == SUCCESS);
    -
    -        // Load advertising data for set #2 that is statically allocated by the app
    -        status = GapAdv_loadByHandle(advHandleLongRange, GAP_ADV_DATA_TYPE_ADV,
    -                                     sizeof(advData2), advData2);
    -        SIMPLEPERIPHERAL_ASSERT(status == SUCCESS);
    -
    -        // Set event mask for set #2
    -        status = GapAdv_setEventMask(advHandleLongRange,
    -                                     GAP_ADV_EVT_MASK_START_AFTER_ENABLE |
    -                                     GAP_ADV_EVT_MASK_END_AFTER_DISABLE |
    -                                     GAP_ADV_EVT_MASK_SET_TERMINATED);
    -
    -        BLE_LOG_INT_TIME(0, BLE_LOG_MODULE_APP, "APP : ---- GapAdv_enable", 0);
    -        // Enable long range advertising for set #2
    -        status = GapAdv_enable(advHandleLongRange, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
    -        SIMPLEPERIPHERAL_ASSERT(status == SUCCESS);
    -
             // Display device address
             Display_printf(dispHandle, SP_ROW_IDA, 0, "%s Addr: %s",
                            (addrMode <= ADDRMODE_RANDOM) ? "Dev" : "ID",
    @@ -1124,12 +1101,10 @@ static void SimplePeripheral_processGapMessage(gapEventHdr_t *pMsg)
           {
             // Start advertising since there is room for more connections
             GapAdv_enable(advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
    -        GapAdv_enable(advHandleLongRange, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
           }
           else
           {
             // Stop advertising since there is no room for more connections
    -        GapAdv_disable(advHandleLongRange);
             GapAdv_disable(advHandleLegacy);
           }
           break;
    @@ -1161,7 +1136,6 @@ static void SimplePeripheral_processGapMessage(gapEventHdr_t *pMsg)
           BLE_LOG_INT_STR(0, BLE_LOG_MODULE_APP, "APP : GAP msg: status=%d, opcode=%s\n", 0, "GAP_LINK_TERMINATED_EVENT");
           // Start advertising since there is room for more connections
           GapAdv_enable(advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
    -      GapAdv_enable(advHandleLongRange, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
     
           // Clear remaining lines
           Display_clearLine(dispHandle, SP_ROW_CONNECTION);
    @@ -1822,14 +1796,10 @@ bool SimplePeripheral_doAutoConnect(uint8_t index)
         {
           if (autoConnect != AUTOCONNECT_GROUP_A)
           {
    -        GapAdv_disable(advHandleLongRange);
             GapAdv_disable(advHandleLegacy);
             advData1[2] = 'G';
             advData1[3] = 'A';
    -        advData2[2] = 'G';
    -        advData2[3] = 'A';
             GapAdv_enable(advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
    -        GapAdv_enable(advHandleLongRange, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
             autoConnect = AUTOCONNECT_GROUP_A;
           }	
     	  Display_printf(dispHandle, SP_ROW_AC, 0, "AutoConnect enabled: Group A");
    @@ -1838,14 +1808,10 @@ bool SimplePeripheral_doAutoConnect(uint8_t index)
         {
           if (autoConnect != AUTOCONNECT_GROUP_B)
           {
    -        GapAdv_disable(advHandleLongRange);
             GapAdv_disable(advHandleLegacy);
             advData1[2] = 'G';
             advData1[3] = 'B';
    -        advData2[2] = 'G';
    -        advData2[3] = 'B';
             GapAdv_enable(advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
    -        GapAdv_enable(advHandleLongRange, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
             autoConnect = AUTOCONNECT_GROUP_B;
           } 
           Display_printf(dispHandle, SP_ROW_AC, 0, "AutoConnect enabled: Group B");
    @@ -1854,14 +1820,10 @@ bool SimplePeripheral_doAutoConnect(uint8_t index)
         {
           if (autoConnect)
           {
    -        GapAdv_disable(advHandleLongRange);
             GapAdv_disable(advHandleLegacy);
             advData1[2] = 'S';
             advData1[3] = 'P';
    -        advData2[2] = 'S';
    -        advData2[3] = 'P';
             GapAdv_enable(advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
    -        GapAdv_enable(advHandleLongRange, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
             autoConnect = AUTOCONNECT_DISABLE;
           } 
           Display_printf(dispHandle, SP_ROW_AC, 0, "AutoConnect disabled");
    
  4. Build and test your project… You might have a warning due to SysConfig (this warning only appears if SysConfig is run, i.e. if you modify the content of the SysConfig file or if you “Rebuild” the project). Apart from that, no warning or error should be raised at build time and the project should still work smoothly! It means you can still advertise (legacy advertisement only), join a connection, pair with another device, etc…

Remove the auto-PHY update

The auto-PHY update is a feature provided by the application and consisting in dynamically change the PHY used by the BLE stack to handle a connection. The PHY is selected based on the RSSI measured. The better the RSSI, the faster the PHY selected is (e.g. if the RSSI is -25, then the 2M PHY will be selected, if the RSSI is -65 then the S8 PHY will be selected). This functionality is available in the simple_peripheral project and has to be activated using the two buttons menu. Other projects provide this functionality too.

This modification should free up some FLASH and some CPU time. The amount of stack required by the example should be decreased too. The goal is to remove the code responsible for the auto-PHY update. As the auto-PHY update is based on RSSI, we are also going to remove the code responsible to read the RSSI of the connection.

Here are the guidelines:

  1. Import the simple_peripheral project

  2. Modify simple_peripheral.c and simple_peripheral_menu.c:

    • In simple_peripheral.c:

      • Remove the function SimplePeripheral_processCmdCompleteEvt and its calls

      • Remove the function SimplePeripheral_initPHYRSSIArray() and its calls

      • Remove the function SimplePeripheral_startAutoPhyChange() and its calls.

      • Remove the function SimplePeripheral_stopAutoPhyChange() and its calls

      • Remove the function SimplePeripheral_updatePHYStat() and its calls

      • Modify the function SimplePeripheral_doSetConnPhy() in order to remove the support of the AUTO_PHY_UPDATE

      • Remove the callback function SimplePeripheral_connEvtCB()

      • Remove the RSSI thresholds defined (this does not save any FLASH or RAM but it these defines are useless now). Same remark for SP_MAX_RSSI_STORE_DEPTH, SP_RSSI_TRACK_CHNLS. You can also remove all the define related to auto-phy update: SP_PHY_NONE, SP_INVALID_HANDLE and AUTO_PHY_UPDATE

      • Modify the spConnRec_t structure. We don’t need any more the RSSI related elements (rssiArr, rssiCntr, rssiAvg) and the PHY change related (currPhy, rqPhy, phyCngRq, phyRqFailCnt, isAutoPHYEnable). Remove all the code referring to these elements.

    • In simple_peripheral_menu.c:

    • In the “ConnPhy” menu, remove the MENU_ITEM_ACTION associated with the auto-PHY update.

    • In the corresponding MENU_OBJ, modify the number of available items.

    Here are the diff files (based on SDK 4.10), click the arrow to see the changes:

    • simple_peripheral.c

      index b0af31a..ea9fde6 100644
      @@ -144,17 +144,6 @@
       #define SP_ROW_DEBUG         (TBM_ROW_APP + 8)
       #define SP_ROW_AC            (TBM_ROW_APP + 9)
       
      -// For storing the active connections
      -#define SP_RSSI_TRACK_CHNLS        1            // Max possible channels can be GAP_BONDINGS_MAX
      -#define SP_MAX_RSSI_STORE_DEPTH    5
      -#define SP_INVALID_HANDLE          0xFFFF
      -#define RSSI_2M_THRSHLD           -30           
      -#define RSSI_1M_THRSHLD           -40           
      -#define RSSI_S2_THRSHLD           -50           
      -#define RSSI_S8_THRSHLD           -60           
      -#define SP_PHY_NONE                LL_PHY_NONE  // No PHY set
      -#define AUTO_PHY_UPDATE            0xFF
      -
       // Spin if the expression is not true
       #define SIMPLEPERIPHERAL_ASSERT(expr) if (!(expr)) simple_peripheral_spin();
       
      @@ -231,14 +220,6 @@ typedef struct
         uint16_t         	    connHandle;                        // Connection Handle
         spClockEventData_t*   pParamUpdateEventData;
         Clock_Struct*    	    pUpdateClock;                      // pointer to clock struct
      -  int8_t           	    rssiArr[SP_MAX_RSSI_STORE_DEPTH];
      -  uint8_t          	    rssiCntr;
      -  int8_t           	    rssiAvg;
      -  bool             	    phyCngRq;                          // Set to true if PHY change request is in progress
      -  uint8_t          	    currPhy;
      -  uint8_t          	    rqPhy;
      -  uint8_t          	    phyRqFailCnt;                      // PHY change request count
      -  bool             	    isAutoPHYEnable;                   // Flag to indicate auto phy change
       } spConnRec_t;
       
       /*********************************************************************
      @@ -353,22 +334,16 @@ static void SimplePeripheral_charValueChangeCB(uint8_t paramId);
       static status_t SimplePeripheral_enqueueMsg(uint8_t event, void *pData);
       static void SimplePeripheral_keyChangeHandler(uint8 keys);
       static void SimplePeripheral_handleKeys(uint8_t keys);
      -static void SimplePeripheral_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg);
      -static void SimplePeripheral_initPHYRSSIArray(void);
      -static void SimplePeripheral_updatePHYStat(uint16_t eventCode, uint8_t *pMsg);
       static uint8_t SimplePeripheral_addConn(uint16_t connHandle);
       static uint8_t SimplePeripheral_getConnIndex(uint16_t connHandle);
       static uint8_t SimplePeripheral_removeConn(uint16_t connHandle);
       static void SimplePeripheral_processParamUpdate(uint16_t connHandle);
      -static status_t SimplePeripheral_startAutoPhyChange(uint16_t connHandle);
      -static status_t SimplePeripheral_stopAutoPhyChange(uint16_t connHandle);
       static status_t SimplePeripheral_setPhy(uint16_t connHandle, uint8_t allPhys,
                                               uint8_t txPhy, uint8_t rxPhy,
                                               uint16_t phyOpts);
       static uint8_t SimplePeripheral_clearConnListEntry(uint16_t connHandle);
       static void SimplePeripheral_menuSwitchCb(tbmMenuObj_t* pMenuObjCurr,
                                                 tbmMenuObj_t* pMenuObjNext);
      -static void SimplePeripheral_connEvtCB(Gap_ConnEventRpt_t *pReport);
       static void SimplePeripheral_processConnEvt(Gap_ConnEventRpt_t *pReport);
       #ifdef PTM_MODE
       void simple_peripheral_handleNPIRxInterceptEvent(uint8_t *pMsg);  // Declaration
      @@ -611,9 +586,6 @@ static void SimplePeripheral_init(void)
         //Initialize GAP layer for Peripheral role and register to receive GAP events
         GAP_DeviceInit(GAP_PROFILE_PERIPHERAL, selfEntity, addrMode, &pRandomAddress);
       
      -  // Initialize array to store connection handle and RSSI values
      -  SimplePeripheral_initPHYRSSIArray();
      -
         // The type of display is configured based on the BOARD_DISPLAY_USE...
         // preprocessor definitions
         dispHandle = Display_open(Display_Type_ANY, NULL);
      @@ -745,12 +717,6 @@ static uint8_t SimplePeripheral_processStackMsg(ICall_Hdr *pMsg)
             // Process HCI message
             switch(pMsg->status)
             {
      -        case HCI_COMMAND_COMPLETE_EVENT_CODE:
      -        // Process HCI Command Complete Events here
      -        {
      -          SimplePeripheral_processCmdCompleteEvt((hciEvt_CmdComplete_t *) pMsg);
      -          break;
      -        }
       
               case HCI_BLE_HARDWARE_ERROR_EVENT_CODE:
                 AssertHandler(HAL_ASSERT_CAUSE_HARDWARE_ERROR,0);
      @@ -776,7 +742,6 @@ static uint8_t SimplePeripheral_processStackMsg(ICall_Hdr *pMsg)
                                      pMyMsg->cmdStatus);
                     }
       
      -              SimplePeripheral_updatePHYStat(HCI_LE_SET_PHY, (uint8_t *)pMsg);
                     break;
                   }
       
      @@ -811,7 +776,6 @@ static uint8_t SimplePeripheral_processStackMsg(ICall_Hdr *pMsg)
                                    (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_CODED) ? "CODED" : "Unexpected PHY Value");
                   }
       
      -            SimplePeripheral_updatePHYStat(HCI_BLE_PHY_UPDATE_COMPLETE_EVENT, (uint8_t *)pMsg);
                 }
                 break;
               }
      @@ -1462,7 +1426,6 @@ bool SimplePeripheral_doSetConnPhy(uint8 index)
         static uint8_t phy[] = {
           HCI_PHY_1_MBPS, HCI_PHY_2_MBPS, HCI_PHY_1_MBPS | HCI_PHY_2_MBPS,
           HCI_PHY_CODED, HCI_PHY_1_MBPS | HCI_PHY_2_MBPS | HCI_PHY_CODED,
      -    AUTO_PHY_UPDATE
         };
       
         uint8_t connIndex = SimplePeripheral_getConnIndex(menuConnHandle);
      @@ -1474,27 +1437,14 @@ bool SimplePeripheral_doSetConnPhy(uint8 index)
       
         // Set Phy Preference on the current connection. Apply the same value
         // for RX and TX.
      -  // If auto PHY update is not selected and if auto PHY update is enabled, then
      -  // stop auto PHY update
      -  // Note PHYs are already enabled by default in build_config.opt in stack project.
      -  if(phy[index] != AUTO_PHY_UPDATE)
      -  {
      -    // Cancel RSSI reading  and auto phy changing
      -    SimplePeripheral_stopAutoPhyChange(connList[connIndex].connHandle);
      -
           SimplePeripheral_setPhy(menuConnHandle, 0, phy[index], phy[index], 0);
       
           Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "PHY preference: %s",
                          TBM_GET_ACTION_DESC(&spMenuConnPhy, index));
      -  }
      -  else
      -  {
      -    // Start RSSI read for auto PHY update (if it is disabled)
      -    SimplePeripheral_startAutoPhyChange(menuConnHandle);
      -  }
       
         return status;
       }
      +
       /*********************************************************************
        * @fn      SimplePeripheral_advCallback
        *
      @@ -1712,22 +1662,6 @@ static void SimplePeripheral_processPasscode(spPasscodeData_t *pPasscodeData)
                                B_APP_DEFAULT_PASSCODE);
       }
       
      -/*********************************************************************
      - * @fn      SimplePeripheral_connEvtCB
      - *
      - * @brief   Connection event callback.
      - *
      - * @param pReport pointer to connection event report
      - */
      -static void SimplePeripheral_connEvtCB(Gap_ConnEventRpt_t *pReport)
      -{
      -  // Enqueue the event for processing in the app context.
      -  if(SimplePeripheral_enqueueMsg(SP_CONN_EVT, pReport) != SUCCESS)
      -  {
      -    ICall_free(pReport);
      -  }
      -}
      -
       /*********************************************************************
        * @fn      SimplePeripheral_processConnEvt
        *
      @@ -1745,13 +1679,6 @@ static void SimplePeripheral_processConnEvt(Gap_ConnEventRpt_t *pReport)
           Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Connection handle is not in the connList !!!");
           return;
         }
      -
      -  // If auto phy change is enabled
      -  if (connList[connIndex].isAutoPHYEnable == TRUE)
      -  {
      -    // Read the RSSI
      -    HCI_ReadRssiCmd(pReport->handle);
      -  }
       }
       
       
      @@ -1923,9 +1850,6 @@ static uint8_t SimplePeripheral_addConn(uint16_t connHandle)
               status = bleMemAllocError;
             }
       
      -      // Set default PHY to 1M
      -      connList[i].currPhy = HCI_PHY_1_MBPS;
      -
             break;
           }
         }
      @@ -1986,14 +1910,6 @@ static uint8_t SimplePeripheral_clearConnListEntry(uint16_t connHandle)
           if((connIndex == i) || (connHandle == LINKDB_CONNHANDLE_ALL))
           {
             connList[i].connHandle = LINKDB_CONNHANDLE_INVALID;
      -      connList[i].currPhy = 0;
      -      connList[i].phyCngRq = 0;
      -      connList[i].phyRqFailCnt = 0;
      -      connList[i].rqPhy = 0;
      -      memset(connList[i].rssiArr, 0, SP_MAX_RSSI_STORE_DEPTH);
      -      connList[i].rssiAvg = 0;
      -      connList[i].rssiCntr = 0;
      -      connList[i].isAutoPHYEnable = FALSE;
           }
         }
       
      @@ -2056,8 +1972,6 @@ static uint8_t SimplePeripheral_removeConn(uint16_t connHandle)
           }
           // Clear pending update requests from paramUpdateList
           SimplePeripheral_clearPendingParamUpdate(connHandle);
      -    // Stop Auto PHY Change
      -    SimplePeripheral_stopAutoPhyChange(connHandle);
           // Clear Connection List Entry
           SimplePeripheral_clearConnListEntry(connHandle);
         }
      @@ -2118,226 +2032,6 @@ static void SimplePeripheral_processParamUpdate(uint16_t connHandle)
         }
       }
       
      -/*********************************************************************
      - * @fn      SimpleCentral_processCmdCompleteEvt
      - *
      - * @brief   Process an incoming OSAL HCI Command Complete Event.
      - *
      - * @param   pMsg - message to process
      - *
      - * @return  none
      - */
      -static void SimplePeripheral_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg)
      -{
      -  uint8_t status = pMsg->pReturnParam[0];
      -
      -  //Find which command this command complete is for
      -  switch (pMsg->cmdOpcode)
      -  {
      -    case HCI_READ_RSSI:
      -    {
      -      int8 rssi = (int8)pMsg->pReturnParam[3];  
      -
      -      // Display RSSI value, if RSSI is higher than threshold, change to faster PHY
      -      if (status == SUCCESS)
      -      {
      -        uint16_t handle = BUILD_UINT16(pMsg->pReturnParam[1], pMsg->pReturnParam[2]);
      -
      -        uint8_t index = SimplePeripheral_getConnIndex(handle);
      -        if (index >= MAX_NUM_BLE_CONNS)
      -        {
      -          Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Connection handle is not in the connList !!!");
      -          return;
      -        }
      -
      -        if (rssi != LL_RSSI_NOT_AVAILABLE)
      -        {
      -          connList[index].rssiArr[connList[index].rssiCntr++] = rssi;
      -          connList[index].rssiCntr %= SP_MAX_RSSI_STORE_DEPTH;
      -
      -          int16_t sum_rssi = 0;
      -          for(uint8_t cnt=0; cnt<SP_MAX_RSSI_STORE_DEPTH; cnt++)
      -          {
      -            sum_rssi += connList[index].rssiArr[cnt];
      -          }
      -          connList[index].rssiAvg = (uint32_t)(sum_rssi/SP_MAX_RSSI_STORE_DEPTH);
      -
      -          uint8_t phyRq = SP_PHY_NONE;
      -          uint8_t phyRqS = SP_PHY_NONE;
      -          uint8_t phyOpt = LL_PHY_OPT_NONE;
      -
      -          if(connList[index].phyCngRq == FALSE)
      -          {
      -            if((connList[index].rssiAvg >= RSSI_2M_THRSHLD) &&
      -            (connList[index].currPhy != HCI_PHY_2_MBPS) &&
      -                 (connList[index].currPhy != SP_PHY_NONE))
      -            {
      -              // try to go to higher data rate
      -              phyRqS = phyRq = HCI_PHY_2_MBPS;
      -            }
      -            else if((connList[index].rssiAvg < RSSI_2M_THRSHLD) &&
      -                    (connList[index].rssiAvg >= RSSI_1M_THRSHLD) &&
      -                    (connList[index].currPhy != HCI_PHY_1_MBPS) &&
      -                    (connList[index].currPhy != SP_PHY_NONE))
      -            {
      -              // try to go to legacy regular data rate
      -              phyRqS = phyRq = HCI_PHY_1_MBPS;
      -            }
      -            else if((connList[index].rssiAvg >= RSSI_S2_THRSHLD) &&
      -                    (connList[index].rssiAvg < RSSI_1M_THRSHLD) &&
      -                    (connList[index].currPhy != SP_PHY_NONE))
      -            {
      -              // try to go to lower data rate S=2(500kb/s)
      -              phyRqS = HCI_PHY_CODED;
      -              phyOpt = LL_PHY_OPT_S2;
      -              phyRq = BLE5_CODED_S2_PHY;
      -            }
      -            else if(connList[index].rssiAvg < RSSI_S2_THRSHLD )
      -            {
      -              // try to go to lowest data rate S=8(125kb/s)
      -              phyRqS = HCI_PHY_CODED;
      -              phyOpt = LL_PHY_OPT_S8;
      -              phyRq = BLE5_CODED_S8_PHY;
      -            }
      -            if((phyRq != SP_PHY_NONE) &&
      -               // First check if the request for this phy change is already not honored then don't request for change
      -               (((connList[index].rqPhy == phyRq) &&
      -                 (connList[index].phyRqFailCnt < 2)) ||
      -                 (connList[index].rqPhy != phyRq)))
      -            {
      -              //Initiate PHY change based on RSSI
      -              SimplePeripheral_setPhy(connList[index].connHandle, 0,
      -                                      phyRqS, phyRqS, phyOpt);
      -              connList[index].phyCngRq = TRUE;
      -
      -              // If it a request for different phy than failed request, reset the count
      -              if(connList[index].rqPhy != phyRq)
      -              {
      -                // then reset the request phy counter and requested phy
      -                connList[index].phyRqFailCnt = 0;
      -              }
      -
      -              if(phyOpt == LL_PHY_OPT_NONE)
      -              {
      -                connList[index].rqPhy = phyRq;
      -              }
      -              else if(phyOpt == LL_PHY_OPT_S2)
      -              {
      -                connList[index].rqPhy = BLE5_CODED_S2_PHY;
      -              }
      -              else
      -              {
      -                connList[index].rqPhy = BLE5_CODED_S8_PHY;
      -              }
      -
      -            } // end of if ((phyRq != SP_PHY_NONE) && ...
      -          } // end of if (connList[index].phyCngRq == FALSE)
      -        } // end of if (rssi != LL_RSSI_NOT_AVAILABLE)
      -
      -        Display_printf(dispHandle, SP_ROW_RSSI, 0,
      -                       "RSSI:%d dBm, AVG RSSI:%d dBm",
      -                       (uint32_t)(rssi),
      -                       connList[index].rssiAvg);
      -
      -	  } // end of if (status == SUCCESS)
      -      break;
      -    }
      -
      -    case HCI_LE_READ_PHY:
      -    {
      -      if (status == SUCCESS)
      -      {
      -        Display_printf(dispHandle, SP_ROW_RSSI + 2, 0, "RXPh: %d, TXPh: %d",
      -                       pMsg->pReturnParam[3], pMsg->pReturnParam[4]);
      -      }
      -      break;
      -    }
      -
      -    default:
      -      break;
      -  } // end of switch (pMsg->cmdOpcode)
      -}
      -
      -/*********************************************************************
      -* @fn      SimplePeripheral_initPHYRSSIArray
      -*
      -* @brief   Initializes the array of structure/s to store data related
      -*          RSSI based auto PHy change
      -*
      -* @param   connHandle - the connection handle
      -*
      -* @param   addr - pointer to device address
      -*
      -* @return  index of connection handle
      -*/
      -static void SimplePeripheral_initPHYRSSIArray(void)
      -{
      -  //Initialize array to store connection handle and RSSI values
      -  memset(connList, 0, sizeof(connList));
      -  for (uint8_t index = 0; index < MAX_NUM_BLE_CONNS; index++)
      -  {
      -    connList[index].connHandle = SP_INVALID_HANDLE;
      -  }
      -}
      -/*********************************************************************
      -      // Set default PHY to 1M
      - * @fn      SimplePeripheral_startAutoPhyChange
      - *
      - * @brief   Start periodic RSSI reads on a link.
      - *
      - * @param   connHandle - connection handle of link
      - * @param   devAddr - device address
      - *
      - * @return  SUCCESS: Terminate started
      - *          bleIncorrectMode: No link
      - *          bleNoResources: No resources
      - */
      -static status_t SimplePeripheral_startAutoPhyChange(uint16_t connHandle)
      -{
      -  status_t status = FAILURE;
      -
      -  // Get connection index from handle
      -  uint8_t connIndex = SimplePeripheral_getConnIndex(connHandle);
      -  SIMPLEPERIPHERAL_ASSERT(connIndex < MAX_NUM_BLE_CONNS);
      -
      -  // Start Connection Event notice for RSSI calculation
      -  status = Gap_RegisterConnEventCb(SimplePeripheral_connEvtCB, GAP_CB_REGISTER, connHandle);
      -
      -  // Flag in connection info if successful
      -  if (status == SUCCESS)
      -  {
      -    connList[connIndex].isAutoPHYEnable = TRUE;
      -  }
      -
      -  return status;
      -}
      -
      -/*********************************************************************
      - * @fn      SimplePeripheral_stopAutoPhyChange
      - *
      - * @brief   Cancel periodic RSSI reads on a link.
      - *
      - * @param   connHandle - connection handle of link
      - *
      - * @return  SUCCESS: Operation successful
      - *          bleIncorrectMode: No link
      - */
      -static status_t SimplePeripheral_stopAutoPhyChange(uint16_t connHandle)
      -{
      -  // Get connection index from handle
      -  uint8_t connIndex = SimplePeripheral_getConnIndex(connHandle);
      -  SIMPLEPERIPHERAL_ASSERT(connIndex < MAX_NUM_BLE_CONNS);
      -
      -  // Stop connection event notice
      -  Gap_RegisterConnEventCb(NULL, GAP_CB_UNREGISTER, connHandle);
      -
      -  // Also update the phychange request status for active RSSI tracking connection
      -  connList[connIndex].phyCngRq = FALSE;
      -  connList[connIndex].isAutoPHYEnable = FALSE;
      -
      -  return SUCCESS;
      -}
      -
       /*********************************************************************
        * @fn      SimplePeripheral_setPhy
        *
      @@ -2365,92 +2059,6 @@ static status_t SimplePeripheral_setPhy(uint16_t connHandle, uint8_t allPhys,
         return SUCCESS;
       }
       
      -/*********************************************************************
      -* @fn      SimplePeripheral_updatePHYStat
      -*
      -* @brief   Update the auto phy update state machine
      -*
      -* @param   connHandle - the connection handle
      -*
      -* @return  None
      -*/
      -static void SimplePeripheral_updatePHYStat(uint16_t eventCode, uint8_t *pMsg)
      -{
      -  uint8_t connIndex;
      -
      -  switch (eventCode)
      -  {
      -    case HCI_LE_SET_PHY:
      -    {
      -      // Get connection handle from list
      -      spConnHandleEntry_t *connHandleEntry =
      -                           (spConnHandleEntry_t *)List_get(&setPhyCommStatList);
      -
      -      if (connHandleEntry)
      -      {
      -        // Get index from connection handle
      -        connIndex = SimplePeripheral_getConnIndex(connHandleEntry->connHandle);
      -
      -        ICall_free(connHandleEntry);
      -
      -        // Is this connection still valid?
      -        if (connIndex < MAX_NUM_BLE_CONNS)
      -        {
      -          hciEvt_CommandStatus_t *pMyMsg = (hciEvt_CommandStatus_t *)pMsg;
      -
      -          if (pMyMsg->cmdStatus == HCI_ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE)
      -          {
      -            // Update the phychange request status for active RSSI tracking connection
      -            connList[connIndex].phyCngRq = FALSE;
      -            connList[connIndex].phyRqFailCnt++;
      -          }
      -        }
      -      }
      -      break;
      -    }
      -
      -    // LE Event - a Phy update has completed or failed
      -    case HCI_BLE_PHY_UPDATE_COMPLETE_EVENT:
      -    {
      -      hciEvt_BLEPhyUpdateComplete_t *pPUC =
      -                                     (hciEvt_BLEPhyUpdateComplete_t*) pMsg;
      -
      -      if(pPUC)
      -      {
      -        // Get index from connection handle
      -        connIndex = SimplePeripheral_getConnIndex(pPUC->connHandle);
      -
      -        // Is this connection still valid?
      -        if (connIndex < MAX_NUM_BLE_CONNS)
      -        {
      -          // Update the phychange request status for active RSSI tracking connection
      -          connList[connIndex].phyCngRq = FALSE;
      -
      -          if (pPUC->status == SUCCESS)
      -          {
      -            connList[connIndex].currPhy = pPUC->rxPhy;
      -          }
      -          if(pPUC->rxPhy != connList[connIndex].rqPhy)
      -          {
      -            connList[connIndex].phyRqFailCnt++;
      -          }
      -          else
      -          {
      -            // Reset the request phy counter and requested phy
      -            connList[connIndex].phyRqFailCnt = 0;
      -            connList[connIndex].rqPhy = 0;
      -          }
      -        }
      -      }
      -
      -      break;
      -    }
      -
      -    default:
      -      break;
      -  } // end of switch (eventCode)
      -}
      -
       /*********************************************************************
        * @fn      SimplePeripheral_menuSwitchCb
        *
      
    • simple_peripheral_menu.c

      index b4080aa..0c73cbb 100644
      @@ -50,12 +50,11 @@ void SimplePeripheral_buildMenu(void)
       
       // Menu: ConnPhy
       // upper: Select Device
      -  MENU_OBJ(spMenuConnPhy, "Set Conn PHY Preference", 6, &spMenuPerConn)
      +  MENU_OBJ(spMenuConnPhy, "Set Conn PHY Preference", 5, &spMenuPerConn)
         MENU_ITEM_ACTION(spMenuConnPhy,0,"1 Mbps",              SimplePeripheral_doSetConnPhy)
         MENU_ITEM_ACTION(spMenuConnPhy,1,"2 Mbps",              SimplePeripheral_doSetConnPhy)
         MENU_ITEM_ACTION(spMenuConnPhy,2,"1 & 2 Mbps",          SimplePeripheral_doSetConnPhy)
         MENU_ITEM_ACTION(spMenuConnPhy,3,"Coded",               SimplePeripheral_doSetConnPhy)
         MENU_ITEM_ACTION(spMenuConnPhy,4,"1 & 2 Mbps, & Coded", SimplePeripheral_doSetConnPhy)
      -  MENU_ITEM_ACTION(spMenuConnPhy,5,"Auto PHY change",     SimplePeripheral_doSetConnPhy)
         MENU_OBJ_END
       }
      
  3. Test your code. It should still compile and work smoothly! It means you can still advertise, join a connection, pair with another device, change the Phy, etc…

Remove the connection parameters update

Once a connection has been formed, one of the two devices might want to modify the connection parameters (connection interval, slave latency, connection timeout). This can be done using a connection parameters update request.

By default, some of the examples provided (e.g. simple_peripheral) send a connection parameters update request right after being connected. By default, the examples are also able to accept a connection update. Let’s see how to not send connection update request and to deny the incoming connection updates. Note that you can choose to apply only one of the two modifications or both of them. The goal is to save flash space and CPU time.

  1. Import the simple_peripheral project

  2. Modify the code to deny all the connection parameters update requests

    • Using SysConfig, set “Parameter Updates Request Decision” to “Deny All”. This must be done in BLE > Peripheral Configuration

      ../_images/SysConfig_deny_conn_update.png

      Figure 112. Deny all the connection parameters update requests

      Note: If your project is not using SysConfig, you have to modify the call to GAP_SetParamValue(GAP_PARAM_LINK_UPDATE_DECISION, paramUpdateDecision) to ensure that the second parameter (i.e. paramUpdateDecision) is set to GAP_UPDATE_REQ_DENY_ALL

    • In simple_peripheral.c, remove all the code executed when a GAP_UPDATE_LINK_PARAM_REQ_EVENT is received. A GAP_UPDATE_LINK_PARAM_REQ_EVENT is triggered at the reception of a connection parameters update requests.

      Here is simple_peripheral.c diff file (based on SDK 4.10), click the arrow to see the changes:

      index b0af31a..5b9a694 100644
      @@ -1169,36 +1169,6 @@ static void SimplePeripheral_processGapMessage(gapEventHdr_t *pMsg)
             break;
           }
       
      -    case GAP_UPDATE_LINK_PARAM_REQ_EVENT:
      -    {
      -      gapUpdateLinkParamReqReply_t rsp;
      -
      -      gapUpdateLinkParamReqEvent_t *pReq = (gapUpdateLinkParamReqEvent_t *)pMsg;
      -
      -      rsp.connectionHandle = pReq->req.connectionHandle;
      -      rsp.signalIdentifier = pReq->req.signalIdentifier;
      -
      -      // Only accept connection intervals with slave latency of 0
      -      // This is just an example of how the application can send a response
      -      if(pReq->req.connLatency == 0)
      -      {
      -        rsp.intervalMin = pReq->req.intervalMin;
      -        rsp.intervalMax = pReq->req.intervalMax;
      -        rsp.connLatency = pReq->req.connLatency;
      -        rsp.connTimeout = pReq->req.connTimeout;
      -        rsp.accepted = TRUE;
      -      }
      -      else
      -      {
      -        rsp.accepted = FALSE;
      -      }
      -
      -      // Send Reply
      -      VOID GAP_UpdateLinkParamReqReply(&rsp);
      -
      -      break;
      -    }
      -
           case GAP_LINK_PARAM_UPDATE_EVENT:
           {
             gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsg;
      
  1. Modify simple_peripheral.c in order to remove the code related to connection update:

    • Remove the treatment of the GAP_LINK_PARAM_UPDATE_EVENT (this event is posted when a connection updated has been attempted)

    • Remove the SimplePeripheral_processParamUpdate() function

    • Remove the treatments of SP_SEND_PARAM_UPDATE_EVT

    • In SimplePeripheral_addConn(), remove the code corresponding to connection parameters update.

    • Modify the spConnRec_t structure to remove the elements pParamUpdateEventData and pUpdateClock. Remove the code using those elements too

    • Remove the list paramUpdateList (and the code referring to).

    • Remove the function SimplePeripheral_clearPendingParamUpdate()

      Here is simple_peripheral.c diff file (based on SDK 4.10), click the arrow to see the changes:

      index b0af31a..3d0468b 100644
      @@ -229,8 +229,6 @@ typedef struct
       typedef struct
       {
         uint16_t         	    connHandle;                        // Connection Handle
      -  spClockEventData_t*   pParamUpdateEventData;
      -  Clock_Struct*    	    pUpdateClock;                      // pointer to clock struct
         int8_t           	    rssiArr[SP_MAX_RSSI_STORE_DEPTH];
         uint8_t          	    rssiCntr;
         int8_t           	    rssiAvg;
      @@ -309,9 +307,6 @@ static uint16_t menuConnHandle = LINKDB_CONNHANDLE_INVALID;
       // List to store connection handles for set phy command status's
       static List_List setPhyCommStatList;
       
      -// List to store connection handles for queued param updates
      -static List_List paramUpdateList;
      -
       // Auto connect Disabled/Enabled {0 - Disabled, 1- Group A , 2-Group B, ...}
       uint8_t autoConnect = AUTOCONNECT_DISABLE;
       
      @@ -359,7 +354,6 @@ static void SimplePeripheral_updatePHYStat(uint16_t eventCode, uint8_t *pMsg);
       static uint8_t SimplePeripheral_addConn(uint16_t connHandle);
       static uint8_t SimplePeripheral_getConnIndex(uint16_t connHandle);
       static uint8_t SimplePeripheral_removeConn(uint16_t connHandle);
      -static void SimplePeripheral_processParamUpdate(uint16_t connHandle);
       static status_t SimplePeripheral_startAutoPhyChange(uint16_t connHandle);
       static status_t SimplePeripheral_stopAutoPhyChange(uint16_t connHandle);
       static status_t SimplePeripheral_setPhy(uint16_t connHandle, uint8_t allPhys,
      @@ -953,18 +947,6 @@ static void SimplePeripheral_processAppMsg(spEvt_t *pMsg)
             SimplePeripheral_updateRPA();
             break;
       
      -    case SP_SEND_PARAM_UPDATE_EVT:
      -    {
      -      // Extract connection handle from data
      -      uint16_t connHandle = *(uint16_t *)(((spClockEventData_t *)pMsg->pData)->data);
      -
      -      SimplePeripheral_processParamUpdate(connHandle);
      -
      -      // This data is not dynamically allocated
      -      dealloc = FALSE;
      -      break;
      -    }
      -
           case SP_CONN_EVT:
             SimplePeripheral_processConnEvt((Gap_ConnEventRpt_t *)(pMsg->pData));
             break;
      @@ -1199,42 +1181,6 @@ static void SimplePeripheral_processGapMessage(gapEventHdr_t *pMsg)
             break;
           }
       
      -    case GAP_LINK_PARAM_UPDATE_EVENT:
      -    {
      -      gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsg;
      -
      -      // Get the address from the connection handle
      -      linkDBInfo_t linkInfo;
      -      linkDB_GetInfo(pPkt->connectionHandle, &linkInfo);
      -
      -      if(pPkt->status == SUCCESS)
      -      {
      -        // Display the address of the connection update
      -        Display_printf(dispHandle, SP_ROW_STATUS_2, 0, "Link Param Updated: %s",
      -                       Util_convertBdAddr2Str(linkInfo.addr));
      -      }
      -      else
      -      {
      -        // Display the address of the connection update failure
      -        Display_printf(dispHandle, SP_ROW_STATUS_2, 0,
      -                       "Link Param Update Failed 0x%x: %s", pPkt->opcode,
      -                       Util_convertBdAddr2Str(linkInfo.addr));
      -      }
      -
      -      // Check if there are any queued parameter updates
      -      spConnHandleEntry_t *connHandleEntry = (spConnHandleEntry_t *)List_get(&paramUpdateList);
      -      if (connHandleEntry != NULL)
      -      {
      -        // Attempt to send queued update now
      -        SimplePeripheral_processParamUpdate(connHandleEntry->connHandle);
      -
      -        // Free list element
      -        ICall_free(connHandleEntry);
      -      }
      -
      -      break;
      -    }
      -
           default:
             Display_clearLines(dispHandle, SP_ROW_STATUS_1, SP_ROW_STATUS_2);
             break;
      @@ -1382,11 +1328,6 @@ static void SimplePeripheral_clockHandler(UArg arg)
          // Post event to read the current RPA
          SimplePeripheral_enqueueMsg(SP_READ_RPA_EVT, NULL);
        }
      - else if (pData->event == SP_SEND_PARAM_UPDATE_EVT)
      - {
      -    // Send message to app
      -    SimplePeripheral_enqueueMsg(SP_SEND_PARAM_UPDATE_EVT, pData);
      - }
       }
       
       /*********************************************************************
      @@ -1894,35 +1835,6 @@ static uint8_t SimplePeripheral_addConn(uint16_t connHandle)
             // Found available entry to put a new connection info in
             connList[i].connHandle = connHandle;
       
      -      // Allocate data to send through clock handler
      -      connList[i].pParamUpdateEventData = ICall_malloc(sizeof(spClockEventData_t) +
      -                                                       sizeof (uint16_t));
      -      if(connList[i].pParamUpdateEventData)
      -      {
      -        connList[i].pParamUpdateEventData->event = SP_SEND_PARAM_UPDATE_EVT;
      -        *((uint16_t *)connList[i].pParamUpdateEventData->data) = connHandle;
      -
      -        // Create a clock object and start
      -        connList[i].pUpdateClock
      -          = (Clock_Struct*) ICall_malloc(sizeof(Clock_Struct));
      -
      -        if (connList[i].pUpdateClock)
      -        {
      -          Util_constructClock(connList[i].pUpdateClock,
      -                              SimplePeripheral_clockHandler,
      -                              SEND_PARAM_UPDATE_DELAY, 0, true,
      -                              (UArg) (connList[i].pParamUpdateEventData));
      -        }
      -        else
      -        {
      -            ICall_free(connList[i].pParamUpdateEventData);
      -        }
      -      }
      -      else
      -      {
      -        status = bleMemAllocError;
      -      }
      -
             // Set default PHY to 1M
             connList[i].currPhy = HCI_PHY_1_MBPS;
       
      @@ -2000,28 +1912,6 @@ static uint8_t SimplePeripheral_clearConnListEntry(uint16_t connHandle)
         return(SUCCESS);
       }
       
      -/*********************************************************************
      - * @fn      SimplePeripheral_clearPendingParamUpdate
      - *
      - * @brief   clean pending param update request in the paramUpdateList list
      - *
      - * @param   connHandle - connection handle to clean
      - *
      - * @return  none
      - */
      -void SimplePeripheral_clearPendingParamUpdate(uint16_t connHandle)
      -{
      -  List_Elem *curr;
      -
      -  for (curr = List_head(&paramUpdateList); curr != NULL; curr = List_next(curr)) 
      -  {
      -    if (((spConnHandleEntry_t *)curr)->connHandle == connHandle)
      -    {
      -      List_remove(&paramUpdateList, curr);
      -    }
      -  }
      -}
      -
       /*********************************************************************
        * @fn      SimplePeripheral_removeConn
        *
      @@ -2037,25 +1927,6 @@ static uint8_t SimplePeripheral_removeConn(uint16_t connHandle)
       
         if(connIndex != MAX_NUM_BLE_CONNS)
         {
      -    Clock_Struct* pUpdateClock = connList[connIndex].pUpdateClock;
      -
      -    if (pUpdateClock != NULL)
      -    {
      -      // Stop and destruct the RTOS clock if it's still alive
      -      if (Util_isActive(pUpdateClock))
      -      {
      -        Util_stopClock(pUpdateClock);
      -      }
      -
      -      // Destruct the clock object
      -      Clock_destruct(pUpdateClock);
      -      // Free clock struct
      -      ICall_free(pUpdateClock);
      -      // Free ParamUpdateEventData
      -      ICall_free(connList[connIndex].pParamUpdateEventData);
      -    }
      -    // Clear pending update requests from paramUpdateList
      -    SimplePeripheral_clearPendingParamUpdate(connHandle);
           // Stop Auto PHY Change
           SimplePeripheral_stopAutoPhyChange(connHandle);
           // Clear Connection List Entry
      @@ -2065,59 +1936,6 @@ static uint8_t SimplePeripheral_removeConn(uint16_t connHandle)
         return connIndex;
       }
       
      -/*********************************************************************
      - * @fn      SimplePeripheral_processParamUpdate
      - *
      - * @brief   Process a parameters update request
      - *
      - * @return  None
      - */
      -static void SimplePeripheral_processParamUpdate(uint16_t connHandle)
      -{
      -  gapUpdateLinkParamReq_t req;
      -  uint8_t connIndex;
      -
      -  req.connectionHandle = connHandle;
      -  req.connLatency = DEFAULT_DESIRED_SLAVE_LATENCY;
      -  req.connTimeout = DEFAULT_DESIRED_CONN_TIMEOUT;
      -  req.intervalMin = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
      -  req.intervalMax = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
      -
      -  connIndex = SimplePeripheral_getConnIndex(connHandle);
      -  if (connIndex >= MAX_NUM_BLE_CONNS)
      -  {
      -    Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Connection handle is not in the connList !!!");
      -    return;
      -  }
      -
      -  // Deconstruct the clock object
      -  Clock_destruct(connList[connIndex].pUpdateClock);
      -  // Free clock struct, only in case it is not NULL
      -  if (connList[connIndex].pUpdateClock != NULL)
      -  {
      -      ICall_free(connList[connIndex].pUpdateClock);
      -      connList[connIndex].pUpdateClock = NULL;
      -  }
      -  // Free ParamUpdateEventData, only in case it is not NULL
      -  if (connList[connIndex].pParamUpdateEventData != NULL)
      -      ICall_free(connList[connIndex].pParamUpdateEventData);
      -
      -  // Send parameter update
      -  bStatus_t status = GAP_UpdateLinkParamReq(&req);
      -
      -  // If there is an ongoing update, queue this for when the udpate completes
      -  if (status == bleAlreadyInRequestedMode)
      -  {
      -    spConnHandleEntry_t *connHandleEntry = ICall_malloc(sizeof(spConnHandleEntry_t));
      -    if (connHandleEntry)
      -    {
      -      connHandleEntry->connHandle = connHandle;
      -
      -      List_put(&paramUpdateList, (List_Elem *)connHandleEntry);
      -    }
      -  }
      -}
      -
       /*********************************************************************
        * @fn      SimpleCentral_processCmdCompleteEvt
        *
      
  2. Test your code. It should still compile and work smoothly! It means you can still advertise, join a connection, pair with another device, change the Phy, etc…

Remove the pairing capabilities

Pairing is the process of generating and exchanging keys (not to be confused with forming or establishing a BLE connection between two devices). The pairing capability is included in many examples provided in your SDK.

As bonding consists in storing the keys generated during the pairing process in nonvolatile memory to use for the next encryption sequence, this functionality will be removed too.

This modification should free up some FLASH and some CPU time.

  1. Import the simple_peripheral project

  2. Using SysConfig, disable pairing and bonding capabilities. This must be done in BLE > Bond Manager

    ../_images/SysConfig_disable_pairing_bonding.png

    Figure 113. Disable pairing and bonding capabilities

  3. In simple_peripheral.c, remove the code related to pairing and bonding.

    • Remove the callback-functions SimplePeripheral_passcodeCb() and SimplePeripheral_pairStateCb()

    • Remove the structure SimplePeripheral_BondMgrCBs.

    • Remove the call to the function GAPBondMgr_Register()

    • Remove the function SimplePeripheral_processPairState() and its calls.

    • Remove the function SimplePeripheral_processPasscode() and its calls.

      Here is simple_peripheral.c diff file (based on SDK 4.10), click the arrow to see the changes:

      index b0af31a..d8244a6 100644
      @@ -179,28 +179,6 @@ typedef struct
         void    *pData;               // pointer to message
       } spEvt_t;
       
      -// Container to store passcode data when passing from gapbondmgr callback
      -// to app event. See the pfnPairStateCB_t documentation from the gapbondmgr.h
      -// header file for more information on each parameter.
      -typedef struct
      -{
      -  uint8_t state;
      -  uint16_t connHandle;
      -  uint8_t status;
      -} spPairStateData_t;
      -
      -// Container to store passcode data when passing from gapbondmgr callback
      -// to app event. See the pfnPasscodeCB_t documentation from the gapbondmgr.h
      -// header file for more information on each parameter.
      -typedef struct
      -{
      -  uint8_t deviceAddr[B_ADDR_LEN];
      -  uint16_t connHandle;
      -  uint8_t uiInputs;
      -  uint8_t uiOutputs;
      -  uint32_t numComparison;
      -} spPasscodeData_t;
      -
       // Container to store advertising event data when passing from advertising
       // callback to app event. See the respective event in GapAdvScan_Event_IDs
       // in gap_advertiser.h for the type that pBuf should be cast to.
      @@ -342,13 +320,6 @@ static void SimplePeripheral_processCharValueChangeEvt(uint8_t paramId);
       static void SimplePeripheral_performPeriodicTask(void);
       static void SimplePeripheral_updateRPA(void);
       static void SimplePeripheral_clockHandler(UArg arg);
      -static void SimplePeripheral_passcodeCb(uint8_t *pDeviceAddr, uint16_t connHandle,
      -                                        uint8_t uiInputs, uint8_t uiOutputs,
      -                                        uint32_t numComparison);
      -static void SimplePeripheral_pairStateCb(uint16_t connHandle, uint8_t state,
      -                                         uint8_t status);
      -static void SimplePeripheral_processPairState(spPairStateData_t *pPairState);
      -static void SimplePeripheral_processPasscode(spPasscodeData_t *pPasscodeData);
       static void SimplePeripheral_charValueChangeCB(uint8_t paramId);
       static status_t SimplePeripheral_enqueueMsg(uint8_t event, void *pData);
       static void SimplePeripheral_keyChangeHandler(uint8 keys);
      @@ -384,13 +355,6 @@ extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);
        * PROFILE CALLBACKS
        */
       
      -// GAP Bond Manager Callbacks
      -static gapBondCBs_t SimplePeripheral_BondMgrCBs =
      -{
      -  SimplePeripheral_passcodeCb,       // Passcode callback
      -  SimplePeripheral_pairStateCb       // Pairing/Bonding state Callback
      -};
      -
       // Simple GATT Profile Callbacks
       static simpleProfileCBs_t SimplePeripheral_simpleProfileCBs =
       {
      @@ -573,9 +537,6 @@ static void SimplePeripheral_init(void)
         // Register callback with SimpleGATTprofile
         SimpleProfile_RegisterAppCBs(&SimplePeripheral_simpleProfileCBs);
       
      -  // Start Bond Manager and register callback
      -  VOID GAPBondMgr_Register(&SimplePeripheral_BondMgrCBs);
      -
         // Register with GAP for HCI/Host messages. This is needed to receive HCI
         // events. For more information, see the HCI section in the User's Guide:
         // http://software-dl.ti.com/lprf/ble5stack-latest/
      @@ -937,14 +898,6 @@ static void SimplePeripheral_processAppMsg(spEvt_t *pMsg)
             SimplePeripheral_processAdvEvent((spGapAdvEventData_t*)(pMsg->pData));
             break;
       
      -    case SP_PAIR_STATE_EVT:
      -      SimplePeripheral_processPairState((spPairStateData_t*)(pMsg->pData));
      -      break;
      -
      -    case SP_PASSCODE_EVT:
      -      SimplePeripheral_processPasscode((spPasscodeData_t*)(pMsg->pData));
      -      break;
      -
           case SP_PERIODIC_EVT:
             SimplePeripheral_performPeriodicTask();
             break;
      @@ -1575,143 +1528,6 @@ static void SimplePeripheral_processAdvEvent(spGapAdvEventData_t *pEventData)
         }
       }
       
      -
      -/*********************************************************************
      - * @fn      SimplePeripheral_pairStateCb
      - *
      - * @brief   Pairing state callback.
      - *
      - * @return  none
      - */
      -static void SimplePeripheral_pairStateCb(uint16_t connHandle, uint8_t state,
      -                                         uint8_t status)
      -{
      -  spPairStateData_t *pData = ICall_malloc(sizeof(spPairStateData_t));
      -
      -  // Allocate space for the event data.
      -  if (pData)
      -  {
      -    pData->state = state;
      -    pData->connHandle = connHandle;
      -    pData->status = status;
      -
      -    // Queue the event.
      -    if(SimplePeripheral_enqueueMsg(SP_PAIR_STATE_EVT, pData) != SUCCESS)
      -    {
      -      ICall_free(pData);
      -    }
      -  }
      -}
      -
      -/*********************************************************************
      - * @fn      SimplePeripheral_passcodeCb
      - *
      - * @brief   Passcode callback.
      - *
      - * @return  none
      - */
      -static void SimplePeripheral_passcodeCb(uint8_t *pDeviceAddr,
      -                                        uint16_t connHandle,
      -                                        uint8_t uiInputs,
      -                                        uint8_t uiOutputs,
      -                                        uint32_t numComparison)
      -{
      -  spPasscodeData_t *pData = ICall_malloc(sizeof(spPasscodeData_t));
      -
      -  // Allocate space for the passcode event.
      -  if (pData )
      -  {
      -    pData->connHandle = connHandle;
      -    memcpy(pData->deviceAddr, pDeviceAddr, B_ADDR_LEN);
      -    pData->uiInputs = uiInputs;
      -    pData->uiOutputs = uiOutputs;
      -    pData->numComparison = numComparison;
      -
      -    // Enqueue the event.
      -    if(SimplePeripheral_enqueueMsg(SP_PASSCODE_EVT, pData) != SUCCESS)
      -    {
      -      ICall_free(pData);
      -    }
      -  }
      -}
      -
      -/*********************************************************************
      - * @fn      SimplePeripheral_processPairState
      - *
      - * @brief   Process the new paring state.
      - *
      - * @return  none
      - */
      -static void SimplePeripheral_processPairState(spPairStateData_t *pPairData)
      -{
      -  uint8_t state = pPairData->state;
      -  uint8_t status = pPairData->status;
      -
      -  switch (state)
      -  {
      -    case GAPBOND_PAIRING_STATE_STARTED:
      -      Display_printf(dispHandle, SP_ROW_CONNECTION, 0, "Pairing started");
      -      break;
      -
      -    case GAPBOND_PAIRING_STATE_COMPLETE:
      -      if (status == SUCCESS)
      -      {
      -        Display_printf(dispHandle, SP_ROW_CONNECTION, 0, "Pairing success");
      -      }
      -      else
      -      {
      -        Display_printf(dispHandle, SP_ROW_CONNECTION, 0, "Pairing fail: %d", status);
      -      }
      -      break;
      -
      -    case GAPBOND_PAIRING_STATE_ENCRYPTED:
      -      if (status == SUCCESS)
      -      {
      -        Display_printf(dispHandle, SP_ROW_CONNECTION, 0, "Encryption success");
      -      }
      -      else
      -      {
      -        Display_printf(dispHandle, SP_ROW_CONNECTION, 0, "Encryption failed: %d", status);
      -      }
      -      break;
      -
      -    case GAPBOND_PAIRING_STATE_BOND_SAVED:
      -      if (status == SUCCESS)
      -      {
      -        Display_printf(dispHandle, SP_ROW_CONNECTION, 0, "Bond save success");
      -      }
      -      else
      -      {
      -        Display_printf(dispHandle, SP_ROW_CONNECTION, 0, "Bond save failed: %d", status);
      -      }
      -      break;
      -
      -    default:
      -      break;
      -  }
      -}
      -
      -/*********************************************************************
      - * @fn      SimplePeripheral_processPasscode
      - *
      - * @brief   Process the Passcode request.
      - *
      - * @return  none
      - */
      -static void SimplePeripheral_processPasscode(spPasscodeData_t *pPasscodeData)
      -{
      -  // Display passcode to user
      -  if (pPasscodeData->uiOutputs != 0)
      -  {
      -    Display_printf(dispHandle, SP_ROW_CONNECTION, 0, "Passcode: %d",
      -                   B_APP_DEFAULT_PASSCODE);
      -  }
      -
      -  // Send passcode response
      -  GAPBondMgr_PasscodeRsp(pPasscodeData->connHandle , SUCCESS,
      -                         B_APP_DEFAULT_PASSCODE);
      -}
      -
       /*********************************************************************
        * @fn      SimplePeripheral_connEvtCB
        *
      
  4. Rebuild your project.

  5. The Flash consumption can be even more decreased by not linking and/or compiling any of the code related to pairing and/or pairing. To do so, the pre-defined symbol GAP_BOND_MGR must not be declared.

    If your project is using SysConfig: By default GAP_BOND_MGR is declared in the file ti_build_config.opt (in the folder Debug/syscfg of your project). The file ti_build_config.opt cannot be directly altered as it is generated by SysConfig.

    • Disable SysConfig and remove the declaration of the symbol GAP_BOND_MGR in the file ti_build_config.opt.

    OR

    • Change the way SysConfig is generating the ti_build_config.opt file. SysConfig is using a template that can be modified. The template to be considered is in the SDK in source\ti\ble5stack\.meta\templates\build_config.opt.xdt. Remove the declaration of the symbol GAP_BOND_MGR in the file build_config.opt.xdt.

    If your project is not using SysConfig: In general GAP_BOND_MGR is declared in the file build_config.opt. Remove the declaration of the symbol in the appropriate file.

  6. Rebuild and test your code. It should still build and work smoothly! It means you can still advertise, join a connection, change the Phy, etc…

Remove the Resolvable Private Address (RPA) functionality

(Random) Resolvable Private Address or RPA is a functionality helping to preserve privacy. It consists in changing the device address over time. The address can be matched, or resolved, to an Identity Address for tracking by trusted peers.

This functionality is provided in several examples and can be removed in order to save memory and CPU time.

  1. Import the simple_peripheral project

  2. Using SysConfig, go to BLE > General Configuration > Address Mode and verify you are not using an RPA. Chose, for example “Random Static Address”. Specify the random static address you want.

    ../_images/SysConfig_disable_RPA.png

    Figure 114. Select a non-RPA address mode

  3. In simple_peripheral.c, remove the code related to RPA.

    • Remove the function SimplePeripheral_updateRPA() and all its calls

    • Remove the global variable argRpaRead and all the code using it

    • Remove the clock structure clkRpaRead and all the code using it

    • Remove the code handling the SP_READ_RPA_EVT events

    • Remove the global variable rpa[] (and all the code using it if some is remaining)

      Here is simple_peripheral.c diff file (based on SDK 4.10), click the arrow to see the changes:

      index b0af31a..c261222 100644
      @@ -289,17 +289,11 @@ static Queue_Handle appMsgQueueHandle;
       // Clock instance for internal periodic events. Only one is needed since
       // GattServApp will handle notifying all connected GATT clients
       static Clock_Struct clkPeriodic;
      -// Clock instance for RPA read events.
      -static Clock_Struct clkRpaRead;
       
       // Memory to pass periodic event ID to clock handler
       spClockEventData_t argPeriodic =
       { .event = SP_PERIODIC_EVT };
       
      -// Memory to pass RPA read event ID to clock handler
      -spClockEventData_t argRpaRead =
      -{ .event = SP_READ_RPA_EVT };
      -
       // Per-handle connection info
       static spConnRec_t connList[MAX_NUM_BLE_CONNS];
       
      @@ -322,9 +316,6 @@ static uint8 advHandleLongRange;
       // Address mode
       static GAP_Addr_Modes_t addrMode = DEFAULT_ADDRESS_MODE;
       
      -// Current Random Private Address
      -static uint8 rpa[B_ADDR_LEN] = {0};
      -
       /*********************************************************************
        * LOCAL FUNCTIONS
        */
      @@ -340,7 +331,6 @@ static void SimplePeripheral_processAdvEvent(spGapAdvEventData_t *pEventData);
       static void SimplePeripheral_processAppMsg(spEvt_t *pMsg);
       static void SimplePeripheral_processCharValueChangeEvt(uint8_t paramId);
       static void SimplePeripheral_performPeriodicTask(void);
      -static void SimplePeripheral_updateRPA(void);
       static void SimplePeripheral_clockHandler(UArg arg);
       static void SimplePeripheral_passcodeCb(uint8_t *pDeviceAddr, uint16_t connHandle,
                                               uint8_t uiInputs, uint8_t uiOutputs,
      @@ -949,10 +939,6 @@ static void SimplePeripheral_processAppMsg(spEvt_t *pMsg)
             SimplePeripheral_performPeriodicTask();
             break;
       
      -    case SP_READ_RPA_EVT:
      -      SimplePeripheral_updateRPA();
      -      break;
      -
           case SP_SEND_PARAM_UPDATE_EVT:
           {
             // Extract connection handle from data
      @@ -1080,15 +1066,6 @@ static void SimplePeripheral_processGapMessage(gapEventHdr_t *pMsg)
                              (addrMode <= ADDRMODE_RANDOM) ? "Dev" : "ID",
                              Util_convertBdAddr2Str(pPkt->devAddr));
       
      -        if (addrMode > ADDRMODE_RANDOM)
      -        {
      -          SimplePeripheral_updateRPA();
      -
      -          // Create one-shot clock for RPA check event.
      -          Util_constructClock(&clkRpaRead, SimplePeripheral_clockHandler,
      -                              READ_RPA_PERIOD, 0, true,
      -                              (UArg) &argRpaRead);
      -        }
               tbm_setItemStatus(&spMenuMain, SP_ITEM_AUTOCONNECT, TBM_ITEM_NONE);
             }
       
      @@ -1327,32 +1304,6 @@ static void SimplePeripheral_performPeriodicTask(void)
         }
       }
       
      -/*********************************************************************
      - * @fn      SimplePeripheral_updateRPA
      - *
      - * @brief   Read the current RPA from the stack and update display
      - *          if the RPA has changed.
      - *
      - * @param   None.
      - *
      - * @return  None.
      - */
      -static void SimplePeripheral_updateRPA(void)
      -{
      -  uint8_t* pRpaNew;
      -
      -  // Read the current RPA.
      -  pRpaNew = GAP_GetDevAddress(FALSE);
      -
      -  if (memcmp(pRpaNew, rpa, B_ADDR_LEN))
      -  {
      -    // If the RPA has changed, update the display
      -    Display_printf(dispHandle, SP_ROW_RPA, 0, "RP Addr: %s",
      -                   Util_convertBdAddr2Str(pRpaNew));
      -    memcpy(rpa, pRpaNew, B_ADDR_LEN);
      -  }
      -}
      -
       /*********************************************************************
        * @fn      SimplePeripheral_clockHandler
        *
      @@ -1374,14 +1325,6 @@ static void SimplePeripheral_clockHandler(UArg arg)
          // Post event to wake up the application
          SimplePeripheral_enqueueMsg(SP_PERIODIC_EVT, NULL);
        }
      - else if (pData->event == SP_READ_RPA_EVT)
      - {
      -   // Start the next period
      -   Util_startClock(&clkRpaRead);
      -
      -   // Post event to read the current RPA
      -   SimplePeripheral_enqueueMsg(SP_READ_RPA_EVT, NULL);
      - }
        else if (pData->event == SP_SEND_PARAM_UPDATE_EVT)
        {
           // Send message to app
      
  4. Test your code. It should still compile and work smoothly! It means you can still advertise, join a connection, pair with another device, change the Phy, etc…

Optimize TI drivers for your project

In order to have easy-to-use and portable code, the TI drivers handle a lot of different configurations. Most of the time, a specific application does not require all those configurations. By optimizing the TI drivers for your own application you can save RAM, FLASH and processor time.

A good example of this is the Power driver (but you can analyze any TI driver in order to optimize it using a similar process). The Power driver is a pretty complex driver. A lot of different combinations of crystals can be used and it handles all of them.

Let’s see how to optimize the Power driver:

  1. Force CCS or IAR to not use the compiled sources for the Power driver.

    • [CCS] Right click on your project and click “Add Files…” Add the files PowerCC26X2.c and PowerCC26X2.h to your project. (The TI drivers files are stored in <Your SDK>/source/ti/drivers)

      It is recommended to select Copy Files and not Link to files.

      Verify if the linker is considering the files you added by checking the “MODULE SUMMARY” section of the .map file. You should find a line presenting the memory consumed by PowerCC26X2.obj.


    • [IAR] Right click on your project, then chose “Add” and “Add Files…”. Add the files PowerCC26X2.c and PowerCC26X2.h to your project. (The TI drivers files are stored in <Your SDK>/source/ti/drivers)


  1. Review the configuration of your project (for the Power driver, the crystal configuration is the most important). To do so, use SysConfig and/or consult the file ti_devices_config.c. If SysConfig is not used, consult the file ccfg.c.


  1. Optimize the code! The goal here is to find the variables that are not seen as constant by the code optimizer but that are constant in practice.

    a- Expressions returning always the same value for a given configuration:

    • CCFGRead_DIS_GPRAM()

    • CCFGRead_SCLK_LF_OPTION()

    • CCFGRead_XOSC_FREQ()

    • OSCClockSourceGet(OSC_SRC_CLK_LF)

    • OSCClockSourceGet(OSC_SRC_CLK_HF)

    Those expressions can be replaced by their constant value. This will allow the code optimizer to generate a simpler code.

    b- Variable that won’t be used (or that will always the same value).

    • Function pointer never set (i.e. always pointing on NULL). In this case no need to test if the function is not NULL, just remove the corresponding code. A good example of this case in the Power driver is PowerCC26X2_config.enableTCXOFxn. By it points on NULL and it is wasting time and FLASH to test this at each execution.

    • Variable with a constant value set only once at driver opening. (The Power driver does not contain any example of this case.)

  2. That’s it! Once again, these guidelines can be adapted to all the drivers used. It is important to test properly your code once optimized to be sure that no unexpected behavior occurs.

Defining Bluetooth Low Energy Behavior

This step involves using Bluetooth Low Energy protocol stack APIs to define the system behavior and adding profiles, defining the GATT database, configuring the security model, and so forth. Use the concepts explained in BLE5-Stack as well as the Bluetooth Low Energy API reference in BLE Stack API Reference.