Master-slave communication problem

I have a master device and a slave device. The slave device has 6 characteristics, 4 of which are notif. I need to use the master device to obtain the data of these 4 characteristics. I use the directory under \examples\ble_central\ble_app_uart_c For example, I first modify the service and feature UUID, and then match 4 features. After burning to the development board, I can find the corresponding four features, but I cannot open two or more notifications. The following is the program I added,err_code = ble_nus_c_tx_2_notif_enable(p_ble_nus_c);The error data returned is 17

void ble_nus_c_on_db_disc_evt(ble_nus_c_t * p_ble_nus_c, ble_db_discovery_evt_t * p_evt)
{
ble_nus_c_evt_t nus_c_evt;
memset(&nus_c_evt,0,sizeof(ble_nus_c_evt_t));

ble_gatt_db_char_t * p_chars = p_evt->params.discovered_db.charateristics;

// Check if the NUS was discovered.
if ( (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE)
&& (p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_NUS_C_SERVICE)
&& (p_evt->params.discovered_db.srv_uuid.type == p_ble_nus_c->uuid_type))
{
for (uint32_t i = 0; i < p_evt->params.discovered_db.char_count; i++)
{
switch (p_chars[i].characteristic.uuid.uuid)
{
case BLE_UUID_NUS_C_RX_CHARACTERISTIC:
nus_c_evt.handles.nus_rx_handle = p_chars[i].characteristic.handle_value;
break;

case BLE_UUID_NUS_C_TX_1_CHARACTERISTIC:
nus_c_evt.handles.nus_tx_1_handle = p_chars[i].characteristic.handle_value;
nus_c_evt.handles.nus_tx_1_cccd_handle = p_chars[i].cccd_handle;
break;

case BLE_UUID_NUS_C_TX_2_CHARACTERISTIC:
nus_c_evt.handles.nus_tx_2_handle = p_chars[i].characteristic.handle_value;
nus_c_evt.handles.nus_tx_2_cccd_handle = p_chars[i].cccd_handle;
break;

case BLE_UUID_NUS_C_TX_3_CHARACTERISTIC:
nus_c_evt.handles.nus_tx_3_handle = p_chars[i].characteristic.handle_value;
nus_c_evt.handles.nus_tx_3_cccd_handle = p_chars[i].cccd_handle;
break;

case BLE_UUID_NUS_C_TX_4_CHARACTERISTIC:
nus_c_evt.handles.nus_tx_4_handle = p_chars[i].characteristic.handle_value;
nus_c_evt.handles.nus_tx_4_cccd_handle = p_chars[i].cccd_handle;
break;


default:
break;
}
}
if (p_ble_nus_c->evt_handler != NULL)
{
nus_c_evt.conn_handle = p_evt->conn_handle;
nus_c_evt.evt_type = BLE_NUS_C_EVT_DISCOVERY_COMPLETE;
p_ble_nus_c->evt_handler(p_ble_nus_c, &nus_c_evt);
}
}
}

