LE DTM

DTM 用于控制 DUT,并向Tester提供测试报告。

概述

Direct Test Mode用于测试低功耗蓝牙设备的 RF PHY 层。 DTM可以通过两种方式设置:基于 HCI 或者通过一个 2-wire UART 接口。

在本文档中, DTM通过第二种方式设置,即通过一个2-wire UART接口。其测试框架如图所示:

../../../../../_images/dtm_test_framework.png

使用2-wire UART interface的测试框架

  1. DUT运行DTM应用,测试设备MT8852B向DUT发送DTM命令。

  2. DTM应用分析收到的命令并调用相应接口以向MT8852B发送数据包(transmitter test)或从MT8852B接收数据包(receiver test)。

  3. DTM应用收集测试结果,并通过DTM事件发送给MT8852B。

  4. MT8852B根据DTM事件判断并显示测试结果。

Transmitter Test

../../../../../_images/dtm_transmiter_test.png

Transmitter Test消息序列图

Upper tester向DUT发送命令,使DUT发送测试数据包给lower tester。发送流程结束后,DUT会向upper tester回报事件。

  • 输出功率测试

    MT8852B通过RS232、USB 或2-Wire接口发送测试控制信息,以指导DUT发送相应测试数据包。MT8852B至少在20%~80%的burst持续时间内测量接收数据包的平均功率。

  • 载波 & 漂移测试

    基于接收数据包的长度,载波漂移测试执行频率漂移测量。以与基本速率初始载波测试同样的方式测量载波频率偏移,只针对low energy相关数据包的8位前同步码。

  • 调制指数测试

    针对选择的频率范围(LOW、MEDIUM和HIGH),该测试测量DUT输出的调制特性。

Receiver Test

../../../../../_images/dtm_receiver_test.png

Receiver Test消息序列图

Upper tester向DUT发送命令,使DUT准备接收lower tester发送的测试数据包。lower tester发送测试数据包给DUT,接收流程结束后,DUT向upper tester回报事件。

  • 灵敏度测试

    在向DUT发送测试控制信息后,MT8852B向DUT发送 LE 相关数据包。DUT统计收到数据包的数目,MT8852B通过2-Wire接口读取该参数。

  • 接收完整度测试

    采用-30 dBm发射功率和 PRBS 9 payload,MT8852B向DUT随机发送偶数个LE相关数据包。这些数据包的 CRC 为有效值或无效值。DUT记录接收数据包的数目,MT8852B通过2-Wire接口读取该参数以计算 FER。该测试将在选择的频率上重复三次。

  • 最大输入功率测试

    在向DUT发送测试控制信息后,MT8852B以-10 dBm发射功率向DUT发送LE相关数据包。DUT记录接收数据包的数目,MT8852B通过2-Wire接口读取该参数。

环境要求

该sample工程可以在以下开发板上运行:

环境要求

Hardware Platforms

Board Name

RTL87x2G HDK

RTL87x2G EVB

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

硬件连线

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

编译和下载

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

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

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

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

  1. 打开项目文件。

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

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

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

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

测试验证

本章节将对测试步骤和测试结果进行详细介绍。

准备步骤

下载DTM应用

编译和下载DTM应用到DUT。

连接DUT和MT8852B

第一步是使用RS232,通过2-wire UART连接DUT和MT8852B,DUT的TX引脚和RX引脚应与RS232的对应引脚相连。

DTM应用默认将 P3_1 设为Data UART的TX引脚,将 P3_0 设为Data UART的RX引脚。

#define DATA_UART_TX_PIN    P3_1
#define DATA_UART_RX_PIN    P3_0
../../../../../_images/dtm_mt8852b_uart.png

MT8852B的UART

../../../../../_images/dut_uart.png

DUT的UART

测试步骤

配置DUT和MT8852B

如图所示, 按 On/Standby 按钮以启动MT8852B,然后按 EUT ADDR 按钮修改EUT address。

