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.

Parents Reply Children
  • 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