static void on_hvx(ble_nus_c_t * p_ble_nus_c, ble_evt_t const * p_ble_evt)
{
ble_nus_c_evt_t ble_nus_c_evt;

// HVX can only occur from client sending.
if ( (p_ble_nus_c->handles.nus_tx_1_handle != BLE_GATT_HANDLE_INVALID)
&& (p_ble_evt->evt.gattc_evt.params.hvx.handle == p_ble_nus_c->handles.nus_tx_1_handle)
&& (p_ble_nus_c->evt_handler != NULL))
{

ble_nus_c_evt.evt_type = BLE_NUS_C_EVT_NUS_TX_1_EVT;
ble_nus_c_evt.p_data = (uint8_t *)p_ble_evt->evt.gattc_evt.params.hvx.data;
ble_nus_c_evt.data_len = p_ble_evt->evt.gattc_evt.params.hvx.len;

p_ble_nus_c->evt_handler(p_ble_nus_c, &ble_nus_c_evt);
// NRF_LOG_DEBUG("Client sending data.");
}
else if ( (p_ble_nus_c->handles.nus_tx_2_handle != BLE_GATT_HANDLE_INVALID)
&& (p_ble_evt->evt.gattc_evt.params.hvx.handle == p_ble_nus_c->handles.nus_tx_2_handle)
&& (p_ble_nus_c->evt_handler != NULL))
{

ble_nus_c_evt.evt_type = BLE_NUS_C_EVT_NUS_TX_2_EVT;
ble_nus_c_evt.p_data = (uint8_t *)p_ble_evt->evt.gattc_evt.params.hvx.data;
ble_nus_c_evt.data_len = p_ble_evt->evt.gattc_evt.params.hvx.len;

p_ble_nus_c->evt_handler(p_ble_nus_c, &ble_nus_c_evt);
// NRF_LOG_DEBUG("Client sending data.");
}
else if ( (p_ble_nus_c->handles.nus_tx_3_handle != BLE_GATT_HANDLE_INVALID)
&& (p_ble_evt->evt.gattc_evt.params.hvx.handle == p_ble_nus_c->handles.nus_tx_3_handle)
&& (p_ble_nus_c->evt_handler != NULL))
{

ble_nus_c_evt.evt_type = BLE_NUS_C_EVT_NUS_TX_3_EVT;
ble_nus_c_evt.p_data = (uint8_t *)p_ble_evt->evt.gattc_evt.params.hvx.data;
ble_nus_c_evt.data_len = p_ble_evt->evt.gattc_evt.params.hvx.len;

p_ble_nus_c->evt_handler(p_ble_nus_c, &ble_nus_c_evt);
// NRF_LOG_DEBUG("Client sending data.");
}
else if ( (p_ble_nus_c->handles.nus_tx_4_handle != BLE_GATT_HANDLE_INVALID)
&& (p_ble_evt->evt.gattc_evt.params.hvx.handle == p_ble_nus_c->handles.nus_tx_4_handle)
&& (p_ble_nus_c->evt_handler != NULL))
{

ble_nus_c_evt.evt_type = BLE_NUS_C_EVT_NUS_TX_4_EVT;
ble_nus_c_evt.p_data = (uint8_t *)p_ble_evt->evt.gattc_evt.params.hvx.data;
ble_nus_c_evt.data_len = p_ble_evt->evt.gattc_evt.params.hvx.len;

p_ble_nus_c->evt_handler(p_ble_nus_c, &ble_nus_c_evt);
// NRF_LOG_DEBUG("Client sending data.");
}
}

uint32_t ble_nus_c_tx_1_notif_enable(ble_nus_c_t * p_ble_nus_c)
{
VERIFY_PARAM_NOT_NULL(p_ble_nus_c);

if ( (p_ble_nus_c->conn_handle == BLE_CONN_HANDLE_INVALID)
||(p_ble_nus_c->handles.nus_tx_1_cccd_handle == BLE_GATT_HANDLE_INVALID)
)
{
return NRF_ERROR_INVALID_STATE;
}
return cccd_configure(p_ble_nus_c->conn_handle,p_ble_nus_c->handles.nus_tx_1_cccd_handle, true);
}

uint32_t ble_nus_c_tx_2_notif_enable(ble_nus_c_t * p_ble_nus_c)
{
VERIFY_PARAM_NOT_NULL(p_ble_nus_c);

if ( (p_ble_nus_c->conn_handle == BLE_CONN_HANDLE_INVALID)
||(p_ble_nus_c->handles.nus_tx_2_cccd_handle == BLE_GATT_HANDLE_INVALID)
)
{
return NRF_ERROR_INVALID_STATE;
}

return cccd_configure(p_ble_nus_c->conn_handle,p_ble_nus_c->handles.nus_tx_2_cccd_handle, true);
}

