LE Peripheral Extended ADV

The LE peripheral extended ADV sample demonstrates how to develop different Peripheral Role based applications.

Supported features:

  • Send advertising events with LE Advertising Extensions.

  • Enable one or more advertising sets at the same time.

  • Enable an advertising set for a duration or the maximum number of extended advertising events.

  • Hold more data with extended advertising PDU s.

  • Can accept the establishment of an LE link and become a peripheral role in the link on LE 1M PHY, LE 2M PHY or LE Coded PHY.

../../../_images/bt5_peripheral_architecture.png

The sample uses LE host and LE manager module. The above figure shows the relationships between several modules in the sample.

More information about these modules can be found in the LE Host and LE Manager documentation.

Overview

  • Peripheral devices with LE Advertising Extensions can set the duration of the advertising or the maximum number of extended advertising events, and enable or disable one or more advertising sets at a time.

  • If extended advertising PDUs are used, the length of the adv data or scan response data could be increased, and the distance at which a connection can be established could be increased with the LE Coded PHY.

  • If the peripheral device uses LE Advertising Extensions, the developer shall take compatibility with peer devices of different Bluetooth versions into account. Compatibility with peer devices of different Bluetooth versions is shown below:

Compatibility of Peripheral Device with LE Advertising Extensions

Bluetooth 5 Feature

Advertising PDUs

Bluetooth 4.0

Bluetooth 4.1

Bluetooth 4.2

Bluetooth 5.0 (Not Using LE Advertising Extensions)

Bluetooth 5.0 (Using LE Advertising Extensions)

LE Advertising Extensions

Extended advertising PDUs

N

N

N

N

Y

LE Advertising Extensions

Legacy advertising PDUs

Y

Y

Y

Y

Y

Requirements

The sample supports the following development kits:

Hardware Platforms

Board Name

Build Target

RTL87x3E HDK

RTL87x3E EVB

ble_bt5_peripheral_4M_bank0

ble_bt5_peripheral_16M_bank0

RTL87x3D HDK

RTL87x3D EVB

ble_bt5_peripheral_8M_bank0

ble_bt5_peripheral_16M_bank0

ble_bt5_peripheral_cs_16M_bank0

This sample project can be found under board\evb\ble_bt5_peripheral in the SDK folder structure. Developers can choose the project according to the Board Name and choose the Build Target according to the flash map.

When built for an xxx_4M_xxx build target, the sample is configured to compile and run with a 4M flash map.

When built for an xxx_8M_xxx build target, the sample is configured to compile and run with an 8M flash map.

When built for an xxx_16M_xxx build target, the sample is configured to compile and run with a 16M flash map.

To quickly set up the development environment, please refer to the detailed instructions provided in Quick Start.

Wiring

Please refer to EVB Interfaces and Modules in Quick Start.

Configurations

Configurable Items

All contents that can be configured for the sample are in src\sample\ble_bt5_peripheral\app_bt5_peripheral_flags.h, developers can configure according to actual needs.

/** @brief Configure Advertising PHY */
#define ADVERTISING_PHY            APP_PRIMARY_CODED_SECONDARY_CODED
/** @brief Configure coding scheme of LE Coded PHY: 0 - S = 2, 1 - S = 8 */
#define F_BT_LE_CODED_PHY_SUPPORT 0
#define LE_CODED_PHY_S8 (F_BT_LE_CODED_PHY_SUPPORT && 0)
/** @brief Configure APP LE link number */
#define APP_MAX_LINKS              1
/** @brief Configure DLPS: 0 - Disable DLPS, 1 - Enable DLPS */
#define F_BT_DLPS_EN               1

Generating System Config File

Developers shall configure the following items through MCUConfig Tool:

MCUConfig Tool Configuration

Configurable Item

Value

LE link number

APP_MAX_LINKS

LE slave link number

APP_MAX_LINKS

For more information about MCUConfig Tool Configuration, please refer to MCUConfig Tool.

Building and Downloading

Take the project rtl87x3e_ble_bt5_peripheral.uvprojx and target ble_bt5_peripheral_4M_bank0 as an example, to build and run the sample with Keil development environment, follow the steps listed below:

  1. Open rtl87x3e_ble_bt5_peripheral.uvprojx.

  2. Choose the build target ble_bt5_peripheral_4M_bank0.

    ../../../_images/chose_build_target12.png
  3. Build the target.

    ../../../_images/building12.png

    After a successful build, the APP bin file ble_bt5_peripheral_bank0_MP-v0.0.0.0-xxx.bin will be generated in the directory bin\rtl87x3e\flash_4M_dualbank\bank0.

  4. Download APP bin into the EVB.

  5. Press the reset button on the EVB and it will start LE advertising.

