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

characteristic_add() returns error 7 (invalid param)

I am trying to add a characteristic and am getting error 7 (invalid param).  I started out calling sd_ble_gatts_characteristic_add() directly but I realized that characteristic_add() in ble_srv_common.c already does a lot of the work for me - and either way, it made no difference.

I saw a number of places that the problem is not having enough memory allocated for UUIDs, so I increased this to 10 in sdk_config.h:

// <o> NRF_SDH_BLE_VS_UUID_COUNT - The number of vendor-specific UUIDs. 
#ifndef NRF_SDH_BLE_VS_UUID_COUNT
#define NRF_SDH_BLE_VS_UUID_COUNT 4
#endif

but that didn't solve the problem.  I think I can actually specify a 16-bit UUID here but it behaves the same either way:

void rv_service_init(rv_service_t *p_rv_service) {
  uint32_t err_code;
  ble_uuid_t service_uuid;
  ble_uuid128_t base_uuid = BLE_UUID_RV_BASE_UUID;

  ble_uuid_t temp_char_uuid;
  // Declare 16 bit service and 128 bit base UUIDs and add them to BLE stack table
  service_uuid.uuid = BLE_UUID_RV_SERVICE;
  err_code = sd_ble_uuid_vs_add(&base_uuid, &service_uuid.type);
  APP_ERROR_CHECK(err_code);

  // Add the service
  err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
      &service_uuid,
      &p_rv_service->service_handle);
  APP_ERROR_CHECK(err_code);

  //    SEGGER_RTT_WriteString(0, "Executing our_service_init().\n"); // Print message to RTT to the application flow
  //    SEGGER_RTT_printf(0, "Service UUID: 0x%#04x\n", service_uuid.uuid); // Print service UUID should match definition BLE_UUID_OUR_SERVICE
  //    SEGGER_RTT_printf(0, "Service UUID type: 0x%#02x\n", service_uuid.type); // Print UUID type. Should match BLE_UUID_TYPE_VENDOR_BEGIN. Search for BLE_UUID_TYPES in ble_types.h for more info
  //    SEGGER_RTT_printf(0, "Service handle: 0x%#04x\n", p_our_service->service_handle); // Print out the service handle. Should match service handle shown in MCP under Attribute values
}

static ble_gatts_attr_t attr_char_value;

void rv_char_init(rv_service_t *service) {

  uint32_t err_code;

  ble_add_char_params_t add_char_params;
  add_char_params.uuid = BLE_UUID_RV_TEMP; /* this is a 16 bit number */
  add_char_params.uuid_type = BLE_UUID_TYPE_BLE; /* BLE_UUID_TYPE_BLE (16 bit) or BLE_UUID_TYPE_VENDOR_BEGIN (128 bit) */  add_char_params.init_len = sizeof(uint8_t);
  add_char_params.max_len = sizeof(uint8_t);
  add_char_params.char_props.read = 1;
  add_char_params.char_props.write = 0;

  add_char_params.read_access = SEC_OPEN;
  add_char_params.write_access = SEC_OPEN;

  err_code = characteristic_add(service->service_handle, &add_char_params, &service->char_handles);
  APP_ERROR_CHECK(err_code);
}

I don't know for sure that running out of UUIDs in stack memory is the problem, but a lot of posts seem to suggest that it is.  If that's the case, do I have to do something OTHER than that #define ?

  • I think I figured out what i was doing wrong with error 7, but now I'm getting error 0x10 (decimal 16) from my call to: sd_ble_gatts_characteristic_add(service_handle, &char_md, &attr_char_value, p_char_handle);

    There are two points in that call, but what's strange is they are both pointers to structs in here:

    uint32_t characteristic_add(uint16_t service_handle, ble_add_char_params_t * p_char_props, ble_gatts_char_handles_t * p_char_handle)

    Here's what it looks like now:

    #include "rv_service.h"
    #include "ble_srv_common.h"
    #include <string.h>
    
    void rv_service_init(rv_service_t *service) {
      uint32_t err_code;
      ble_uuid128_t base_uuid = BLE_UUID_RV_BASE_UUID;
    
      // Declare 16 bit service and 128 bit base UUIDs and add them to BLE stack table
      err_code = sd_ble_uuid_vs_add(&base_uuid, &service->uuid_type);
      APP_ERROR_CHECK(err_code);
    
      ble_uuid_t service_uuid;
      service_uuid.uuid = BLE_UUID_RV_SERVICE;
      service_uuid.type = service->uuid_type;
    
      // Add the service
      err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
          &service_uuid,
          &service->service_handle);
      APP_ERROR_CHECK(err_code);
    
      //    SEGGER_RTT_WriteString(0, "Executing our_service_init().\n"); // Print message to RTT to the application flow
      //    SEGGER_RTT_printf(0, "Service UUID: 0x%#04x\n", service_uuid.uuid); // Print service UUID should match definition BLE_UUID_OUR_SERVICE
      //    SEGGER_RTT_printf(0, "Service UUID type: 0x%#02x\n", service_uuid.type); // Print UUID type. Should match BLE_UUID_TYPE_VENDOR_BEGIN. Search for BLE_UUID_TYPES in ble_types.h for more info
      //    SEGGER_RTT_printf(0, "Service handle: 0x%#04x\n", p_our_service->service_handle); // Print out the service handle. Should match service handle shown in MCP under Attribute values
    }
    
    static ble_gatts_attr_t attr_char_value;
    
    void rv_char_init(rv_service_t *service) {
    
      uint32_t err_code;
    
    
      ble_add_char_params_t add_char_params;
    
      add_char_params.uuid = BLE_UUID_RV_TEMP;
      add_char_params.uuid_type = service->uuid_type; /* BLE_UUID_TYPE_BLE (16 bit) or BLE_UUID_TYPE_VENDOR_BEGIN (128 bit) */
      add_char_params.init_len = sizeof(uint8_t);
      add_char_params.max_len = sizeof(uint8_t);
      add_char_params.char_props.read = 1;
      add_char_params.char_props.write = 1;
    
      add_char_params.read_access = SEC_OPEN;
      add_char_params.write_access = SEC_OPEN;
    
      err_code = characteristic_add(service->service_handle, &add_char_params, &service->char_handles);
      APP_ERROR_CHECK(err_code);
    }

    The sd_ble_gatts_characteristic_add() call is returning 0x10 which means:

    #define NRF_ERROR_INVALID_ADDR                (NRF_ERROR_BASE_NUM + 16) ///< Bad Memory Address

    which according to the documentation means "Invalid pointer supplied"

    [in] service_handle Handle of the service where the characteristic is to be placed, if BLE_GATT_HANDLE_INVALID is used, it will be placed sequentially.
    [in] p_char_md Characteristic metadata.
    [in] p_attr_char_value Pointer to the attribute structure corresponding to the characteristic value.
    [out] p_handles

    Pointer to the structure where the assigned handles will be stored.

    Which pointer?  I guess there's three pointers provided, none of them are NULL, so I'm not sure what's wrong.

  • OK maybe I figured that out, too.  Even though the blinky LBS service doesn't do this:

      add_char_params.is_value_user = false;

    seems to have made it pick the right place to put the value ..................... I notice a lot of this code doesn't set things that are supposed to default to zero.  I think the idea is the memsets (when present) clear all these things out.  I think I'd still prefer to be explicit .... 

Related