This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Adding NUS service in ble_app_buttonless_dfu example

I am developing with SDK 15.0.0

I want to add  NUS service in ble_app_buttonless_dfu example.

All I have done:

1. Add including files and including paths to the project.

2. Combine sdk_config.h files.

3. Add NUS definition and services as needed. Here is the code:

BLE_NUS_DEF(m_nus, NRF_SDH_BLE_TOTAL_LINK_COUNT); /**< BLE NUS service instance. */

// YOUR_JOB: Use UUIDs for service(s) used in your application.
static ble_uuid_t m_adv_uuids[] = {
{BLE_UUID_DEVICE_INFORMATION_SERVICE, BLE_UUID_TYPE_BLE},
{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}
};

/**@brief Function for initializing services that will be used by the application.
*/
static void services_init(void)
{
uint32_t err_code;
nrf_ble_qwr_init_t qwr_init = {0};
ble_dfu_buttonless_init_t dfus_init = {0};

// Initialize Queued Write Module.
qwr_init.error_handler = nrf_qwr_error_handler;

err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
APP_ERROR_CHECK(err_code);

// Initialize the async SVCI interface to bootloader.
err_code = ble_dfu_buttonless_async_svci_init();
APP_ERROR_CHECK(err_code);

dfus_init.evt_handler = ble_dfu_evt_handler;

err_code = ble_dfu_buttonless_init(&dfus_init);
APP_ERROR_CHECK(err_code);

// Initialize NUS.
ble_nus_init_t nus_init;
memset(&nus_init, 0, sizeof(nus_init));

nus_init.data_handler = nus_data_handler;

err_code = ble_nus_init(&m_nus, &nus_init);
APP_ERROR_CHECK(err_code);

}

/**@brief Function for initializing the Advertising functionality.
*/
static void advertising_init(void)
{
uint32_t err_code;
ble_advertising_init_t init;

memset(&init, 0, sizeof(init));

init.advdata.name_type = BLE_ADVDATA_FULL_NAME;
init.advdata.include_appearance = true;
init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
init.advdata.uuids_complete.p_uuids = m_adv_uuids;

init.config.ble_adv_fast_enabled = true;
init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
init.config.ble_adv_fast_timeout = APP_ADV_DURATION;

init.evt_handler = on_adv_evt;

err_code = ble_advertising_init(&m_advertising, &init);
APP_ERROR_CHECK(err_code);

ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
}

No error occurs in the compling and linking procedure.

But the device does not advertise. When I debug it with Keil, it stops at advertising_init() -> ble_advertising_init() -> // Copy advertising data:.ble_advdata_encode() -> // Encode 'complete' uuid list: uuid_list_encode() -> // Encode 16 bit UUIDs.: uuid_list_sized_encode() -> // Find encoded uuid size.: sd_ble_uuid_encode().

Inside the for loop of sd_ble_uuid_encode(), the function encoded two ble_uuid into the advertising data: DIS and NUS service. During the first loop, encoding DIS service, everything seems to be fine. However, during the second loop, encoding NUS service, the return err_code = 0x07 (NRF_ERROR_INVALID_PARAM).

I have compared with ble_app_uart example. In NUS example, running to Line 265, the value of uuid is the same.

I do not know why the error occurs.

  • This is either due to an invalid UUID type(ble_uuid_t), or too much data in the advertisment data. When adding UUIDs it's easy to fill up the advertising data. If this is the case then you should use shorter UUIDs or place some in the scan response packet. 

  • Thanks. You give me two possible solutions, but neither of them works well.

    1. Invalid UUID type

    The NUS UUID type is defined as NUS_SERVICE_UUID_TYPE. And in the main function, we have

    #define NUS_SERVICE_UUID_TYPE           BLE_UUID_TYPE_VENDOR_BEGIN                  /**< UUID type for the Nordic UART Service (vendor specific). */

    Therefore the UUID type of NUS is valid.

    2. Place some in scan response packet

    The err_code = 0x07, NRF_ERROR_INVALID_PARAM. If this is due to too much data in the advertisement data, I think the returned err_code should be 0x04, NRF_ERROR_NO_MEM.

    Anyway I follow your advice and move the NUS UUID into  scan response packet and modify the program as below.

    However, when encoding the srdata in ble_advertising_init(),, the same error code occurs (0x07, NRF_ERROR_INVALID_PARAM).

     

  • well the API doc for sd_ble_uuid_encode says:
    Return values

    NRF_SUCCESS Successfully encoded into the buffer.
    NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
    NRF_ERROR_INVALID_PARAM Invalid UUID type.


    This means that the UUID type for the UUID that sd_ble_uuid_encode checks in the list of UUIDs provided is invalid. 

    "Inside the for loop of sd_ble_uuid_encode(), the function encoded two ble_uuid into the advertising data: DIS and NUS service. During the first loop, encoding DIS service, everything seems to be fine. However, during the second loop, encoding NUS service, the return err_code = 0x07 (NRF_ERROR_INVALID_PARAM)."

    You need to check the content of the 
    ble_advdata_uuid_list_t that is passed to uuid_list_sized_encode(). 

    _EDIT_

    I think the issue is that uuid_list_encode() first tries to encode a list of 16-bit UUIDs and then a list of 128-bit UUIDs. The DIS service UUID is a 16-bit BLE UUID and passes just fine, but the NUS service is a 128-bit vendor specific UUID and fails. 

  • Thank you again!

    I have fixed the problem by changing both DIS and NUS UUID type to BLE_UUID_TYPE_BLE in the advertising data. And then this error disappears.

    It is just a little odd that 16-bit and 128-bit UUID can not coexist。

    Furthermore, is the vendor specific UUID unique?It seems I have to delete the sd_ble_uuid_vs_add() in the ble_nus_init() since there is another operation in the ble_dfu_buttonless_init().

  • "It is just a little odd that 16-bit and 128-bit UUID can not coexist" 
    - I agree, I'll try to figure out why. You might have to use two lists of UUIDs, one for 16-bit UUIDs and one for 128-bit UUIDs. I'd try that before using the NUS service UUID as a 16-bit one. Those should be reserved for official BT SIG profiles. 

    "Furthermore, is the vendor specific UUID unique?"
    -Yeah I think the vendor specific UUID is unique, 

Related