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

sd_ble_gatts_value_set causes a segmentation violation (SIGSEGV)

I'm trying to create a simple service that would just provide some data which could get updated internally (for example, via SPI bus). Data may be of a different size, so I'm trying to notify the device about the change in data buffer by calling sd_ble_gatts_value_set. However, I get a SIGSEGV when I call that function. Here's how I set up a service:

ble_uuid_t ble_uuid;

ble_gatts_char_md_t char_md;
ble_gatts_attr_md_t attr_md;
ble_gatts_attr_t attr_char_value;
...
char_md.char_props.read = 1;
char_md.char_props.write = 0;
char_md.char_props.notify = 0;

BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.write_perm);
attr_md.vloc = BLE_GATTS_VLOC_STACK;
attr_md.rd_auth = 0;
attr_md.wr_auth = 0;
attr_md.vlen = 1;

attr_char_value.p_uuid = &ble_uuid;
attr_char_value.p_attr_md = &attr_md;
attr_char_value.init_len = 1;
attr_char_value.init_offs = 0;
attr_char_value.max_len = 256;
attr_char_value.p_value = data; // data is a pointer to the buffer

err_code = sd_ble_gatts_characteristic_add(
p_service->service_handle,
&char_md, &attr_char_value,
&p_service->char_handle
);

VERIFY_SUCCESS(err_code);

I tried setting attr_md.vloc to either BLE_GATTS_VLOC_STACK or BLE_GATTS_VLOC_USER, depending on whether I was allocating arrays on stack or on heap - I have tried both, with both using malloc and nrf_malloc.
Then I change a data in the buffer and I would like to update the length of the data:

ble_gatts_value_t value_md = {
.len = length, // length is passed to the function
.offset = 0,
.p_value = NULL
};
err_code = sd_ble_gatts_value_set(
BLE_CONN_HANDLE_INVALID,
p_service->char_handles.value_handle,
&value_md
);
VERIFY_SUCCESS(err_code);

return NRF_SUCCESS

I suspect I have some issues with allocating my buffers, or I don't understand something about what data exactly is in the Characteristic, because when I try to just change the first byte of the data array in the code after I have created the service and characteristics, I don't see an update in the nRF Connect app, but if I set it beforehand, I can see it.

Please tell me if I can provide any other code snippets or sdk configuration information if that would help you help me solve this problem. My SDK version is 7.0.1.

Thanks in advance for all suggestions.

  • Hello,

    What does

    sd_ble_gatts_characteristic_add() and sd_ble_gatts_value_set() return?

    Until you get this up and running, I suggest you stick to BLE_GATTS_VLOC_STACK.

    Have you checked any of the examples in the SDK how they set up and use the softdevice to send notifications? Check out the ble_app_uart example.

    What does the SIGSEGV look like?

    BR,

    Edvin

  • Hello,

    sd_ble_gatts_characteristic_add() returns NRF_SUCCESS, as (hopefully) confirmed by VERIFY_SUCCESS macro.

    sd_ble_gatts_value_set() does not return any value - SIGSEGV occurs during the call to it. I can't get much information from backtrack (stuck is corrupted), but looking at the addresses I could make a guess that those belong to the softdevice code:

    238 ble_gatts_value_t value_md = {
    (gdb) n
    243 err_code = sd_ble_gatts_value_set(
    (gdb) n
    
    Program received signal SIGSEGV, Segmentation fault.
    0x0001521a in ?? ()
    (gdb) bt
    #0 0x0001521a in ?? ()
    #1 0x000151ea in ?? ()
    Backtrace stopped: previous frame identical to this frame (corrupt stack?)


    Here is buffer allocation on the stack:

    (gdb) p &buffer
    $2 = (uint8_t (*)[256]) 0x2000fef4

    And when I look at corrupted stack, I get this:

    (gdb) info frame
    Stack level 0, frame at 0x2000fd78:
    pc = 0x1521a; saved pc = 0x151ea
    called by frame at 0x2000fd78
    Arglist at 0x2000fd78, args:
    Locals at 0x2000fd78, Previous frame's sp is 0x2000fd78


    I also made sure to increase the stack size in my Makefile;

    nrf52832_xxaa: CFLAGS += -D__HEAP_SIZE=16384
    nrf52832_xxaa: CFLAGS += -D__STACK_SIZE=16384
    nrf52832_xxaa: ASMFLAGS += -D__HEAP_SIZE=16384
    nrf52832_xxaa: ASMFLAGS += -D__STACK_SIZE=16384


    I will look into some examples, but for now I hope this would help you make a guess about the issue.
    Thanks.

     

  • SergeyK said:
    as (hopefully) confirmed by VERIFY_SUCCESS macro.

     Yes, that is what the VERIFY_SUCCESS does, but if you are not aware of it, then you may just see the lack of advertisements, and assume that something is wrong (hard fault).

    The softdevice calls should normally not assert or hardfault unless you pass some invalid pointers to them. 

    What did you add at the point that you started to encounter these SIGSEGVs?

    What is the "data" variable in your initialization:

    attr_char_value.p_value = data; // data is a pointer to the buffer

    Is it possible for me to reproduce this issue? Does it run on a DK?

  • you may just see the lack of advertisements

    No, I see advertisements alright. I had configured multiple services, some with multiple characteristics, and I can see them.

    What did you add at the point that you started to encounter these SIGSEGVs?

    After I tried to have one characteristic show data from the buffer. Right after I had all services set up.

    What is the "data" variable in your initialization:

    It's the statically allocated array I created.

    I tried to reduce my code to the minimal example at which I experience the issue. You can find the code here:

    https://github.com/SuperPrower/nrf_issue_minimal_example

    Please take a look.

  • Are you really using SDK7? Please try to update the SDK version. There is probably a lot of SDK and softdevice bugfixes between SDK7 and SDK16.

    This should be a trivial fix. You can see how it is done in basically all the peripheral examples in the SDK. Please compare your implementation with those. If you struggle with this after trying a later SDK version, then let me know.

    BR,

    Edvin

Related