BLE+FDS Problem to read/write flash data err

sdk:17.1
example: ble_app_uart+ secure_bootloader.
Our device is charged with power-off reset function.

When I call fds_record_update(&desc, &gtPara_record),if returns FDS_ERR_NO_SPACE_IN_FLASH, which means I need to call to clean up the garbage.So i need to call err_code = fds_gc();Right?

// <e> FDS_ENABLED - fds - Flash data storage module
//==========================================================
#ifndef FDS_ENABLED
#define FDS_ENABLED 1
#endif
// <h> Pages - Virtual page settings

// <i> Configure the number of virtual pages to use and their size.
//==========================================================
// <o> FDS_VIRTUAL_PAGES - Number of virtual flash pages to use. 
// <i> One of the virtual pages is reserved by the system for garbage collection.
// <i> Therefore, the minimum is two virtual pages: one page to store data and one page to be used by the system for garbage collection.
// <i> The total amount of flash memory that is used by FDS amounts to @ref FDS_VIRTUAL_PAGES * @ref FDS_VIRTUAL_PAGE_SIZE * 4 bytes.

#ifndef FDS_VIRTUAL_PAGES
#define FDS_VIRTUAL_PAGES 2
#endif

// <o> FDS_VIRTUAL_PAGE_SIZE  - The size of a virtual flash page.
 

// <i> Expressed in number of 4-byte words.
// <i> By default, a virtual page is the same size as a physical page.
// <i> The size of a virtual page must be a multiple of the size of a physical page.
// <1024=> 1024 
// <2048=> 2048 

#ifndef FDS_VIRTUAL_PAGE_SIZE
#define FDS_VIRTUAL_PAGE_SIZE 1024
#endif

// <o> FDS_VIRTUAL_PAGES_RESERVED - The number of virtual flash pages that are used by other modules. 
// <i> FDS module stores its data in the last pages of the flash memory.
// <i> By setting this value, you can move flash end address used by the FDS.
// <i> As a result the reserved space can be used by other modules.

#ifndef FDS_VIRTUAL_PAGES_RESERVED
#define FDS_VIRTUAL_PAGES_RESERVED 0
#endif

// </h> 
//==========================================================

// <h> Backend - Backend configuration

// <i> Configure which nrf_fstorage backend is used by FDS to write to flash.
//==========================================================
// <o> FDS_BACKEND  - FDS flash backend.
 

// <i> NRF_FSTORAGE_SD uses the nrf_fstorage_sd backend implementation using the SoftDevice API. Use this if you have a SoftDevice present.
// <i> NRF_FSTORAGE_NVMC uses the nrf_fstorage_nvmc implementation. Use this setting if you don't use the SoftDevice.
// <1=> NRF_FSTORAGE_NVMC 
// <2=> NRF_FSTORAGE_SD 

#ifndef FDS_BACKEND
#define FDS_BACKEND 2
#endif

// </h> 
//==========================================================

// <h> Queue - Queue settings

//==========================================================
// <o> FDS_OP_QUEUE_SIZE - Size of the internal queue. 
// <i> Increase this value if you frequently get synchronous FDS_ERR_NO_SPACE_IN_QUEUES errors.

#ifndef FDS_OP_QUEUE_SIZE
#define FDS_OP_QUEUE_SIZE 4
#endif

// </h> 
//==========================================================

// <h> CRC - CRC functionality

//==========================================================
// <e> FDS_CRC_CHECK_ON_READ - Enable CRC checks.

// <i> Save a record's CRC when it is written to flash and check it when the record is opened.
// <i> Records with an incorrect CRC can still be 'seen' by the user using FDS functions, but they cannot be opened.
// <i> Additionally, they will not be garbage collected until they are deleted.
//==========================================================
#ifndef FDS_CRC_CHECK_ON_READ
#define FDS_CRC_CHECK_ON_READ 1
#endif
// <o> FDS_CRC_CHECK_ON_WRITE  - Perform a CRC check on newly written records.
 

// <i> Perform a CRC check on newly written records.
// <i> This setting can be used to make sure that the record data was not altered while being written to flash.
// <1=> Enabled 
// <0=> Disabled 

#ifndef FDS_CRC_CHECK_ON_WRITE
#define FDS_CRC_CHECK_ON_WRITE 0
#endif

I have two questions about that.
1. How long does it take to clean fds gc.
2. What happens if the fds_gc is interrupted by a charging reset during cleanup?

Best regard
Kenyon

  • Hi Zicongkuang, 

    1. It depends. The gc process basically erase all the records that's marked as "dirty" . It does it by copy the "valid" records to the swap page, erase the page and copy the valid record to the current page. So the process may take longer time if you have a lot of pages to copy&erase. 
    As mentioned in the documentation, you should wait for the FDS_EVT_GC event with NRF_SUCCESS status before continue. But I don't think it would take very long time (usually less than a second). You can find the timing specification here: https://docs.nordicsemi.com/bundle/ps_nrf52810/page/nvmc.html#unique_728973123

    2. There is a checksum at each step in gc process. A page is backed up before it's erased. So there shouldn't be a situation when you lose your data when interrupted when doing gc. I don't think the GC process automatically resume after a reset, so you may need to call it again if you run out of flash again. 

    It's a good practice to use  fds_stat to monitor the amount of flash available instead of waiting for FDS_ERR_NO_SPACE_IN_FLASH error. 

  • Hi Hung Bui


    After I used the FDS module, there was a problem found that there were two valid flash data in the flash area of the hex file, why is this, is there a solution? Or how can we avoid it?

    Best Regard
    Kenyon

  • Hi Kenyon, 
    Could you please explain a little bit more on " there were two valid flash data in the flash area of the hex file"  ? 
    Please describe what do you expect and what was wrong with that. Did it have anything to do with FDS_ERR_NO_SPACE_IN_FLASH issue ? 

    You mentioned that you used secure bootloader, was the problem related to the DFU update ?

  • Hi Hung Bui

    #define CONFIG_FILE (0x8010)
    #define CONFIG_REC_KEY (0x7010)
    static fds_record_t const gtPara_record =
    {
    .file_id = CONFIG_FILE,
    .key = CONFIG_REC_KEY,
    .data.p_data = &gtStorePara,
    /* The length of a record is always expressed in 4-byte units (words). */
    .data.length_words = (sizeof(gtStorePara) + sizeof(uint32_t) - 1) / sizeof(uint32_t),
    };

    We are constantly updating data under the same File ID and Record Key. So I think in flash we should only have one valid data. But strangely enough, we found two valid bits of data in flash using the hex file. Why is that?
    Because of the existence of two valid data, we have to read the data two times each time to read out the latest update data.How can I avoid this?

    Best regard
    Kenyon

  • Hi Kenyon, 

    Have you managed to reproduce the issue ? If not please double check the code to see if there is any chance that you created two record with the same key ? 
    How did you find out the problem ? Did it has any relation to a DFU update ? 

Related