../../../../../_images/dtm_mt8852b_init.png

启动MT8852B

先按 Sel 按钮,然后选择 BLE2WIRE 作为Source。

../../../../../_images/dtm_eut_address.png

选择EUT address中的Source

Setup 按钮设置Low energy脚本。

../../../../../_images/dtm_low_energy.png

设置Low energy脚本

运行MT8852B

根据测试用例运行MT8852B。

  • 运行所有测试用例

    Run 按钮运行所有测试用例。

../../../../../_images/dtm_test_scripts.png

运行所有测试用例

  • 运行单个测试用例

    选择需要测试的用例,然后按 Single 按钮和 Run 按钮运行单个测试用例。

../../../../../_images/dtm_test_single_script.png

运行单个测试用例

测试结果

Pass的测试结果如图所示,已经Pass的测试用例后面会显示字母 P

../../../../../_images/dtm_test_result.png

DTM测试结果

代码介绍

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

源码路径

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

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

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

└── Project: broadcast
    └── 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_scatternet user application implementation.
            ├── data_uart.c
            ├── app_task.c            Create message queue and application task.
            ├── dtm_app.c             Handle commands from MT8852B and return with events.
            └── main.c                Entry of application, initialize parameters and register application message callback.

示例工程使用与 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)
{
   le_gap_init(0);
   gap_lib_init();
   app_le_gap_init();
   application_task_init();
   os_sched_start();

   return 0;
 }
  • le_gap_init() 用于初始化GAP并配置链接个数。

  • app_le_gap_init() 用于初始化GAP参数。

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

主要函数

dtm_app.c 文件中, UART0_Handler() 接收来自8852B的命令。示例代码如下:

void UART0_Handler(void)
{
   uint8_t uartdata[2] = {0, 0};
   uint8_t *p = uartdata;
   uint16_t command = 0;
   uint32_t int_status = 0;
   int_status = UART_GetIID(UART0);

   UART_INTConfig(UART0, UART_INT_RD_AVA | UART_INT_LINE_STS, DISABLE);

   switch (int_status)
   {
   case UART_INT_ID_TX_EMPTY:
      break;

   case UART_INT_ID_RX_LEVEL_REACH:

   case UART_INT_ID_RX_TMEOUT:
      while (UART_GetFlagState(UART0, UART_FLAG_RX_DATA_RDY) == SET)
      {
            UART_ReceiveData(UART0, p++, 1);
            if (p - uartdata > 2)
            {
               break;
            }
      }
      command = (uartdata[0] << 8) | uartdata[1];
      APP_PRINT_INFO1("FORM 8852B: 0x%x", command);
      dtm_test_req(command);
      break;

   case UART_INT_ID_LINE_STATUS:
      break;

   default:
      break;
   }

   UART_INTConfig(UART0, UART_INT_RD_AVA, ENABLE);
   return;
}

dtm_test_req() 处理来自8852B的测试命令,调用GAP层接口测试。示例代码如下:

void dtm_test_req(uint16_t command)
{
   uint8_t contrl = 0;
   uint8_t param = 0;
   uint8_t tx_chann = 0;
   uint8_t rx_chann = 0;
   uint8_t data_len = 0;
   uint8_t pkt_pl = 0;
   uint8_t cmd = (command & 0xc000) >> 14;
   uint16_t event  = 0;

   //the upper 2 bits of the data length for any Transmitter or Receiver commands following
   static uint8_t up_2_bits = 0;
   //physical to use
   static uint8_t phy = 1;
   //modulation index to use
   static uint8_t mod_idx = 0;
   //local supported features
   static uint8_t lcl_feats[GAP_LE_SUPPORTED_FEATURES_LEN] = {0};

   switch (cmd)
   {
   case 0:
      contrl = (command & 0x3f00) >> 8;
      param = (command & 0xfc) >> 2;

      switch (contrl)
      {
      case 0:
            if (param == 0)
            {
               up_2_bits = 0;
               phy = 1;
               mod_idx = 0;
            }
            else
            {
               event |= 1;
            }
            dtm_uart_send_bytes(event);
            break;
      ......
      case 5:
            /*
            MT8852B do not send these commands
               0x00 Read supportedMaxTxOctets
               0x01 Read supportedMaxTxTime
               0x02 Read supportedMaxRxOctets
               0x03 Read supportedMaxRxTime
            */
            break;
      default:
            break;
      }
      APP_PRINT_INFO3("dtm_test_req: up_2_bits 0x%x, phy 0x%x, mod_idx 0x%x", up_2_bits, phy, mod_idx);
      break;

   ......
   }
}

