4. Preparing the Periheral

The tests use a modified version of DA1469x Custom Bluetooth Service which can also be found here under the Software Applications & Examples section, along with a modified ble_central project that comes along with the SDK. This chapter and the next are dedicated to explaining the changes that need to be made to the peripheral in order to be able to test all the use cases described in chapter 2.2.

For the reader’s convenience, DA1469x Tutorial Power Measurement provides pc_custom_service_periph project where all the changes discussed in this and the next chapter are implemented and the various parameters are summed up in a header file called custom_config_power_consumption.h in the config folder of pc_custom_service_periph project. Altering the values in the header file can cover a very diverse set of use cases.

4.1. Generic Changes

This section will guide the reader step by step to perform the relevant modifications required on Bluetooth Custom Service example code. The goal of these modifications is to cover all the test scenarios from the peripheral side, as discussed in Chapter 2: Background.

4.1.1. Characteristic Declaration

For the declaration of a characteristic, a macro has been defined in file ble_custom_service.h. The macro is declared as follows:

#define CHARACTERISTIC_DECLARATION(_characteristic_uuid, _characteristic_max_size, _write_prop,             \\
                                        _read_prop, _notifications, _characteristic_user_descriptor,        \\
                                                                           _read_cb, _write_cb, _event_cb)  \\
                                                                                                            \\
        {                                                                                                   \\
                  .characteristic_128_uuid             = #_characteristic_uuid,                             \\
                  .characteristic_max_size             = _characteristic_max_size,                          \\
                  .characteristic_write_prop           = _write_prop,                                       \\
                  .characteristic_read_prop            = _read_prop,                                        \\
                  .notifications                       = _notifications,                                    \\
                  .characteristic_user_descriptor      = #_characteristic_user_descriptor,                  \\
                  .characteristic_user_descriptor_size = sizeof(#_characteristic_user_descriptor),          \\
                  {                                                                                         \\
                          .get_characteristic_value = _read_cb,                                             \\
                          .set_characteristic_value = _write_cb,                                            \\
                          .event_sent               = _event_cb,                                            \\
                  }                                                                                         \\
         }

The above macro creates an object of mcs_characteristic_config_t type and sets its fields to the values of the parameters passed when the macro is called. One of the parameters is _characteristic_max_size which sets the size of the characteristic.

The macro also takes three parameters in order to set the corresponding properties of the characteristic. These properties are _write_prop , _read_prop, and _notifications. Since one of the test cases involves ATT Write no Response Operations an extra property has to be set and enabled. For this reason we need to do the following:

  • In file ble_custom_service.h

    Create a new enum type for the Write no Response property:

typedef enum
{
      CHAR_WRITE_NO_RESP_PROP_DIS = 0,
      CHAR_WRITE_NO_RESP_PROP_EN  = 1,
} CHAR_WRITE_NO_RESP_PROP;

Add an extra field to the mcs_characteristic_config struct as highlighted below:

typedef struct mcs_characteristic_config {

      const char     *characteristic_128_uuid;
      uint16_t       characteristic_max_size;

      /* Characteristic permissions (at GATT level) */
      CHAR_WRITE_NO_RESP_PROP         characteristic_write_no_response_prop;
      CHAR_WRITE_PROP                 characteristic_write_prop;
      CHAR_READ_PROP                  characteristic_read_prop;
      CHAR_NOTIF                      notifications;

      /* Characteristic User Descriptor attribute */
      const char     *characteristic_user_descriptor;
      uint16_t       characteristic_user_descriptor_size;

      /* Callback functions */
      const mcs_characteristic_cb_t cb;

} mcs_characteristic_config_t;

Alter the CHARACTERISTIC_DECLARATION macro by adding the highlighted lines:

#define CHARACTERISTIC_DECLARATION(_characteristic_uuid, _characteristic_max_size,                        \\
                                                                                   _write_no_resp_prop,   \\
                                                                _write_prop, _read_prop, _notifications,  \\
                                          _characteristic_user_descriptor, _read_cb, _write_cb, _event_cb)\\
                                                                                                          \\
      {                                                                                                   \\
                .characteristic_128_uuid               = #_characteristic_uuid,                           \\
                .characteristic_max_size               = _characteristic_max_size,                        \\
                .characteristic_write_no_response_prop = _write_no_resp_prop,                             \\
                .characteristic_write_prop             = _write_prop,                                     \\
                .characteristic_read_prop              = _read_prop,                                      \\
                .notifications                         = _notifications,                                  \\
                .characteristic_user_descriptor        = #_characteristic_user_descriptor,                \\
                .characteristic_user_descriptor_size   = sizeof(#_characteristic_user_descriptor),        \\
                {                                                                                         \\
                        .get_characteristic_value = _read_cb,                                             \\
                        .set_characteristic_value = _write_cb,                                            \\
                        .event_sent               = _event_cb,                                            \\
                }                                                                                         \\
      }

  • In file ble_custom_service.c

In the function that initializes the custom service mcs_init(), find the following code snippet and add to it the highlighted line to allow setting the write no response property during the characteristic declaration.

/*
 * 'Characteristic' declarations.
 */
ble_uuid_from_string(settings[i].characteristic_128_uuid, &uuid);

ble_gatts_add_characteristic(&uuid,((settings[i].characteristic_read_prop) ? GATT_PROP_READ : GATT_PROP_NONE) |
        ((settings[i].characteristic_write_no_response_prop) ? GATT_PROP_WRITE_NO_RESP   : GATT_PROP_NONE)    |
                 ((settings[i].characteristic_write_prop) ? GATT_PROP_WRITE    : GATT_PROP_NONE)    |
                 ((settings[i].notifications == 1)        ? GATT_PROP_NOTIFY   : GATT_PROP_NONE)    |
                 ((settings[i].notifications == 2)        ? GATT_PROP_INDICATE : GATT_PROP_NONE),
                                              ATT_PERM_RW, (settings[i].characteristic_max_size),
                      ((settings[i].characteristic_read_prop) ? GATTS_FLAG_CHAR_READ_REQ : 0x00),
                                                              NULL, &position->characteristic_h);

  • In ble_peripheral_task.c for simplicity’s sake find and replace the service declaration section with the following snippet which also contains the extra property. Now, only one service with one characteristic will be created.

//************ Characteristic declarations for the 1st custom BLE Service  *************
const mcs_characteristic_config_t custom_service_1[] = {

        /* Initialized Characteristic Attribute */
        CHARACTERISTIC_DECLARATION(11111111-0000-0000-0000-000000000001, CHARACTERISTIC_ATTR_VALUE_MAX_BYTES,
                CHAR_WRITE_NO_RESP_PROP_EN, CHAR_WRITE_PROP_EN, CHAR_READ_PROP_EN, CHAR_NOTIF_NOTIF_EN,
                Initialized Characteristic, get_var_value_cb, set_var_value_cb, event_sent_cb),



         // -----------------------------------------------------------------
         // -- Here you can continue adding more Characteristic Attributes --
         // -----------------------------------------------------------------


};
// ***************** Register the Bluetooth Service in Dialog BLE framework *****************
SERVICE_DECLARATION(custom_service_1, 11111111-0000-0000-0000-111111111111)

4.1.2. Sleep Mode

The system uses pm_sleep_mode_set() function in file main.c to set the sleep mode that the device will enter. Refer to the Datasheet for detailed information about the sleep modes of DA1469x products. The possible options for sleep are defined in the SDK file sys_power_mgr.h.

typedef enum {
        pm_mode_active = 0,
        pm_mode_idle,
        pm_mode_extended_sleep,
        pm_mode_deep_sleep,
        pm_mode_hibernation,
        pm_mode_sleep_max,
} sleep_mode_t;

Note

In deep sleep, the system can be woken either by external interrupt or possibly by some timer and it always starts from a cold reset state. For that particular reason, make sure that no BLE activity is scheduled to happen (e.g. advertising) when the system goes to sleep or the system will reboot everytime making it impossible to measure the deep sleep power consumption accurately.

4.1.3. Low Power Clock

Choosing the Low Power clock requires only the modification of a single entry in custom_config_qspi.h header file located under [project_path]/config folder.

Find #define dg_configUSE_LP_CLK entry and assign to it ( LP_CLK_32768 ) for XTAL32K, ( LP_CLK_RCX ) for RCX or ( LP_CLK_32000 ) if an external XTAL crystal oscillator is provided at 32Khz.

4.1.4. Maximum Transmission Unit

The maximum allowed MTU supported by DA1469x family products, is 512 Bytes. In order to enable it ble_gap_mtu_size_set() is called in file ble_peripheral_task. The parameter this function takes is the number of Bytes that can be sent per connection interval.

Calling this function will not set the MTU of a connection since it can only be set by the Central Device and not the Peripheral. However it will let the central know that the peripheral device can support up to that MTU. The Central in turn, when it exchanges MTU with the Peripheral, it will set it to the maximum supported by both devices.

4.1.5. Production Mode

Enabling production mode will make several parts of code to not be compiled and others to be optimized out effectively reducing the number of instructions that do not have a use in production mode. A typical example are all ASSERTs which are optimized out while in production mode. Exception to that are ASSERT_ERROR calls. Activating PRODUCTION mode requires a set of entries to custom_config_qspi.h file.

#define dg_configIMAGE_SETUP                    PRODUCTION_MODE
#define dg_configSKIP_MAGIC_CHECK_AT_START      (1)

Additionally, all printf() calls defined in Bluetooth Custom Service can be disabled by adding after the last #include the preprocessor directive

#define DBG_SERIAL_CONSOLE_ENABLE               (0)

It is also advised to avoid using unnecessary operations in the code or instructions that utilize components of the board that consume a lot of energy(e.g UART for printf). The more instructions executed, the more the time that ARM M33 remains active, consequently reducing the sleep time and consuming more power overall. While one or two such instructions will not alter the measurements significantly, when they pile up, in depth of time they can make a difference.