I've been using the device firmware update service for quite some time now. I'm looking to add the ble_nus
service, but this feature seems to fail when ble_dfus
is re-enabled. I check all my err_code
s and nothing ever fails. I just can't ever get my callback COMMS_OnNusDataReceived
to execute on data being received from the nrftoobox UART sub-app. Is there a known incompatibility with ble_dfus
and ble_nus
?
What is strange is that I can sometimes get this to work if the bootloader is also programmed. Without the bootloader programmed in, I can only get the ble_nus callback to execute if I comment out the ble_dfu_on_ble_evt
usage:
static void COMMS_InitServices(void) {
uint32_t err_code;
ble_dfu_init_t dfus_init;
ble_nus_init_t nus_init;
ble_bas_init_t bas_init;
ble_dis_init_t dis_init;
// Initialize the Device Firmware Update Service.
memset(&dfus_init, 0, sizeof(dfus_init));
dfus_init.evt_handler = dfu_app_on_dfu_evt;
dfus_init.error_handler = NULL; // Not used as only the switch from app to DFU mode is required and not full dfu service.
dfus_init.revision = DFU_REVISION;
err_code = ble_dfu_init(&comms.dfus, &dfus_init);
APP_ERROR_CHECK(err_code);
// Specify the callback to execute just before resetting
dfu_app_reset_prepare_set(COMMS_PrepareForReset);
// Initialize the Nordic UART Service
memset(&nus_init, 0, sizeof(nus_init));
nus_init.data_handler = COMMS_OnNusDataReceived;
err_code = ble_nus_init(&comms.nus, &nus_init);
APP_ERROR_CHECK(err_code);
// Initialize the Battery Service
memset(&bas_init, 0, sizeof(bas_init));
// Here the sec level for the Battery Service can be changed/increased
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.cccd_write_perm);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&bas_init.battery_level_char_attr_md.write_perm);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_report_read_perm);
bas_init.evt_handler = NULL;
bas_init.support_notification = true;
bas_init.p_report_ref = NULL;
bas_init.initial_batt_level = 100;
err_code = ble_bas_init(&bas, &bas_init);
APP_ERROR_CHECK(err_code);
// Initialize the Device Information Service
memset(&dis_init, 0, sizeof(dis_init));
ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, MANUFACTURER_NAME);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&dis_init.dis_attr_md.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&dis_init.dis_attr_md.write_perm);
err_code = ble_dis_init(&dis_init);
APP_ERROR_CHECK(err_code);
}
static void COMMS_InitAdvertising(void) {
uint32_t err_code;
ble_advdata_t advdata;
ble_advdata_t scanrsp;
// BUG ALERT: WE ONLY HAVE ENOUGH BYTES IN THE PAYLOAD FOR ONE CUSTOM UUID
ble_uuid_t adv_uuids[] = {
{BLE_UUID_NUS_SERVICE, comms.nus.uuid_type},
};
// Build and set advertising data
memset(&advdata, 0, sizeof(advdata));
advdata.name_type = BLE_ADVDATA_FULL_NAME;
advdata.include_appearance = false;
advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
memset(&scanrsp, 0, sizeof(scanrsp));
scanrsp.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
scanrsp.uuids_complete.p_uuids = adv_uuids;
err_code = ble_advdata_set(&advdata, &scanrsp);
APP_ERROR_CHECK(err_code);
// Initialize advertising parameters (used when starting advertising)
memset(&comms.adv_params, 0, sizeof(ble_gap_adv_params_t));
comms.adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND;
comms.adv_params.p_peer_addr = NULL; // Undirected advertisement.
comms.adv_params.fp = BLE_GAP_ADV_FP_ANY;
comms.adv_params.interval = APP_ADV_INTERVAL;
comms.adv_params.timeout = APP_ADV_TIMEOUT_IN_SECONDS;
}
static void COMMS_DispatchBleEvent(ble_evt_t* p_ble_evt) {
dm_ble_evt_handler(p_ble_evt);
ble_conn_params_on_ble_evt(p_ble_evt);
ble_nus_on_ble_evt(&comms.nus, p_ble_evt);
ble_dfu_on_ble_evt(&comms.dfus, p_ble_evt); //<-- IF I COMMENT THIS OUT, NUS WORKS
COMMS_OnBleEvent(p_ble_evt);
}
EDIT
Master Control Panel Screenshot of working trial using a PCA10000 on the PC side and my own device. I write to request firmware version and a valid response is returned. There are no changes to the firmware which is tracked with git. There is no bootloader on this device and I am running with the debugger. I can breakpoint in my callback:
In a failed trial, the NUS UART RX (data pathway TO the device) characteristic had handle 0x000E. This does NOT seem deterministic. There is a variable other than the firmware.
EDIT 2
I reduced the size of a large buffer in my application. I may have been close to consuming the limit of RAM for my variant? Things seem to be working better now. I wish there was a simpler way to monitor the RAM and Flash consumption. Perhaps a little usage report printed at the end of a successful compilation or some basic GUI element or some kind of coarse percentage is fine enough.