uint32_t ble_nus_c_tx_3_notif_enable(ble_nus_c_t * p_ble_nus_c)
{
VERIFY_PARAM_NOT_NULL(p_ble_nus_c);

if ( (p_ble_nus_c->conn_handle == BLE_CONN_HANDLE_INVALID)
||(p_ble_nus_c->handles.nus_tx_3_cccd_handle == BLE_GATT_HANDLE_INVALID)
)
{
return NRF_ERROR_INVALID_STATE;
}
return cccd_configure(p_ble_nus_c->conn_handle,p_ble_nus_c->handles.nus_tx_3_cccd_handle, true);
}

uint32_t ble_nus_c_tx_4_notif_enable(ble_nus_c_t * p_ble_nus_c)
{
VERIFY_PARAM_NOT_NULL(p_ble_nus_c);

if ( (p_ble_nus_c->conn_handle == BLE_CONN_HANDLE_INVALID)
||(p_ble_nus_c->handles.nus_tx_4_cccd_handle == BLE_GATT_HANDLE_INVALID)
)
{
return NRF_ERROR_INVALID_STATE;
}
return cccd_configure(p_ble_nus_c->conn_handle,p_ble_nus_c->handles.nus_tx_4_cccd_handle, true);
}

static void ble_nus_c_evt_handler(ble_nus_c_t * p_ble_nus_c, ble_nus_c_evt_t const * p_ble_nus_evt)
{
ret_code_t err_code;

switch (p_ble_nus_evt->evt_type)
{
case BLE_NUS_C_EVT_DISCOVERY_COMPLETE:
NRF_LOG_INFO("Discovery complete.");
err_code = ble_nus_c_handles_assign(p_ble_nus_c, p_ble_nus_evt->conn_handle, &p_ble_nus_evt->handles);
APP_ERROR_CHECK(err_code);

err_code = ble_nus_c_tx_1_notif_enable(p_ble_nus_c);
APP_ERROR_CHECK(err_code);
err_code = ble_nus_c_tx_2_notif_enable(p_ble_nus_c);
APP_ERROR_CHECK(err_code);
err_code = ble_nus_c_tx_3_notif_enable(p_ble_nus_c);
APP_ERROR_CHECK(err_code);
err_code = ble_nus_c_tx_4_notif_enable(p_ble_nus_c);
APP_ERROR_CHECK(err_code);


NRF_LOG_INFO("Connected to device with Nordic UART Service.");

ble_central_connenct_flag =1;
ble_central_connenct_running_flag =1;


break;

case BLE_NUS_C_EVT_NUS_TX_1_EVT:
ble_nus_chars_received_uart_print(p_ble_nus_evt->p_data, p_ble_nus_evt->data_len);
break;
case BLE_NUS_C_EVT_NUS_TX_2_EVT:
ble_nus_chars_received_uart_print(p_ble_nus_evt->p_data, p_ble_nus_evt->data_len);
break;
case BLE_NUS_C_EVT_NUS_TX_3_EVT:
ble_nus_chars_received_uart_print(p_ble_nus_evt->p_data, p_ble_nus_evt->data_len);
break;
case BLE_NUS_C_EVT_NUS_TX_4_EVT:
ble_nus_chars_received_uart_print(p_ble_nus_evt->p_data, p_ble_nus_evt->data_len);
break;

case BLE_NUS_C_EVT_DISCONNECTED:
NRF_LOG_INFO("Disconnected.NUS1111111");
ble_central_connenct_running_flag =0;
ble_central_disconnenct_flag =1;
break;
}
}

  • Hi,

    Your ble_nus_c_tx_2_notif_enable() calls cccd_configure() which in turn calls sd_ble_gattc_write(), and this must be where the return value 17 comes from. This is NRF_ERROR_BUSY, and is returned when a procedure is already in progress. That is the case here, as you called ble_nus_c_tx_1_notif_enable() immediately before this. The solution is to do as described in the API documentation for sd_ble_gattc_write: "For write with response, procedure already in progress. Wait for a @ref BLE_GATTC_EVT_WRITE_RSP event and retry."

Related