dtm_uart_send_bytes() 向8852B发送事件。示例代码如下:

void dtm_uart_send_bytes(uint16_t event)
{
   uint8_t uartdata[2] = {0};
   uartdata[0] = (event & 0xff00) >> 8;
   uartdata[1] = event & 0xff;
   uint8_t *p_ch = uartdata;

   uint8_t i = 0;
   for (i = 0; i < 2; i++)
   {
      while (UART_GetFlagState(UART0, UART_FLAG_THR_EMPTY) != SET)
      {
            ;
      }
      UART_SendData(UART0, p_ch++, 1);
   }
}

GAP回调函数处理

app_gap_callback() 函数用于处理GAP回调函数消息。 更多关于GAP回调函数的信息可以查阅 LE Host 中的章节 Bluetooth LE GAP回调函数

当测试开始时,GAP层使用 GAP_MSG_LE_DTM_ENHANCED_RECEIVER_TEST 或者 GAP_MSG_LE_DTM_ENHANCED_TRANSMITTER_TEST 消息来通知APP执行 Transmitter Test 或者 Receiver Test。示例代码如下:

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;
   uint16_t status  = 0;
   uint16_t event = 0;
   APP_PRINT_INFO1("app_gap_callback: cb_type %d", cb_type);
   switch (cb_type)
   {
   ......
#if F_BT_LE_5_0_DTM_SUPPORT
   case GAP_MSG_LE_DTM_ENHANCED_RECEIVER_TEST:
#endif
      status = p_data->le_cause.cause;
      if (status == 0)
      {
            APP_PRINT_INFO2("app_gap_callback: event 0x%x, status 0x%x", (event & 0x8000) >> 15, event & 0x1);
      }
      else
      {
            event |= 1;
            APP_PRINT_INFO2("app_gap_callback: event 0x%x, status 0x%x", (event & 0x8000) >> 15, event & 0x1);
      }
      dtm_uart_send_bytes(event);
      break;

   ......
#if F_BT_LE_5_0_DTM_SUPPORT
   case GAP_MSG_LE_DTM_ENHANCED_TRANSMITTER_TEST:
#endif
      status = p_data->le_cause.cause;
      if (status == 0)
      {
            APP_PRINT_INFO2("app_gap_callback: event 0x%x, status 0x%x", (event & 0x8000) >> 15, event & 0x1);
      }
      else
      {
            event |= 1;
            APP_PRINT_INFO2("app_gap_callback: event 0x%x, status 0x%x", (event & 0x8000) >> 15, event & 0x1);
      }
      dtm_uart_send_bytes(event);
      break;

   case GAP_MSG_LE_DTM_TEST_END:
      status = p_data->p_le_dtm_test_end_rsp->cause;
      if (status == 0)
      {
            event |= 1 << 15;
            event |= p_data->p_le_dtm_test_end_rsp->num_pkts;
            APP_PRINT_INFO2("app_gap_callback: event 0x%x, packet count 0x%x", (event & 0x8000) >> 15,
                           event & 0x7fff);
      }
      else
      {
            event |= 1;
            APP_PRINT_INFO2("app_gap_callback: event 0x%x, status 0x%x", (event & 0x8000) >> 15, event & 0x1);
      }
      dtm_uart_send_bytes(event);
      break;
   }

   return result;
}