LE Peripheral Extended ADV

LE peripheral extended ADV 示例工程可以作为开发基于Peripheral角色的APP的框架。

特征:

  • 使用LE Advertising Extensions发送advertising events。

  • 同时使能一个或多个advertising set。

  • 设定advertising set使能的duration或最大的extended advertising events数目。

  • 使用extended advertising PDU s传输更多数据。

  • 可以作为Peripheral角色建立一条LE链路, PHYLE 1M PHYLE 2M PHYLE Coded PHY

简介

  • 使用LE Advertising Extensions的peripheral设备可以设置广播的持续时间或extended advertising event的最大数目,使能或禁用一个或多个advertising set。

  • 若使用extended advertising PDUs,可以扩展adv data或scan response data的长度,以及使用 LE Coded PHY 增大可以建立连线的距离。关于extended advertising PDUs和legacy advertising PDUs的信息参见 LE Host 中的 Extended Advertising相关参数的配置

  • 若Peripheral设备使用LE Advertising Extensions,开发者需要考虑与不同蓝牙版本的对端设备的兼容性,与不同蓝牙版本的对端设备的兼容性如下表所示:

使用LE Advertising Extensions的Peripheral设备的兼容性

Bluetooth 5 Feature

Advertising PDUs

Bluetooth 4.0

Bluetooth 4.1

Bluetooth 4.2

Bluetooth 5.0 (Not Use LE Advertising Extensions)

Bluetooth 5.0 (Use 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

环境需求

该示例支持以下开发工具包:

环境需求

Hardware Platforms

Board Name

RTL87x2G HDK

RTL87x2G EVB

为快速搭建起开发环境,可参考 快速入门 中提供的详细指导。

硬件连线

请参考 快速入门 中的 EVB接口和模块

配置

配置选项

该示例工程全部配置选项在 samples\bluetooth\ble_bt5_peripheral\src\app_flags.h 中, 开发者可以根据实际需求配置。

/** @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 LE_CODED_PHY_S8            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

生成系统配置文件

开发者可以通过MP Tool配置以下项目:

MP Tool配置

Configurable Item

Value

LE Slave Link Num

APP_MAX_LINKS

更多有关于MP Tool配置的信息请参考 快速入门 中的 生成System Config File

编译和下载

该示例可以在SDK文件夹中找到:

Project file: samples\bluetooth\ble_bt5_peripheral\proj\rtl87x2g\mdk

Project file: samples\bluetooth\ble_bt5_peripheral\proj\rtl87x2g\gcc

编译和运行该示例请遵循以下步骤:

  1. 打开项目文件。

  2. 要编译目标文件,请参考 快速入门编译APP Image 中列出的步骤。

  3. 编译成功后,目录 samples\bluetooth\ble_bt5_peripheral\proj\rtl87x2g\mdk\bin 下会生成app bin文件 app_MP_sdk_xxx.bin

  4. 要下载app bin到 EVB,请参考 快速入门MP Tool 下载 中列出的步骤。

  5. 在EVB上按下 reset 键,程序将开始运行。

测试验证

将示例工程烧录到EVB后,开发者可以使用另一个运行 LE Central Extended Scan 工程的开发板来与之对测。

与另一块开发板对测

测试流程请参考 LE Central Extended Scan 中的 与另一块开发板对测

代码介绍

本章将按照以下几个部分进行介绍:

源码路径

  • 工程目录: samples\bluetooth\ble_bt5_peripheral\proj

  • 源码目录: samples\bluetooth\ble_bt5_peripheral\src

LE peripheral extended advertising示例工程中的源文件当前被分为几个组,如下所示:

└── Project: bt5_peripheral
    └── secure_only_app
        └── Device                   includes startup code
        ├── CMSE Library             Non-secure callable library
        ├── Lib                      includes all binary symbol files that user application is built on
            ├── ROM_NS.lib
            └── lowerstack.lib
            └── rtl87x2g_sdk.lib
            └── gap_utils.lib
        ├── peripheral               includes all peripheral drivers and module code used by the application
        ├── Profile                  includes LE profiles or services used by the sample application
        └── APP                      includes the ble_bt5_peripheral user application implementation
            ├── app_task.c
            ├── main.c
            ├── bt5_peripheral_stack_api.c
            └── bt5_peripheral_app.c

示例工程使用与 bt_host_0_0 匹配的默认GAP LIB,请参阅文档 Bluetooth Host Image 中的 GAP LIB的使用方法 以获取更多信息。

Bluetooth Host介绍

示例工程默认使用Bluetooth Host image版本 bt_host_0_0,更多信息可参阅 Bluetooth Host Image

关于Bluetooth Host所支持的蓝牙功能的详细信息,请参阅文件 bin\rtl87x2g\bt_host_image\bt_host_0_0\bt_host_config.h

初始化

当EVB启动并且芯片复位时, main() 函数将被调用,它执行以下初始化函数:

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

   return 0;
 }
void app_le_gap_init(void)
{
   /* Device name and device appearance */
   ......

   /* GAP Bond Manager parameters */
   ......

   /* LE Advertising Extensions parameters */
   bool use_extended = true;

   /* Set device name and device appearance */
   le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name);
   le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance);
   le_set_gap_param(GAP_PARAM_SLAVE_INIT_GATT_MTU_REQ, sizeof(slave_init_mtu_req),
                   &slave_init_mtu_req);

   le_set_gap_param(GAP_PARAM_DEFAULT_DATA_LEN_MAX_TX_OCTETS, sizeof(max_data_len_tx_oct),
                   &max_data_len_tx_oct);
   le_set_gap_param(GAP_PARAM_DEFAULT_DATA_LEN_MAX_TX_TIME, sizeof(max_data_len_tx_time),
                   &max_data_len_tx_time);

   /* Setup the GAP Bond Manager */
   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);

   /* Use LE Advertising Extensions */
   le_set_gap_param(GAP_PARAM_USE_EXTENDED_ADV, sizeof(use_extended), &use_extended);

   /* Initialize extended advertising related parameters */
   le_init_ext_adv_params_ext_conn();

   /* Register gap message callback */
   le_register_app_cb(app_gap_callback);
}

