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

Unexplained large increase in RAM requirement when increasing existing characteristic length

I am wanting to increase the length of one of my characteristics used when my device is acting as a peripheral. When I increase the size of my characteristic, the softdevice requires a large amount of extra RAM (more RAM than I can spare) but if I remove one 2 byte field from this characteristic then the softdevice requires no extra RAM. Why is this?

Key points about my device:

  •  s332 v5.0
  • NRF52832 
  • SDK v14.2.
  • 8 central connections
  • 5 peripheral connections
  • The characteristic in question supports notifications and reads
  • hvn_tx_queue_size is set to 30

My original structure is

typedef struct
{
    uint8_t gps_state;          /**< GPS State */
    uint8_t num_satellites;     /**< Number of GNSS satellites */
    uint16_t gps_accuracy;      /**< Accuracy in (m)*/
} ble_gps_t;

My original scatter file is

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************

LR_IROM1 0x0002D000 0x00046000  {    ; load region size_region
  ER_IROM1 0x0002D000 0x00046000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }
  RW_IRAM1 0x20009340 UNINIT 0x00000100  {  ; RW data
   *(.noinit)
  }
  RW_IRAM2 0x20009440 0x00006BC0  {  ; RW data
   .ANY (+RW +ZI)
  }
}

If I change my characteristic to

typedef struct
{
    uint8_t gps_valid;          /**< GPS valid */
    uint8_t num_satellites;     /**< Number of GNSS satellites */
    uint16_t gps_accuracy;      /**< Accuracy in (m)*/
    int32_t latitude;
    int32_t longitude;
    int32_t speed;
    uint8_t fix_ok : 1;
    uint8_t heading_valid : 1;
    uint8_t differential_soln : 1;
    uint8_t carrier_soln : 2;
    uint8_t _unused : 3;
    uint32_t horizontal_accuracy;
    uint16_t pdop;
} __attribute__((packed)) ble_gps_t;

Then increasing the softdevice RAM allocation by 448 bytes (which is about as much as I can spare) still isn't enough for all my services to be initialised, I get NRF_ERROR_NO_MEM when calling sd_ble_gatts_characteristic_add.

But, if I remove the pdop field, so my characteristic is now

typedef struct
{
    uint8_t gps_valid;          /**< GPS valid */
    uint8_t num_satellites;     /**< Number of GNSS satellites */
    uint16_t gps_accuracy;      /**< Accuracy in (m)*/
    int32_t latitude;
    int32_t longitude;
    int32_t speed;
    uint8_t fix_ok : 1;
    uint8_t heading_valid : 1;
    uint8_t differential_soln : 1;
    uint8_t carrier_soln : 2;
    uint8_t _unused : 3;
    uint32_t horizontal_accuracy;
} __attribute__((packed)) ble_gps_t;

Then I don't need to change my scatter file at all.

Why do those extra 2 bytes mean the softdevice requires so much more RAM?

  • Hi,

    The function sd_ble_enable()/ nrf_sdh_ble_enable() will tell you how much RAM is required to enable the SoftDevice with the current SD configuration. If you enable the SD, starts to add characteristic/services, and then get the error-code “NRF_ERROR_NO_MEM “, then the SD configuration need to be changed. I suspect that you might need to increase the Attribute Table size. (NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE in sdk_config.h).

Related