<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>pc-ble-driver sd_ble_uuid_vs_add() returns NRF_ERROR_NO_MEM</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/79637/pc-ble-driver-sd_ble_uuid_vs_add-returns-nrf_error_no_mem</link><description>I am using PC code derived from pc-ble-driver heart rate collector with a nRF52840 dev board 
 On adding characteristics sd_ble_uuid_vs_add() I get an error of 4 - NRF_ERROR_NO_MEM. This is on the 9th characteristic to add. I am using: 
 
 pc-ble-driver</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Thu, 16 Sep 2021 06:11:36 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/79637/pc-ble-driver-sd_ble_uuid_vs_add-returns-nrf_error_no_mem" /><item><title>RE: pc-ble-driver sd_ble_uuid_vs_add() returns NRF_ERROR_NO_MEM</title><link>https://devzone.nordicsemi.com/thread/329710?ContentTypeID=1</link><pubDate>Thu, 16 Sep 2021 06:11:36 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:7787cc0a-1604-44c4-8af1-810861346f9b</guid><dc:creator>Vidar Berg</dc:creator><description>&lt;p&gt;We actually recommend trial and error to find the appropriate table size. That is, start with the default ATT table size and increase it until you no longer get the NO_MEM error. There are too many factors that determine the size of a service/characteristics to make it an easy calculation.&lt;/p&gt;
[quote user="Dave New"]At the moment I am adding 13 vendor specific characteristic UUIDs and 3 services[/quote]
&lt;p&gt;Is it a requirement to have a different base UUIDs for each characteristic? Services and characteristics that belong together will typically share the same vendor specific base UUID. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: pc-ble-driver sd_ble_uuid_vs_add() returns NRF_ERROR_NO_MEM</title><link>https://devzone.nordicsemi.com/thread/329588?ContentTypeID=1</link><pubDate>Wed, 15 Sep 2021 11:28:20 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:2e8424a6-c9e7-49d1-8f42-2650d685e221</guid><dc:creator>Dave New</dc:creator><description>&lt;p&gt;Thanks, that seems to work. Is there a&amp;nbsp;recommended table size for a given UUID count? At the moment I am adding 13 vendor specific characteristic UUIDs and 3 services&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: pc-ble-driver sd_ble_uuid_vs_add() returns NRF_ERROR_NO_MEM</title><link>https://devzone.nordicsemi.com/thread/329555?ContentTypeID=1</link><pubDate>Wed, 15 Sep 2021 09:01:42 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:fb4a30e6-09b5-476a-bc65-49549859cbbe</guid><dc:creator>Vidar Berg</dc:creator><description>&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;The attribute table size and the size of the vendor specific UUID buffer has to be configured on the application side through the ble_cfg_set() function.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;/**@brief Function for setting configuration for the BLE stack.
 *
 * @return NRF_SUCCESS on success, otherwise an error code.
 */
static uint32_t ble_cfg_set(uint8_t conn_cfg_tag)
{
    const uint32_t ram_start = 0; // Value is not used by ble-driver
    uint32_t error_code;
    ble_cfg_t ble_cfg;

    // Configure the connection roles.
    memset(&amp;amp;ble_cfg, 0, sizeof(ble_cfg));

#if NRF_SD_BLE_API &amp;gt;= 6
    ble_cfg.gap_cfg.role_count_cfg.adv_set_count = BLE_GAP_ADV_SET_COUNT_DEFAULT;
#endif
    ble_cfg.gap_cfg.role_count_cfg.periph_role_count  = 0;
    ble_cfg.gap_cfg.role_count_cfg.central_role_count = 1;
    ble_cfg.gap_cfg.role_count_cfg.central_sec_count  = 0;

    error_code = sd_ble_cfg_set(m_adapter, BLE_GAP_CFG_ROLE_COUNT, &amp;amp;ble_cfg, ram_start);
    if (error_code != NRF_SUCCESS)
    {
        printf(&amp;quot;sd_ble_cfg_set() failed when attempting to set BLE_GAP_CFG_ROLE_COUNT. Error code: &amp;quot;
               &amp;quot;0x%02X\n&amp;quot;,
               error_code);
        fflush(stdout);
        return error_code;
    }

    memset(&amp;amp;ble_cfg, 0x00, sizeof(ble_cfg));
    ble_cfg.conn_cfg.conn_cfg_tag                 = conn_cfg_tag;
    ble_cfg.conn_cfg.params.gatt_conn_cfg.att_mtu = NRF_SDH_BLE_GATT_MAX_MTU_SIZE;

    error_code = sd_ble_cfg_set(m_adapter, BLE_CONN_CFG_GATT, &amp;amp;ble_cfg, ram_start);
    if (error_code != NRF_SUCCESS)
    {
        printf(&amp;quot;sd_ble_cfg_set() failed when attempting to set BLE_CONN_CFG_GATT. Error code: &amp;quot;
               &amp;quot;0x%02X\n&amp;quot;,
               error_code);
        fflush(stdout);
        return error_code;
    }

    memset(&amp;amp;ble_cfg, 0x00, sizeof(ble_cfg));
    ble_cfg.common_cfg.vs_uuid_cfg.vs_uuid_count = 10;

     error_code = sd_ble_cfg_set(m_adapter, BLE_COMMON_CFG_VS_UUID, &amp;amp;ble_cfg, ram_start);
    if (error_code != NRF_SUCCESS)
    {
        printf(&amp;quot;sd_ble_cfg_set() failed when attempting to set BLE_COMMON_CFG_VS_UUID. Error code: &amp;quot;
               &amp;quot;0x%02X\n&amp;quot;,
               error_code);
        fflush(stdout);
        return error_code;
    }   

    memset(&amp;amp;ble_cfg, 0x00, sizeof(ble_cfg));
    ble_cfg.gatts_cfg.attr_tab_size.attr_tab_size = 2816;
     error_code = sd_ble_cfg_set(m_adapter, BLE_GATTS_CFG_ATTR_TAB_SIZE, &amp;amp;ble_cfg, ram_start);
    if (error_code != NRF_SUCCESS)
    {
        printf(&amp;quot;sd_ble_cfg_set() failed when attempting to set BLE_GATTS_CFG_ATTR_TAB_SIZE. Error code: &amp;quot;
               &amp;quot;0x%02X\n&amp;quot;,
               error_code);
        fflush(stdout);
        return error_code;
    } 
    
    ...&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Please try this and see if it helps.&lt;/p&gt;
[quote user=""]Doubled the stack size and heap size in the Keil options to&amp;nbsp;&amp;nbsp;__HEAP_SIZE=1024 __STACK_SIZE=4096[/quote]
&lt;p&gt;&amp;nbsp;You can leave this configuration as is. The connectivity FW does not use heap memory and the call stack is placed at the end of RAM anyway.&lt;/p&gt;
&lt;p&gt;Best regards,&lt;/p&gt;
&lt;p&gt;Vidar&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Correction: &lt;/strong&gt;Call stack is not placed at the end of RAM if you build with Keil but instead placed right above the globals. I.e. a stack overrun is guaranteed to overwrite global variables unlike FW built with GCC and therefore lead to undefined behavior. But 4096 bytes should be sufficient.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>