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

Getting a 0x3401=BLE_ERROR_GATTS_SYS_ATTR_MISSING from sd_ble_gatts_hvx

So I'm trying to write a value to a characteristic I have set up as in the code below (figure 1), using the code further below (figure 2).

The sd_ble_gatts_hvx call is coming back with BLE_ERROR_GATTS_SYS_ATTR_MISSING.  I've read here 

https://devzone.nordicsemi.com/f/nordic-q-a/1948/strange-error-code-13313-0x3401-returned-by-sd_ble_gatts_hvx

that this is perhaps normally handled with the BLE_GATTS_EVT_SYS_ATTR_MISSING event, and I'm supposed to make a call like I have in my figure 3 below.

However, this event is not being called.  I'm not sure if that's the cause of my error.

So, is there something wrong with my setup, my write, or have I somehow misrouted my event handling of BLE_GATTS_EVT_SYS_ATTR_MISSING?

(I have refactored quite a bit from the example, may have broken something.)

Thanks for any help!

Figure 1: setting up the characteristic

            //////////////////////////////////////////
            // Add State characteristic BLE_UUID_SMILE_STATE
            ////////////////////////////////////////// 

            memset(&add_char_params, 0, sizeof(add_char_params));
            add_char_params.uuid                      = BLE_UUID_SMILE_STATE;
            add_char_params.uuid_type                 = service_uuid.type;
            add_char_params.max_len                   = 10;
            add_char_params.init_len                  = sizeof(uint8_t);
            add_char_params.is_var_len                = true;
                        
            add_char_params.char_props.broadcast      = 0;
            add_char_params.char_props.read           = 1;
            add_char_params.char_props.write_wo_resp  = 0;
            add_char_params.char_props.write          = 0;
            add_char_params.char_props.notify         = 1;
            add_char_params.char_props.indicate       = 0;
            add_char_params.char_props.auth_signed_wr = 0;            
            add_char_params.read_access               = SEC_OPEN;
            add_char_params.write_access              = SEC_OPEN;
            add_char_params.cccd_write_access         = SEC_OPEN;

            err_code = characteristic_add(p_our_service->service_handle, &add_char_params,&(p_our_service->characteristichandles_State));            
            if (err_code != NRF_SUCCESS)             {                 RETURN_FAULT(10,err_code)   

Figure 2: code that writes

            uint16_t length = 10;
            uint8_t state_bytes[10];
            state_bytes[0] = 0xFF & (state >> 8);
            state_bytes[1] = 0xFF & (state >> 0);

            ble_gatts_hvx_params_t hvx_params;

            memset(&hvx_params, 0, sizeof(hvx_params));

            hvx_params.handle = m_our_service.characteristichandles_State.value_handle;
            hvx_params.type   =   BLE_GATT_HVX_NOTIFICATION;
            hvx_params.offset = 0;
            hvx_params.p_len  = &length;
            hvx_params.p_data = state_bytes;

            uint32_t err_code = sd_ble_gatts_hvx(  m_conn_handle, &hvx_params);

Figure 3: my handler for BLE_ERROR_GATTS_SYS_ATTR_MISSING

static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
    uint32_t err_code;

    switch (p_ble_evt->header.evt_id)
    {
// ... 

        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
            
            UART_SendString("[BLE event: BLE_GATTS_EVT_SYS_ATTR_MISSING]");    
        
            // No system attributes have been stored.
            err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
            APP_ERROR_CHECK(err_code);
            break;

  

    }
}

Parents
  • The call to sd_ble_gatts_sys_attr_set() will set the system attributes. If you have called it you will never get a BLE_GATTS_EVT_SYS_ATTR_MISSING event for the current connection (because they are no longer missing at that point).

    If you have enabled bonding in the Peer Manager, the Peer Manager should handle the BLE_GATTS_EVT_SYS_ATTR_MISSING event for you, and sets the persistent system attributes for you. In that case, you will get a PM_EVT_BONDED_PEER_CONNECTED event, and when the system attributes has been provided to the SoftDevice, you will get a PM_EVT_LOCAL_DB_CACHE_APPLIED event.

  • Thank you.  I have worked through the tutorials and have worked through a couple of projects where I never really needed anything called bonding (at least consciously).  Could you point me to a good primer for what bonding is?  Is It a BLE thing or a nordic thing?

    Also, I have inherited almost everything from the ble_example_uart project, I don't think it uses the peer manager, correct?

    Thanks again for the reply.

  • Could you point me to a good primer for what bonding is?  Is It a BLE thing or a nordic thing?

    It's a BLE thing. Take a look at this post.

    Also, I have inherited almost everything from the ble_example_uart project, I don't think it uses the peer manager, correct?

    Correct. If you are not using Bonding, you could set it with sd_ble_gatts_sys_attr_set() when the sd_ble_gatts_hvx function returns BLE_ERROR_GATTS_SYS_ATTR_MISSING, e.g. as shown in this MSC. Note that the central has to enable notification/indication before you can send the data with sd_ble_gatts_hvx().

Reply
  • Could you point me to a good primer for what bonding is?  Is It a BLE thing or a nordic thing?

    It's a BLE thing. Take a look at this post.

    Also, I have inherited almost everything from the ble_example_uart project, I don't think it uses the peer manager, correct?

    Correct. If you are not using Bonding, you could set it with sd_ble_gatts_sys_attr_set() when the sd_ble_gatts_hvx function returns BLE_ERROR_GATTS_SYS_ATTR_MISSING, e.g. as shown in this MSC. Note that the central has to enable notification/indication before you can send the data with sd_ble_gatts_hvx().

Children
Related