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

Why are the records getting dirty in fds example

I am trying to use the fds example provided in the sdk16, while viewing the debugging prints I see the following,

<info> app: Initializing fds...
<info> app: Event: FDS_EVT_INIT received (NRF_SUCCESS)
<info> app: Found 1 valid records.
<info> app: Found 41 dirty records (ready to be garbage collected).

Every time I restart the boot count is rightfully incremented and saved back on the flash also displayed in the debugging log. Why are the records getting dirty (and I need to run garbage collector).

Thank you

Parents
  • Hi,

    The purpose of creating a new record and then invalidating the old one is not solely to prevent data loss due to power loss, this is also a more effective way to store data in flash. Flash can only be erased a whole page at a time, meaning that deleting a record and writing a new one back to the same location would require the entire flash page to be erased in between. Erasing a flash page takes a long time, and the flash has a limited number of write/erase cycles (endurance) before it starts to fail. Spreading the writes out over the entire page will provide basic flash wear leveling, increase the lifetime of the flash.

    The maximum data you can store before running garbage collection depends on the number of reserved pages for FDS (FDS_VIRTUAL_PAGES). Note that one of the pages (SWAP page) will be reserved for garbage collection. During garbage collection, valid records are copied to the SWAP page before the DATA page is erased. The old SWAP page is then promoted to a DATA page, while the old DATA page will become the new SWAP page.

    You can call fds_stat() to get statistics about the available flash size. It is not recommended to run garbage collection too often, as this will increase the wear on flash. We recommend calling it only when FDS has filled all available space, or when it is getting close to full.

    Best regards,
    Jørgen

  • That is almost correct. Each page contains a Page tag, which occupies the first two words. This limits the available words for each page to 1022. Also, note that each record has a 3-word header, which needs to be accounted for when calculating the available space for actual data.

Reply Children
  • Refer the declaration below,

    typedef struct
    {
      uint32_t boot_count;
      
    } minimal_configuration_t;
    
    

    I am updating single word record in flash,

    After record has been successfully updated I am comparing the words (stat.words_used) written in flash,

    ================================================================================
                      F L A S H   S T A T S  ( F D S )
    ================================================================================
    | BEFORE | AFTER | DESCRIPTION
    |-------------------------------------------------------------------------------
    | 3      | 3     |   Pages Available.
    | 0      | 0     |   Open records.
    | 1      | 1     |   Valid records.
    | 74     | 75    |   Dirty records (ready to be garbage collected).
    | 7      | 7     |   Words reserved by fds_reserve().
    | 680    | 687   |   Words written to flash.
    | 1022   | 1022  |   Largest number of free contiguous words in file system.
    | 662    | 669   |   Words that can be reclaimed by garbage.
    | 0      | 0     |   Corrupted records.
    ================================================================================
    

    Before: 680

    After : 687

    Difference = 7

    Since the length of new record's header is 3 and length of the data i.e. boot_count is 1 word. Shouldn't the difference be 4 instead of 7?

  • Are you sure you did only write one word? Note that the data.length_words parameter in the fds_record_t struct takes the number of words, not the number of bytes, to be written. If you use sizeof() or similar to get the size of the struct, you need to divide by 4.

    I modified the FDS example to output stats.words_used and it seems to work correctly:

    fds example:~$ stat
    total pages:    3
    total records:  2
    valid records:  2
    dirty records:  0
    largest contig: 1022
    freeable words: 0 (0 bytes)
    words used:     12
    fds example:~$ write 0xFF 0xFF TEST
    writing record to flash...
    file: 0xFF, key: 0xFF, "TEST", len: 4 bytes
    <info> app: Event: FDS_EVT_WRITE received (NRF_SUCCESS)
    <info> app: Record ID:  0x0003
    <info> app: File ID:    0x00FF
    <info> app: Record key: 0x00FF
    fds example:~$ stat
    total pages:    3
    total records:  3
    valid records:  3
    dirty records:  0
    largest contig: 1022
    freeable words: 0 (0 bytes)
    words used:     16

  • That was the case.

    .data.length_words = (sizeof(four_word_cfg) + 3) / sizeof(uint32_t),

Related