Hello everyone,
I am a student that just got started with Nordic products and BLE. I am trying to build a small application that makes the nRF52840 DK periodically send some data to another device using notifications. The nRF52840 only needs to support the peripheral role. I have created a custom service and characteristic following this tutorial: https://devzone.nordicsemi.com/nordic/short-range-guides/b/bluetooth-low-energy/posts/ble-characteristics-a-beginners-tutorial. I am using the latest SDK version.
The custom service and characteristic worked fine until I tried to add the CCCD and enable notifications on the characteristic, I surrounded the part that breaks it with comments in the code below. When removing that specific part, the code runs fine again.
The error occurs at the bottom when calling the sd_ble_gatts_characteristic_add function. It return NRF_ERROR_INVALID_PARAM (0x07) so I gues the problem is in the char_md, but i can't spot it. I have included the code that inits the characteristic and the arguments passed to sd_ble_gatts_characteristic_add.
static uint32_t ee5_char_add(ble_os_t* p_service){ uint32_t err_code; ble_uuid_t char_uuid; ble_uuid128_t base_uuid = BLE_UUID_EE5_BASE_UUID; char_uuid.uuid = BLE_UUID_EE5_CHAR_UUID; err_code = sd_ble_uuid_vs_add(&base_uuid, &char_uuid.type); APP_ERROR_CHECK(err_code); ble_gatts_char_md_t char_md; memset(&char_md, 0, sizeof(char_md)); char_md.char_props.read = 1; //Error occurs when this part is added ble_gatts_attr_md_t cccd_md; memset(&cccd_md, 0, sizeof(cccd_md)); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); cccd_md.vloc = BLE_GATTS_VLOC_STACK; char_md.p_cccd_md = &cccd_md; char_md.char_props.notify = 1; // ----------------------------------------------- ble_gatts_attr_md_t attr_md; memset(&attr_md, 0, sizeof(attr_md)); attr_md.vloc = BLE_GATTS_VLOC_STACK; BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); ble_gatts_attr_t attr_char_value; memset(&attr_char_value, 0, sizeof(attr_char_value)); attr_char_value.p_uuid = &char_uuid; attr_char_value.p_attr_md = &attr_md; attr_char_value.max_len = 10; attr_char_value.init_len = 10; err_code = sd_ble_gatts_characteristic_add(p_service->service_handle, &char_md, &attr_char_value, &(p_service->char_handles)); APP_ERROR_CHECK(err_code); return NRF_SUCCESS; }
The arguments for sd_ble_gatts_characteristic_add:
p_attr_char_value 0x2003ff00 r2 20 const ble_gatts_attr_t* * <struct> 0x2003ff00 20 struct p_uuid 0x2003fedc 0x2003ff00 4 const ble_uuid_t* * <struct> 0x2003fedc 4 struct uuid 0xee5a 0x2003fedc 2 short unsigned int type 0x02 0x2003fede 1 unsigned char p_attr_md 0x2003fed4 0x2003ff04 3 const ble_gatts_attr_md_t* * <struct> 0x2003fed4 3 struct read_perm <struct> 0x2003fed4 1 struct sm 0x01 0x2003fed4 <0-3> 1 uint8_t lv 0x01 0x2003fed4 <4-7> 1 uint8_t write_perm <struct> 0x2003fed5 1 struct sm 0x00 0x2003fed5 <0-3> 1 uint8_t lv 0x00 0x2003fed5 <4-7> 1 uint8_t vlen 0x00 0x2003fed6 <0-0> 1 uint8_t vloc 0x01 0x2003fed6 <1-2> 1 uint8_t rd_auth 0x00 0x2003fed6 <3-3> 1 uint8_t wr_auth 0x00 0x2003fed6 <4-4> 1 uint8_t init_len 0x000a 0x2003ff08 2 short unsigned int init_offs 0x0000 0x2003ff0a 2 short unsigned int max_len 0x000a 0x2003ff0c 2 short unsigned int p_value 0x00000000 0x2003ff10 4 uint8_t* p_char_md 0x2003ff14 r1 28 const ble_gatts_char_md_t* * <struct> 0x2003ff14 28 struct char_props <struct> 0x2003ff14 1 struct broadcast 0x00 0x2003ff14 <0-0> 1 uint8_t read 0x01 0x2003ff14 <1-1> 1 uint8_t write_wo_resp 0x00 0x2003ff14 <2-2> 1 uint8_t write 0x00 0x2003ff14 <3-3> 1 uint8_t notify 0x01 0x2003ff14 <4-4> 1 uint8_t indicate 0x00 0x2003ff14 <5-5> 1 uint8_t auth_signed_wr 0x00 0x2003ff14 <6-6> 1 uint8_t char_ext_props <struct> 0x2003ff15 1 struct reliable_wr 0x00 0x2003ff15 <0-0> 1 uint8_t wr_aux 0x00 0x2003ff15 <1-1> 1 uint8_t p_char_user_desc 0x00000000 0x2003ff18 4 const uint8_t* char_user_desc_max_size 0x0000 0x2003ff1c 2 short unsigned int char_user_desc_size 0x0000 0x2003ff1e 2 short unsigned int p_char_pf 0x00000000 0x2003ff20 4 const ble_gatts_char_pf_t* p_user_desc_md 0x00000000 0x2003ff24 4 const ble_gatts_attr_md_t* p_cccd_md 0x2003fed0 0x2003ff28 3 const ble_gatts_attr_md_t* * <struct> 0x2003fed0 3 struct read_perm <struct> 0x2003fed0 1 struct sm 0x01 0x2003fed0 <0-3> 1 uint8_t lv 0x01 0x2003fed0 <4-7> 1 uint8_t write_perm <struct> 0x2003fed1 1 struct sm 0x00 0x2003fed1 <0-3> 1 uint8_t lv 0x00 0x2003fed1 <4-7> 1 uint8_t vlen 0x00 0x2003fed2 <0-0> 1 uint8_t vloc 0x01 0x2003fed2 <1-2> 1 uint8_t rd_auth 0x00 0x2003fed2 <3-3> 1 uint8_t wr_auth 0x00 0x2003fed2 <4-4> 1 uint8_t p_sccd_md 0x00000000 0x2003ff2c 4 const ble_gatts_attr_md_t* p_handles 0x200031f2 r3 8 ble_gatts_char_handles_t* * <struct> 0x200031f2 8 struct value_handle 0x0000 0x200031f2 2 short unsigned int user_desc_handle 0x0000 0x200031f4 2 short unsigned int cccd_handle 0x0000 0x200031f6 2 short unsigned int sccd_handle 0x0000 0x200031f8 2 short unsigned int service_handle 0x000e r0 2 short unsigned int
Thank you very much in advance!