更多关于LE GAP初始化和启动流程的信息可以查阅 LE Host 中的 GAP参数的初始化

启动Extended Advertising

由于支持LE Advertising Extensions,设备可以使用一个或多个advertising sets。 APP需要创建advertising handle以识别advertising set,extended advertising相关参数是针对指定advertising set配置的。 使用LE Advertising Extensions时,APP可以通过修改advertising event properties选择发送legacy advertising PDUs ( LE Peripheral 示例工程只能发送 legacy advertising PDUs)或extended advertising PDUs。

开启extended advertising的流程图如下所示。 Optional 部分取决于advertising event properties。

../../../../../_images/Start_Extended_Advertising_Flow_Chart.png

开启Extended Advertising流程图

GAP Extended Advertising相关参数配置

请参考 LE Host 中的 Extended Advertising相关参数的配置 章节。

GAP消息处理

当APP从Bluetooth Host接收到GAP消息时,函数 app_handle_gap_msg() 会被调用。更多关于GAP消息的信息参见 LE Host 中的 蓝牙状态消息

void app_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));

   APP_PRINT_TRACE1("app_handle_gap_msg: subtype %d", p_gap_msg->subtype);
   switch (p_gap_msg->subtype)
   {
   case GAP_MSG_LE_DEV_STATE_CHANGE:
       {
           app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state,
                                   gap_msg.msg_data.gap_dev_state_change.cause);
       }
       break;
   .......
 }
 void app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause)
{
   APP_PRINT_INFO3("app_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("GAP stack ready");
            /* Stack ready */
            ......
            /* Set extended advertising related parameters */
            le_ext_adv_start_setting(adv_handle, EXT_ADV_SET_AUTO);
      }
   }
   gap_dev_state = new_state;
}

