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

Confused about persisting characteristic values written by a central

I have an nRF51822-based device, which is a peripheral running the Soft Device s110. It has some vendor specific (custom) characteristics that are read/write. A mobile app (central) reads and writes them.

I'm confused about how I should be persisting the values for these characteristics. They need to be persisted across a reset or system off.

Firstly, is it my responsibility to persist the value or do I get that for free somehow? Having a look at the source for the Immediate Alert Service implementation in the SDK, there's no persistence going on, so it seems like the responsibility of the application.

If I must persist the values myself, it seems I have these options:

  1. Keep the value in RAM and use RAM retention. There's an example app for this: ram_retention_example.

  2. Keep the value in flash and use the pstorage module.

  3. The new Device Manager has an application context which looks like it might be a suitable place to write the values. I can see no examples that use it, however. If I write some data to it, does the Device Manager use pstorage to write this to flash for me?

If #3 is not suitable, what are the power consumption considerations for choosing between #1 and #2? Does my flash "wear out" over thousands of read/write operations?

  • Hi Eliot,

    You are responsible for persisting the values written to the characteristics over resets and system off modes. If you do not need to have them survive power reset then RAM retention is a viable option. If they do need to survive power reset then I would be using NVRAM and pstorage. I'm not familiar with the Device Manager so I can't help with addressing it's usage.

    There are power considerations for RAM vs. NVRAM. According to the nRF51822 product specification NVRAM erase/write operations typically take 21-22 mS so you will be burning more power than a RAM write. I suspect NVRAM erase/write operations also consume additional current but I didn't see any mention of it in the product spec. The product specification also indicates that the endurance of the flash is 20,000 write/erase cycles.

    Regards, John

  • Hi Eliot,

    The application context in Device Manager has been added to address use cases you mention above. Hence 3, is suitable. However, note that you will be to use application context store and load functionality only for a bonded device.

    You are right, there is no SDK example that shows how to use the application context.

    Below are some code snippets that may be of useful to you.

    typedef struct
    {
        uint32_t value;
    }my_char_t;
    
    static dm_handle_t m_bonded_dev_handle;
    static my_char_t   m_my_char;
    
    
    // Code for storing.
    static void on_ble_evt(ble_evt_t * p_evt)
    {
       api_result_t               retval;
       dm_application_context_t   app_context;
       
       switch (p_evt->header.evt_id)
       {
            .
    	    .
    	    case BLE_GAP_EVT_DISCONNECTED:
    	    {
    		    app_context.len    = sizeof(my_char_t);
    			app_context.p_data = ((uint8_t *)&m_my_char); 
    			
    	        // Want to store the last updated value of the characteristic persistently.
    		    retval = dm_application_context_set(&m_bonded_dev_handle,
    		                                       &app_context);
                if (retval == NRF_SUCCESS)
    			{
    			    // Wait for DM_EVT_APPL_CONTEXT_STORED event.
    				// Note do not reuse or change m_my_char.
    			}
    			else
    			{
    			    // Failed to store application context.
    			}
    	        break;
           }
    	   .
    	   .
       }
    }
    
    
    // Code for loading.
    static uint32_t device_manager_evt_handler(dm_handle_t const    * p_handle,
                                               dm_event_t const     * p_event,
                                               api_result_t           event_result)
    {
        APP_ERROR_CHECK(event_result);
    	
    	
        api_result_t               retval;
        dm_application_context_t   app_context;
    	
    	switch(p_event->event_id)
    	{
    	    .
    		.
    		case DM_EVT_DEVICE_CONTEXT_LOADED:
    		{		
    		    // This event is generated as soon as a bonded device reconnects and its bond and 
    			// service information have been loaded. This may be most appropriate to load application
    			// context. 			
    			app_context.len    = sizeof(my_char_t);
    			app_context.p_data = ((uint8_t *)&m_my_char);
    			
    			retval = dm_application_context_get(p_handle,&app_context);
    			if (retval == NRF_SUCCESS)
    			{
                    // DM_EVT_APPL_CONTEXT_LOADED event generated to indicate load complete.
    				// Note do not reuse or change m_my_char.
    			}
    		    break;
    		}
    		case DM_EVT_APPL_CONTEXT_LOADED:		
    		{
    		    // Set char value using sd_ble_gatts_value_set
    		    break;
    		}
    		.
    		.
    	}
        return NRF_SUCCESS;
    }
    

    Please ensure that DEVICE_MANAGER_APP_CONTEXT_SIZE is set to a value suitable for storing your application context size. By default DEVICE_MANAGER_APP_CONTEXT_SIZE is set to 0 in examples to disable these APIs for applications that do not need it. Also, note that I mention suitable here and not maximum because the DEVICE_MANAGER_APP_CONTEXT_SIZE is expected to be a multiple of 4. Therefore in case your application context size if 30, you will need to set this to 32.

    Hope this helps!

    Regards, Krishna

  • OK this compiles but won't link. It's the first time I've used pstorage. I'm overflowing the FLASH region. How to I make room for what I'm writing?

    /Users/Eliot/dev/gcc-arm-none-eabi-4_8-2013q4/bin/../lib/gcc/arm-none-eabi/4.8.3/../../../../arm-none-eabi/bin/ld: _build/device-nordic_s110.elf section .text' will not fit in regionFLASH' /Users/Eliot/dev/gcc-arm-none-eabi-4_8-2013q4/bin/../lib/gcc/arm-none-eabi/4.8.3/../../../../arm-none-eabi/bin/ld: region `FLASH' overflowed by 2388 bytes collect2: error: ld returned 1 exit status

  • Hi Eliot,

    It appears to me that the application image exceeds the flash size. Is it possible for you to disable device manager logs? That will give some saving. I am not able to give specific recommendations on how to reduce the image size without knowing your requirements, if you can use optimization or not etc.

    I should also mention that enabling application context in device manager results in an increase of ~700 bytes without any optimization and not more. Hence it will be worth investigating 2388 bytes increase in image keeping the one used earlier as reference.

    Regards, Krishna

Related