This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

nonvolatile memory access

I need to have configuration tables(more than one) on my BLE device. As far as I know nRF51822 doesn't have built-in eeprom so my options are limited to external serial one or flash. I do prefer flash. I'll be updating one table at a time. Now are my questions:

How can tell to a compiler(Keil in my case)/linker to reserve space in flash for those tables(will be updated wirelessly from the client device)?

Should the room for each table be a multiple of flash page size?

What is the exact sequence of actions, that needs to be taken? Any existing examples?

PS: found pstorage.c - is that the only code to look at?

  • To reserve space in flash I would simply decrease the size of IROM1 in Options for Target.

    Should the room for each table be a multiple of flash page size?

    If you want to use pstorage, the maximum block size is equal to the flash page size. If you use the maximum block size, each table should be less than the block size, or be divided in such a way that each part is less than the block size.

    If you have enough flash available, it is best to have each table on a separate page, then you can just clear the page and write the complete table to it, instead of updating it. Update is much more time consuming.

    What is the exact sequence of actions, that needs to be taken? Any existing examples?

    First you must ensure that pstorage has the sufficient number of flash pages available. This is set in pstorage_platform.h.

    Increase PSTORAGE_MAX_APPLICATIONS to 2, your application and the device manager.

    If your application requires more than 1 flash page, subract the the number of additional pages from PSTORAGE_FLASH_PAGE_END in PSTORAGE_DATA_START_ADDR define. Unmodified it reserves 1 flash page per application and one swap page.

    Some variables:

    static pstorage_handle_t        m_store_variables_base_handle;
    static pstorage_handle_t        m_store_variables_curr_handle;
    static int block_number = 0;
    static uint8_t block0[4]  __attribute__((aligned(4)));
    

    You must register your application in the pstorage module. It is recommended that the block size is a multiple of the flash word size (4B) and that the block size is a divisor of the flash page size (1024B), that flash page size % block size = 0. This doesn't matter if you use less than 1 page of flash. It should look something like this:

    static void store_variables_init(void)
    {
        uint32_t err_code;
        
        pstorage_module_param_t param;
    
        param.block_size  = 20;
        param.block_count = 7;
        param.cb          = store_variables_cb_handler;
    
        err_code = pstorage_register(&param, &m_store_variables_base_handle);
        APP_ERROR_CHECK(err_code);
    }
    

    You must define the pstorage event handler for your application:

    static void store_variables_cb_handler(
                                    pstorage_handle_t  * handle,
                                    uint8_t              op_code,
                                    uint32_t             result,
                                    uint8_t            * p_data,
                                    uint32_t             data_len)
    {
        switch(op_code)
        {
            case PSTORAGE_STORE_OP_CODE:
               if (result == NRF_SUCCESS)
               {
                  rdy_for_next = true; // Ready for next store operation
               }
               else
               {
                   // Store operation failed. This must be handled
               }
               break;       
        }
    }
    

    rdy_for_next is a flag that is checked in the main loop:

    // Enter main loop.
    for (;;)
    {
        if(rdy_for_next)
        {
            store_next_block();
        }
        err_code = sd_app_evt_wait();
        APP_ERROR_CHECK(err_code);
    }
    

    The store_next_block() can look like this:

    static void store_next_block(void)
    {
        rdy_for_next = false;
        uint32_t err_code;
    
        err_code = pstorage_block_identifier_get(&m_store_variables_base_handle, block_number, &m_store_variables_curr_handle);
        APP_ERROR_CHECK(err_code);
        err_code = pstorage_store(&m_store_variables_curr_handle, block0, 4,0);
        APP_ERROR_CHECK(err_code);
        block_number++;            
    }
    

    This should get you started, please add a comment if anything is unclear or if anything requires a better explanation.

  • Thank you for fast reply.

    Will try to find some time this week. The only question I have for now is that I was thinking that I'll need to use sd_flash_erase (write, protect) functions but you didn't mentioned them.

  • You can use the sd_flash_ functions directly, or you can let pstorage handle them.

Related