LE DTM

dtm sample project is used to control the DUT and provides a report back to the Tester.

Overview

DTM is used to test the RF PHY layer of Bluetooth low energy devices. It can be set up by one of the two alternative methods: Over HCI or through a 2-wire UART interface.

In this document, DUT implements the second method, which is set through a 2-wire UART interface. The test framework of through 2-wire UART interface is shown below:

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

Test Framework for using a 2-Wire UART Interface

Step instructions:

  1. DUT runs DTM application, and test equipment of MT8852B sends DTM commands to DUT.

  2. DTM application analyzes commands and invokes APIs to send(Transmitter Test) and receive(Receiver Test) packets from MT8852B.

  3. DTM application collects test results and sends them to MT8852B by DTM events.

  4. MT8852B judges and displays the results.

Transmitter Test

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

Transmitter Test MSC

Upper Tester sends command to DUT to order it to transmit test packets to Lower Tester. DUT reports event to Upper Tester after transmit procedure terminates.

  • Output Power Test

    The MT8852B transmits a test control message over the RS232, USB, or 2-wire interface to instruct the DUT to transmit reference test packets. The MT8852B measures the average power of the received packets over at least 20% to 80% of the duration of the burst.

  • Carrier & Drift Test

    The carrier drift test performs a frequency drift measurement over the length of the packet received. The carrier frequency offset is measured similarly to the basic rate initial carrier test, but on the eight preamble bits in the low energy reference packet.

  • Modulation Index Test

    This test measures the modulation characteristics on the DUT output for each of the selected frequency ranges (LOW, MEDIUM, and HIGH).

Receiver Test

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

Receiver Test MSC

Upper Tester sends command to DUT to order DUT to prepare to receive test packets from Lower Tester. Lower Tester sends test packets to DUT, and DUT reports event to Upper Tester after receive procedure terminates.

  • Sensitivity Test

    After sending a test control to prepare the DUT, the MT8852B sends LE reference packets to the DUT. The number of packets DUT received is counted and this data is then read by the MT8852B over the 2-wire connection.

  • PER Integrity

    The MT8852B sends a random even number of LE reference packets to the DUT at -30 dBm with a PRBS9 payload. The CRC value for the packets is alternated between a valid and invalid value. The DUT counts the number of received packets and this value is read by the MT8852B over the 2-wire interface for frame error rate (FER) calculation. The test is repeated three times at the frequency selected.

  • Maximum Input Power Test

    After sending a test control, the MT8852B sends LE reference packets to the DUT at -10 dBm. The number of packets received by the DUT is counted, and this data is then read by the MT8852B over the 2-Wire connection.

Environmental Requirements

The sample supports the following development kits:

Development Kits

Hardware Platforms

Board Name

RTL8752H HDK

RTL8752H EVB

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

Hardware Connections

Please refer to RTL8752H EVB Interfaces and Modules in Quick Start.

Building and Downloading

This sample can be found in the SDK folder:

Project file: board\evb\dtm\mdk

Project file: board\evb\dtm\gcc

To build and run the sample, follow the steps listed below:

  1. Open the project file.

  2. To build the target, follow the steps listed in the Generating App Image section in Quick Start.

  3. After a successful compilation, the APP bin app_MP_sdk_xxx.bin will be generated in the directory board\evb\dtm\mdk\bin.

  4. To download APP bin into the EVB, please follow the steps listed in the MP Tool Download section in Quick Start.

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

Experimental Verification

This section gives a brief introduction of test steps and test results in detail.

Preparation Phase

  1. Downloading DTM Application

    Compile and download DTM application to DUT.

  2. Connecting DUT and MT8852B

    1. The first step is to connect the DUT and MT8852B through the 2-wire UART using RS232. The TX pin and RX pin of the DUT should be connected with the same pin of RS232.

    2. DTM application sets P3_1 as the TX pin of data UART and P3_0 as the RX pin of data UART by default.

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

      UART of MT8852B

Testing Phase

  1. Configuring DUT and MT8852B

    As shown below, press the On/Standby button to start MT8852B, and then press the EUT addr button to modify the EUT address.

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

    Start up MT8852B

    1. DUT implements DTM application based on 2-Wire UART, so first press the Sel button, then choose BLE2WIRE as the Source.

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

      Select source of EUT address

    2. Press the Setup button to set Low energy script.

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

      Set up Low energy script

  2. Running MT8852B

    1. Run All Test Cases

      Press the Run button to run all test cases.

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

      Run all test cases

    2. Run Single Test Case

      Choose the case to test and then press the Single button and the Run button to run a single test case.

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

      Run single test case

Test Results

The passed test result is shown below. The letter P will display after the passed test case.

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

DTM Test Result

Code Overview

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

Source Code Directory

  • Project directory: board\evb\dtm.

  • Source code directory: src\sample\dtm.

Source files in dtm project are currently categorized into several groups as below.

└── Project: dtm
    └── dtm
        └── include
        ├── lib                      Includes all binary symbol files that user application is built on.
            ├── ROM.lib
            ├── gap_utils.lib
            ├── lowerstack.lib
            └── rtl8752h_sdk.lib
        ├── cmsis                    Includes startup code.
        ├── peripheral               Includes all peripheral drivers and module code used by the application.
        └── app                      Includes the ble_scatternet user application implementation.
            ├── 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.
            └── overlay_mgr.c

The sample uses default GAP LIB that matches with upperstack_0_0, please refer to Usage of GAP LIB in Host Image for more information.

Bluetooth Host Overview

The sample uses the default Bluetooth Host image in upperstack_0_0, please refer to Host Image for more information.

For details of Bluetooth technology features supported by the Bluetooth Host, please refer to the file bin\upperstack_img\upperstack_0_0\upperstack_config.h.

Initialization

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

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() function is used to initialize GAP and configure the link number.

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

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

Main Functions

In dtm_app.c, Description of the main functions is as follows:

  • UART0_Handler() receives commands from MT8852B.

    Sample code is as follows:

    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() handles test command from MT8852B, then invokes GAP API to start test. Sample code is listed as below:

    Sample code is as follows:

    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:
                /*
                8852B 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() sends event to MT8852B. Sample code is listed as below:

    Sample code is as follows:

    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 Callback Handler

app_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 test begins, the GAP Layer will use GAP_MSG_LE_DTM_ENHANCED_RECEIVER_TEST or GAP_MSG_LE_DTM_ENHANCED_TRANSMITTER_TEST message to inform application to perform Transmitter Test or Receiver Test.

Sample code is listed as below:

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;
}