Experimental Verification

After downloading the sample bin to the EVB, developers can test it by using another kit that is running the LE Central Extended Scan sample.

Testing with Another Kit

For the test procedure, please refer to Testing with Another Kit in LE Central Extended Scan.

Code Overview

This chapter will be introduced according to the following several parts:

Source Code Directory

  • Project directory: board\evb\ble_bt5_peripheral.

  • Source code directory: src\sample\ble_bt5_peripheral.

Source files in the sample project are currently categorized into several groups as below:

└── ble_bt5_peripheral_4M_bank0
    ├── include                  ROM UUID header files. Developers do not need to modify them.
    ├── lib                      Includes all binary symbol files that the user application is built on.
        ├── gap_utils.lib
        ├── ROM.lib
        ├── upperstack_4M.lib
        ├── hal_utils.lib
        ├── ble_mgr.lib
        └── sysm.lib
    ├── cmsis                    The CMSIS source code. Developers do not need to modify it.
    ├── app                      The application source code.
        ├── app_bt5_peripheral_main.c        Main entry
        ├── app_bt5_peripheral_gap.c         LE GAP initialize and message handler
        ├── app_bt5_peripheral_adv.c         Advertising manager
        └── app_bt5_peripheral_task.c        APP task
    └── io_hal

Initialization

main() function is invoked when the EVB is powered on, and the chip boots up, and it performs the following initialization functions:

int main(void)
{
   board_init();
   le_gap_init(APP_MAX_LINKS);
   gap_lib_init();
   app_peripheral_gap_init();
   pwr_mgr_init();
   task_init();
   os_sched_start();

   return 0;
 }
  • le_gap_init() function is used to initialize GAP and configure the link number.

  • app_peripheral_gap_init() function is used to initialize the GAP parameters.

GAP Parameter Initialization

The app_peripheral_gap_init() function is used to initialize the GAP parameters. Developers can easily customize the sample by modifying the following parameter values.

void app_peripheral_gap_init(void)
{
   /* Device name and device appearance */
   uint8_t  device_name[GAP_DEVICE_NAME_LEN] = "BLE_BT5_PERIPHERAL";
   uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN;
   le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name);
   le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance);

   /* GAP Bond Manager parameters */
   ......
   gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode);
   gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags);
   gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap);
   gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob);
   le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey);
   le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey),
                     &auth_use_fix_passkey);
   le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags),
                     &auth_sec_req_flags);

   /* LE Advertising Extensions parameters */
   bool use_extended = true;
   le_set_gap_param(GAP_PARAM_USE_EXTENDED_ADV, sizeof(use_extended), &use_extended);

   /* register GAP message callback */
   le_register_app_cb(app_peripheral_gap_callback);

   /* LE manager module initialize */
   app_peripheral_gap_ble_mgr_init();

   /* advertising parameters initialize */
   app_peripheral_adv_init_conn_undirect_public();
}
  1. le_set_gap_param()

  2. gap_set_param() and le_bond_set_param()

    Initialize GAP pairing parameters.

  3. le_register_app_cb()

    Register the GAP message callback function app_peripheral_gap_callback(), and all GAP callback messages will be handled in this callback.

  4. app_peripheral_gap_ble_mgr_init()

    Initialize the LE manager library. More information on LE manager library initialization can be found in the chapter LE Manager Initialization of LE Manager.

    void app_peripheral_gap_ble_mgr_init(void)
    {
       BLE_MGR_PARAMS param = {0};
       param.ble_ext_adv.enable = true;
       param.ble_ext_adv.adv_num = 1;
       ble_mgr_init(&param);
    }
    
  5. app_peripheral_adv_init_conn_undirect_public()

    Initialize advertising parameters. Developers can set flags according to advertising event properties with Table Extended Advertising Parameters Setting with Legacy Advertising PDUs or Table Extended Advertising Parameters Setting with Extended Advertising PDUs. More information on LE Extended Advertising can be found in the chapter Advertising Parameter Initialization of LE Manager.

More information on LE GAP initialization and startup flow can be found in the chapter GAP Parameters Initialization of LE Host.

Start Extended Advertising

