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

What does the 'vloc' mean in ble_gatts_attr_md_t ?

Hi there,

I'm confused with the meaning of the 'vloc' variable in the attribute meta data. In the example code ble_bps.c  of "ble_app_bps_pca10040_s132" , in the function bps_measurement_char_add(), as below:

/**@brief Function for adding Blood Pressure Measurement characteristics.
 *
 * @param[in]   p_bps        Blood Pressure Service structure.
 * @param[in]   p_bps_init   Information needed to initialize the service.
 *
 * @return      NRF_SUCCESS on success, otherwise an error code.
 */
static uint32_t bps_measurement_char_add(ble_bps_t * p_bps, ble_bps_init_t const * p_bps_init)
{
    ble_gatts_char_md_t char_md;
    ble_gatts_attr_md_t cccd_md;
    ble_gatts_attr_t    attr_char_value;
    ble_uuid_t          ble_uuid;
    ble_gatts_attr_md_t attr_md;
    ble_bps_meas_t      initial_bpm;
    uint8_t             encoded_bpm[MAX_BPM_LEN];

    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;
    cccd_md.write_perm = p_bps_init->bps_meas_attr_md.cccd_write_perm;

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

    char_md.char_props.indicate = 1;
    char_md.p_char_user_desc    = NULL;
    char_md.p_char_pf           = NULL;
    char_md.p_user_desc_md      = NULL;
    char_md.p_cccd_md           = &cccd_md;
    char_md.p_sccd_md           = NULL;

    BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_BLOOD_PRESSURE_MEASUREMENT_CHAR);

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

    attr_md.vloc       = BLE_GATTS_VLOC_STACK;
    attr_md.read_perm  = p_bps_init->bps_meas_attr_md.read_perm;
    attr_md.write_perm = p_bps_init->bps_meas_attr_md.write_perm;
    attr_md.rd_auth    = 0;
    attr_md.wr_auth    = 0;
    attr_md.vlen       = 1;

    memset(&attr_char_value, 0, sizeof(attr_char_value));
    memset(&initial_bpm, 0, sizeof(initial_bpm));

    attr_char_value.p_uuid    = &ble_uuid;
    attr_char_value.p_attr_md = &attr_md;
    attr_char_value.init_len  = bps_measurement_encode(p_bps, &initial_bpm, encoded_bpm);
    attr_char_value.init_offs = 0;
    attr_char_value.max_len   = MAX_BPM_LEN;
    attr_char_value.p_value   = encoded_bpm;

    return sd_ble_gatts_characteristic_add(p_bps->service_handle,
                                           &char_md,
                                           &attr_char_value,
                                           &p_bps->meas_handles);
}

in the comments of its definition it says 'vloc' is "Value location", in this code, the attribute value is apparently in the user memory  ( encoded_bpm[] ), then why the 'vloc' is set to BLE_GATTS_VLOC_STACK ?

Thank you for any comments.

Parents
  • Hi JJ,

            the GATT characteristic table can be stored in two places: on the stack as above or in user memory. I think vloc is short for value location. The stack location is the softdevice stack I believe. Your stuff gets copied in. Stack is better but you can easily run out of space. Vlen is completely different in specifying whether there are any variable length characteristics.

    Cheers Paul

  • As  says, the vloc is short for value location, and BLE_GATTS_VLOC_STACK means that it is stored in the Bluetooth stack.  

    the attribute value is apparently in the user memory  ( encoded_bpm[] ), then why the 'vloc' is set to BLE_GATTS_VLOC_STACK ?

     The value is fetched from the user memory, but it is stored in the SoftDevice (bluetooth stack). So the encoded_bpm is only used to initialize the value. Similarly, the value can be updated by passing a pointer with a new value to the softdevice (the softdevice call depends on whether you use notifications or not. 

    I can recommend this tutorial if you want an introduction to BLE characteristics. There are some other tutorials on BLE here as well.

  • Thank you Paul and Edvin, that explained clearly. Now I have a further question about this, is there a guideline about when to use the stack memory and when to use the user memory? I guess if the value length is large then we should use the user memory? I found the BLE_GATTS_FIX_ATTR_LEN_MAX is defined 510 and BLE_GATTS_FIX_ATTR_LEN_MAX is 512, does it mean if the value length is less than this value then we can use the stack memory, if I need more than that then I should use the user memory? Thank you.

  • Hello,

    I wouldn't recommend to use the USER region unless you have a very specific reason to do so. The BLE_GATTS_VLOC_STACK is easier to use, as the softdevice handles all the updates and memory update for you. I haven't really looked into what you would need to do to use the USER, but it seems like a bit more work handling the lengths and so on. You can check my colleague, run_ar's, answer here:

    https://devzone.nordicsemi.com/f/nordic-q-a/30040/ble_gatts_vloc_user-and-volatile-variable

     

    jj8431 said:
    I found the BLE_GATTS_FIX_ATTR_LEN_MAX is defined 510 and BLE_GATTS_FIX_ATTR_LEN_MAX is 512, does it mean if the value length is less than this value then we can use the stack memory, if I need more than that then I should use the user memory?

     That is not really the use case. The maximum length of a characteristic is not dependent on whether it is in the user memory or in the stack. The use case for the user memory area is if you are really restricted on memory, and you can manage the characteristics manually, knowing that you will never exceed the total limit. This is typically not the use case. 

    My tip to you is to use the BLE_GATTS_VLOCK_STACK, and use the get and set functions to manage them.

    Best regards,

    Edvin

  • Thanks Edvin, I didn't have particular reason to think about using user memory, just a bit worried about the memory size as the softdevice memory size was defined in the linker file, if I add one or many large attribute value size later in application code then if it will run out of memory. Anyway that's not a situation I'm facing right now, so I'll just use the stack memory as you suggested. Thanks a lot.

    Regards,

    Jian

Reply
  • Thanks Edvin, I didn't have particular reason to think about using user memory, just a bit worried about the memory size as the softdevice memory size was defined in the linker file, if I add one or many large attribute value size later in application code then if it will run out of memory. Anyway that's not a situation I'm facing right now, so I'll just use the stack memory as you suggested. Thanks a lot.

    Regards,

    Jian

Children
No Data
Related