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

1000-2000ms delay during sd_ble_gattc_write

Hello all,

In controlling two devices simultaneously from one central controller, I have noticed significant time delays in processing the second call to sd_ble_gattc_write() but only some of the time (~25%). The code is basically below, some things renamed -

// Write characteristic to all connected devices
void write_charas(uint16_t uuid, uint8_t val) {
	uint32_t err_code;
	static ble_gattc_write_params_t write_params;
	static uint8_t tmp_data;
	tmp_data = val;

	write_params.write_op = BLE_GATT_OP_WRITE_CMD;
	write_params.offset = 0;
	write_params.len = 1;
	write_params.flags = 0;
	write_params.p_value = &tmp_data;

	for(uint8_t i = 0; i < rbcf.num_devices; i++) {
		if(rbcf.devices[i].connected) {
			// Check each of the characteristics for the UUID we are asking for
			for(uint8_t c = 0; c < rbcf.devices[i].dev_db.services[0].char_count; c++) {
				if(rbcf.devices[i].dev_db.services[0].charateristics[c].characteristic.uuid.uuid == uuid) {
					// We found it, so set the handle to the chara handles and write the characteristic
					write_params.handle = rbcf.devices[i].dev_db.services[0].charateristics[c].characteristic.handle_value;
					NRF_LOG_PRINTF("Writing %d to characteristic value %d\r\n", val, write_params.handle);
					err_code = sd_ble_gattc_write(rbcf.devices[i].conn_handle, &write_params);
					NRF_LOG_PRINTF("Write result for CH %d was %d\r\n", rbcf.devices[i].conn_handle, err_code);
				}
			}
		}
	}
}

The above code pretty much just wraps a characteristic write call with some logic to delegate that call to a number of connected devices.

  1. BLE_GATT_OP_WRITE_CMD uses an internal buffer, for which I would receive BLE_ERROR_NO_TX_BUFFERS - this is not occurring
  2. In fact, err_code is always NRF_SUCCESS
  3. BLE_GATT_OP_WRITE_REQ always works immediately, if it works - but it's not guaranteed to work because technically, you would need to wait for a RESP event. Sometimes, it receives NRF_ERROR_BUSY, which is to be expected.

The next thing I was going to try was to implement a transmit queue that sends BLE_GATT_OP_WRITE_REQ, and on RESP event, sends the next item in the queue. However, it sounds like writes using BLE_GATT_OP_WRITE_CMD should already be buffered, and I never get any errors from it, but it's incredibly slow. Why is there a difference in the timing characteristics of BLE_GATT_OP_WRITE_CMD and BLE_GATT_OP_WRITE_REQ? If the timing were fixed, I wouldn't need to re-develop the transmit queue.

Obviously, I don't need these two events to happen absolutely simultaneously; within a few connection intervals is acceptable. Above 500ms is when it starts getting noticeably incorrect, and the 2s I am seeing feels like an error in the configuration somewhere since nearly everything else happens imperceptibly fast. It shouldn't take 100ms to scan 2 devices for all of their characteristics, and 20 times that time to send a queued characteristic write.

Just in case, I am using Eclipse/GCC, SD120, and the 10.0 SDK.

Any insight would be appreciated,

Thanks! -Alex

Parents
  • OK, I am not seeing that event on the central. I see the scan returns the address, the connection is performed and DB discovery is performed, and then the log is silent while the user performs no action.

    Which makes sense, because I have the same settings for the parameters in both the peripheral and central, so I wouldn't have expected a parameter update request.

Reply
  • OK, I am not seeing that event on the central. I see the scan returns the address, the connection is performed and DB discovery is performed, and then the log is silent while the user performs no action.

    Which makes sense, because I have the same settings for the parameters in both the peripheral and central, so I wouldn't have expected a parameter update request.

Children
No Data
Related