当收到 GAP_INIT_STATE_STACK_READY 消息时,该示例工程将调用 le_ext_adv_start_setting() 设置extended advertising相关参数。 EXT_ADV_SET_AUTO 表示将根据advertising event properties自动设置针对指定advertising set的extended advertising相关参数(包括advertising参数、advertising数据和scan response数据)。否则,application需要参考表 使用legacy advertising PDUs的Extended Advertising参数设置 或表 使用extended advertising PDUs的Extended Advertising参数设置 根据advertising event properties设置flags。

void app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause)
{
   APP_PRINT_INFO3("app_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("GAP stack ready");
            /* Stack ready */
            ......
            /* Set extended advertising related parameters */
            le_ext_adv_start_setting(adv_handle, EXT_ADV_SET_AUTO);
      }
   }
   gap_dev_state = new_state;
}

app_gap_callback() 调用 le_ext_adv_enable() 之后,APP将收到extended advertising状态消息。更多关于处理extended advertising状态消息的信息参见 LE Host 中的 Extended Advertising状态消息。 当收到 GAP_CONN_STATE_DISCONNECTED 消息时,APP将调用 le_ext_adv_enable() 以使能指定advertising set。在连接断开之后,APP将恢复为可连接状态。

void app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause)
{
   APP_PRINT_INFO4("app_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_handle_conn_state_evt: connection lost cause 0x%x", disc_cause);
            }
            /* Enable one advertising set */
            le_ext_adv_enable(1, &adv_handle);
      }
      break;
   ......
   }
   gap_conn_state = new_state;
}

GAP回调函数处理

app_gap_callback() 用于处理GAP回调函数消息,更多关于GAP回调函数的信息参见 LE Host 中的 Bluetooth LE GAP回调函数

在协议栈准备就绪之后调用 le_ext_adv_start_setting(),设置extended advertising参数的结果将在函数 app_gap_callback() 中以回调类型 GAP_MSG_LE_EXT_ADV_START_SETTING 返回。若返回结果表示参数设置成功,APP将使能extended advertising。

首先,APP设置GAP extended advertising使能参数,以决定是否通过使用duration或最大的extended advertising events数目停止extended advertising。APP调用 le_ext_adv_enable() 对一个advertising set使能extended advertising,示例代码如下:

T_APP_RESULT app_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;

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

   switch (cb_type)
   {
   case GAP_MSG_LE_EXT_ADV_START_SETTING:
      APP_PRINT_INFO3("GAP_MSG_LE_EXT_ADV_START_SETTING:cause 0x%x, flag 0x%x, adv_handle %d",
                        p_data->p_le_ext_adv_start_setting_rsp->cause, p_data->p_le_ext_adv_start_setting_rsp->flag,
                        p_data->p_le_ext_adv_start_setting_rsp->adv_handle);

      if (p_data->p_le_ext_adv_start_setting_rsp->cause == GAP_CAUSE_SUCCESS)
      {
            /* Initialize enable parameters */
            le_init_ext_adv_enable_params(p_data->p_le_ext_adv_start_setting_rsp->adv_handle);
            /* Enable one advertising set */
            le_ext_adv_enable(1, &p_data->p_le_ext_adv_start_setting_rsp->adv_handle);
      }
      break;
   ......
   }
}

Extended advertising状态消息在 app_handle_gap_msg() 函数中处理。使能advertising set的结果将在 app_gap_callback() 中以回调类型 GAP_MSG_LE_EXT_ADV_ENABLE 返回,示例代码如下:

T_APP_RESULT app_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;

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

   switch (cb_type)
   {
   case GAP_MSG_LE_EXT_ADV_ENABLE:
      APP_PRINT_INFO1("GAP_MSG_LE_EXT_ADV_ENABLE:cause 0x%x", p_data->le_cause.cause);
      break;
   ......
   }
}

当Peripheral extended advertising示例工程在开发板上运行时,设备是可发现且可连接的。对端设备可以对peripheral设备进行扫描,并创建连线。