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

Multiple Characteristics and Notifications

Hi Forum,

i've started the development of an custom service on a nrf51822 with s110. The Service contains 4 Characteristics where notifications are enabled.

At the central side i use a nrf51822 with s120. On this Device the multilink_central app is running with modifications to my needs.

I can connect to a peer device and also dicover my characteristics. But when i only can set one characteristic to notify. ( enable_notify)

When i try to run this more than one time the software crashes.

Hope you can help me.

Edit: Ive attached the functions where i am stuck.

The Problem is i can only receive one hvx Notification -> last i discovered

static void notif_enable(client_t * p_client)
{
  uint32_t                 err_code;
  ble_gattc_write_params_t write_params;
  uint8_t                  buf[BLE_CCCD_VALUE_LEN];
     
  printf("In Notify Enable \r\n");

  p_client->state = STATE_NOTIF_ENABLE;

  buf[0] = BLE_GATT_HVX_NOTIFICATION;
  buf[1] = 0;

  write_params.write_op = BLE_GATT_OP_WRITE_REQ;
  write_params.handle   = p_client->srv_db.services[0].charateristics[p_client->char_index].cccd_handle;
  write_params.offset   = 0;
  write_params.len      = sizeof(buf);
  write_params.p_value  = buf;

  err_code = sd_ble_gattc_write(p_client->srv_db.conn_handle, &write_params);
  printf("Error Code: %i",err_code);
  //sd_app_evt_wait();
  wait(200000);
  APP_ERROR_CHECK(err_code);


}


static void db_discovery_evt_handler(ble_db_discovery_evt_t * p_evt)
{
  // Find the client using the connection handle.
  client_t * p_client;
  uint32_t   index;
  bool       is_valid_srv_found = false;

  index = client_find(p_evt->conn_handle);
  p_client = &m_client[index];

  if (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE)
  {
    uint8_t i;

    printf("Characteritics found: %i\r\n",p_evt->params.discovered_db.char_count);
    for (i = 0; i <= p_evt->params.discovered_db.char_count; i++)
    {
        ble_db_discovery_char_t * p_characteristic;

        p_characteristic = &(p_evt->params.discovered_db.charateristics[i]);
        printf("UUID: %x ",p_characteristic->characteristic.uuid.uuid);
        if ((p_characteristic->characteristic.uuid.uuid == TEXMESSBOX_PERIPHERAL_CHANNEL_1_UUID)
            &&
            (p_characteristic->characteristic.uuid.type == m_base_uuid_type))
        {
            // Characteristic found. Store the information needed and break.
    	printf("Texxmessbox Channel 1\r\n");
            p_client->char_index = i;
            is_valid_srv_found   = true;

            //break;
        }
        if ((p_characteristic->characteristic.uuid.uuid == TEXMESSBOX_PERIPHERAL_CHANNEL_2_UUID)
                        &&
                        (p_characteristic->characteristic.uuid.type == m_base_uuid_type))
                    {
                        // Characteristic found. Store the information needed and break.
    	printf("Texxmessbox Channel 2\r\n");
                        p_client->char_index = i;
                        is_valid_srv_found   = true;

                        //break;
                    }
        if ((p_characteristic->characteristic.uuid.uuid == TEXMESSBOX_PERIPHERAL_CHANNEL_3_UUID)
                                    &&
                                    (p_characteristic->characteristic.uuid.type == m_base_uuid_type))
                                {
                                    // Characteristic found. Store the information needed and break.
                	printf("Texxmessbox Channel 3\r\n");
                                    p_client->char_index = i;
                                    is_valid_srv_found   = true;
                                    //break;
                                }
        if ((p_characteristic->characteristic.uuid.uuid == TEXMESSBOX_PERIPHERAL_CHANNEL_4_UUID)
                                    &&
                                    (p_characteristic->characteristic.uuid.type == m_base_uuid_type))
                                {
                                    // Characteristic found. Store the information needed and break.
                	printf("Texxmessbox Channel 4\r\n");
                                    p_client->char_index = i;
                                    is_valid_srv_found   = true;
                                    //break;
                                }
    }
}

if (is_valid_srv_found)
{
  // Enable notification.
  printf("Enable Notification\r\n");
  notif_enable(p_client);
}
else
{
    printf("Error\r\n");
    p_client->state = STATE_ERROR;
  }

}

Parents
  • I think the issue here is that you are trying to send multiple write requests. You cannot send a new request before you have received a response, unlike the write command which has no response. Until the response is received, sd_ble_gattc_write() will return NRF_ERROR_BUSY. You should therefore either:

    1. Wait for BLE_GATTC_EVT_WRITE_RSP before sending a new write request.
    2. Change to write command, and track free application buffers.

    It is important to notice that option 1 will take a bit longer time (1-2 connection intervals per CCCD), compared to write command which can write to up to 6 per connection interval (depending on the peer and the softdevice version). Option 2 can also fail if the number of CCCDs go beyond the number of available application buffers, which means you have to keep track of these separately to run safely. This is done by waiting for BLE_EVT_TX_COMPLETE events and counting how many buffers that were freed. There are multiple threads about this on DevZone if you go for this option.

  • Hello Ulrich, I also have the same problem and I am waiting on the BLE_GATTC_EVT_WRITE_RSP before calling "sd_ble_gattc_write" again. I still get a BUSY error. What is the problem here?

Reply Children
Related