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

Running out of memory for service tables - but it is so small!

I am getting a 


<debug> app: char val length 22
<debug> app: Failed to initialize characteristics. Error code: 0x04
<debug> app: Unable to create RegCertDataList characteristic. Error code 0x4

while creating my service tables. But it is so small. How could this be?

The service table contains

  • one service with two characteristics,
  • A second service with one characteristic
  • the DeviceInformationService with all the characteristics
  • the battery service with one characteristic

The code itself is not large - 40096 bytes according to Keil, half of which is due to NRF_LOG.

It appears the size of the characteristic value may be part of the issue.

That being said, there is one service I am creating with two characteristics that are never read and do not support being read. When written, the application catches the written value and performs tasks based upon that. The written value has no meaning and does not need to be stored. I set a 0 value for the characteristic value size and that did not work. Will I be forced to make the size of the value the size of the data written even though that written data serves no purpose in the service tables?

Parents
  • Correct me if I am wrong, I think it's probably the attribute table size which is causing this problem.

    When adding characteristics/attributes you are able to specify if the value should be located in the stack memory or managed by the user. See struct "ble_gatts_attr_md_t" "vloc" and defines BLE_GATTS_VLOC_STACK or BLE_GATTS_VLOC_USER.

    When it is located on the stack it will have a maximum size specified in the sdk_config under "NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE"

    You can increase the attribute table size, or manage the memory your self.

  • I am not sure what it means to manage the memory by myself. I have a couple of very different situations.

    First I have a service with two characteristics. One characteristic is only notified and never read. The other characteristic is written to and indicated. When I do notifications or indications on these characteristics the buffer I am sending remains in scope. In fact, the buffer is often quite long and I have to do the notifications in fragments. How would I 'manage' the memory in that case?

    IN another case I have the good old Device Information Service. I know the size of each entry. But when creating the characteristic there a several 'size' fields which I find confusing as to their purpose. I commented out the battery service so I didn't run out of memory. Then I ran the application where I used the option to trap the read in the BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST event and set the value there. If I did that, the program hung after about the fifth read. If I did not 'trap' the read, the program did not hang and the DIS was successfully read. I do not understand that. I need that option to set battery values and current time values when requested by the client. I don't need it for the DIS but it should work anyways.

    How does the max_size parameter of the ble_gatts_attr_t affect the memory requirements?

  • Hi,

    brianreinhold said:
    I am not sure what it means to manage the memory by myself. I have a couple of very different situations.

    The difference is if the memory is within the RAM that is reserved for the SoftDevice (which depends on the configuration used to initialize it), or if it should be in the application RAM. In that case the application has to provide the memory to the SoftDevice. In most cases it makes sense to use BLE_GATTS_VLOC_STACK and increase NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE, as suggested by .

    brianreinhold said:
    In fact, the buffer is often quite long and I have to do the notifications in fragments. How would I 'manage' the memory in that case?

    The memory should be scaled for the whole characteristic. Then you call sd_ble_gatts_hvx() several times with an increasing offset value to send the whole characteristic in pieces.

    brianreinhold said:
    If I did that, the program hung after about the fifth read.

    I am not sure what happened here. What did you find by debugging? If "the program hangs" there should be an error somewhere you can find by debugging.

    brianreinhold said:
    How does the max_size parameter of the ble_gatts_attr_t affect the memory requirements?

    The memory usage is defined by the max_len. (It could for instance be that the default value of a characteristic is less then the maximum, and if so, reserving memory for the default value would not be enough.)

Reply
  • Hi,

    brianreinhold said:
    I am not sure what it means to manage the memory by myself. I have a couple of very different situations.

    The difference is if the memory is within the RAM that is reserved for the SoftDevice (which depends on the configuration used to initialize it), or if it should be in the application RAM. In that case the application has to provide the memory to the SoftDevice. In most cases it makes sense to use BLE_GATTS_VLOC_STACK and increase NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE, as suggested by .

    brianreinhold said:
    In fact, the buffer is often quite long and I have to do the notifications in fragments. How would I 'manage' the memory in that case?

    The memory should be scaled for the whole characteristic. Then you call sd_ble_gatts_hvx() several times with an increasing offset value to send the whole characteristic in pieces.

    brianreinhold said:
    If I did that, the program hung after about the fifth read.

    I am not sure what happened here. What did you find by debugging? If "the program hangs" there should be an error somewhere you can find by debugging.

    brianreinhold said:
    How does the max_size parameter of the ble_gatts_attr_t affect the memory requirements?

    The memory usage is defined by the max_len. (It could for instance be that the default value of a characteristic is less then the maximum, and if so, reserving memory for the default value would not be enough.)

Children
  • To be honest everything was going hunky-dory with my 2-characteristic device. The max size of each of the characteristics is

    (NRF_SDH_BLE_GAP_DATA_LENGTH - 4 - OPCODE_LENGTH - HANDLE_LENGTH)

    Forgot why the -4 is in there. That is actually overkill for one of the characteristics. However the other one I do a sequence of notifications that is far longer than the maximum and I have been doing exactly as you say in that case below in blue. (I don't know how to make fancy quotes.)

    The memory should be scaled for the whole characteristic. Then you call sd_ble_gatts_hvx() several times with an increasing offset value to send the whole characteristic in pieces."

    Now that data array I am sending stays in scope. So just for fun I changed ONE parameter - BLE_GATTS_VLOC_STACK to BLE_GATTS_VLOC_USER. The application crashed. I was hoping that the notification code would just take that hunk of my data array and send it. But that is clearly not what happened. So I don't know what happened. I also not that the ->vloc parameter is on the md stuff (descriptor-related) but I don't know why.

    I have managed to solve my memory problems by taking the static DIS and fixing the max size to a much smaller value. I wanted to set it to the size of the data value but that crashed. I had to do this

    (valueLength + OPCODE_LENGTH + HANDLE_LENGTH)

    where valuelength is the length of the actual data. This was not at all clear from the documentation.

Related