Due to support of the LE Advertising Extensions, the device can use one or more advertising sets. The sample needs to create an advertising handle to identify the advertising set and extended advertising related parameters are configured for a specified advertising set. Using LE Advertising Extensions, the sample can choose to send legacy advertising PDUs ( LE Peripheral sample can only send legacy advertising PDUs) or extended advertising PDUs by modifying advertising event properties.

More information on LE Extended Advertising can be found in the chapter LE Extended Advertising Manager of LE Manager.

GAP Message Handler

app_peripheral_gap_handle_gap_msg() function is invoked whenever a GAP message is received from the Bluetooth Host. More information on GAP messages can be found in the chapter Bluetooth LE GAP Message of LE Host.

When the sample handles GAP message, the ble_mgr_handle_gap_msg() shall be called to handle the GAP message.

void app_peripheral_gap_handle_gap_msg(T_IO_MSG *p_gap_msg)
{
   T_LE_GAP_MSG gap_msg;
   uint8_t conn_id;
   memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param));
   ble_mgr_handle_gap_msg(p_gap_msg->subtype, &gap_msg);

   APP_PRINT_TRACE1("app_peripheral_gap_handle_gap_msg: subtype %d", p_gap_msg->subtype);
   switch (p_gap_msg->subtype)
   {
   case GAP_MSG_LE_DEV_STATE_CHANGE:
       {
           app_peripheral_gap_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state,
                                                   gap_msg.msg_data.gap_dev_state_change.cause);
       }
       break;
   .......
 }

The sample will call app_peripheral_adv_start() to start advertising when receiving GAP_INIT_STATE_STACK_READY. If app_peripheral_adv_start() returns true , it means LE manager library has already received this command and is ready to execute. When the sample runs on the EVB, the device will send connectable advertising events and can be connected as a peripheral role by a remote device.

void app_peripheral_gap_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause)
{
   APP_PRINT_INFO3("app_peripheral_gap_handle_dev_state_evt: init state %d, ADV state %d, cause 0x%x",
                  new_state.gap_init_state, new_state.gap_adv_state, cause);
   if (gap_dev_state.gap_init_state != new_state.gap_init_state)
   {
      if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY)
      {
            APP_PRINT_INFO0("app_peripheral_gap_handle_dev_state_evt: GAP stack ready");
            /* Stack ready */
            ......
            /*start advertising*/
            app_peripheral_adv_start(0);
      }
   }
   gap_dev_state = new_state;
}

When the sample receives the GAP_CONN_STATE_DISCONNECTED message, it will call the app_peripheral_adv_start() function again to start advertising. After disconnecting, the sample will be restored to the status that is discoverable and connectable again.

void app_peripheral_gap_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause)
{
   APP_PRINT_INFO4("app_peripheral_gap_handle_conn_state_evt: conn_id %d old_state %d new_state %d, disc_cause 0x%x",
                  conn_id, gap_conn_state, new_state, disc_cause);
   switch (new_state)
   {
   case GAP_CONN_STATE_DISCONNECTED:
      {
            if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE))
               && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE)))
            {
               APP_PRINT_ERROR1("app_peripheral_gap_handle_conn_state_evt: connection lost cause 0x%x", disc_cause);
            }
            /*start advertising*/
            app_peripheral_adv_start(0);
      }
      break;
   ......
   }
   gap_conn_state = new_state;
}

GAP Callback Handler

app_peripheral_gap_callback() function is used to handle GAP callback messages. More information on GAP callback can be found in the chapter Bluetooth LE GAP Callback of LE Host.

When the sample handles GAP callback, the ble_mgr_handle_gap_cb() shall be called to handle the callback message.

T_APP_RESULT app_peripheral_gap_callback(uint8_t cb_type, void *p_cb_data)
{
   T_APP_RESULT result = APP_RESULT_SUCCESS;
   T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data;
   ble_mgr_handle_gap_cb(cb_type, p_cb_data);

   APP_PRINT_TRACE1("app_peripheral_gap_callback: cb_type = 0x%x", cb_type);

   switch (cb_type)
   {
   case GAP_MSG_LE_DATA_LEN_CHANGE_INFO:
       APP_PRINT_INFO3("app_peripheral_gap_callback: GAP_MSG_LE_DATA_LEN_CHANGE_INFO conn_id %d, tx octets 0x%x, max_tx_time 0x%x",
                       p_data->p_le_data_len_change_info->conn_id, p_data->p_le_data_len_change_info->max_tx_octets,
                       p_data->p_le_data_len_change_info->max_tx_time);
       break;
     ......
   }
}