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

fds garbage. Invalid offset on new page.

SDK 4.0.0-2.alpha

When run garbage collection, sometimes invalid offset on new page is present. Adding next string fix this. m_swap_page.write_offset = FDS_PAGE_TAG_SIZE; // [FIX]

I did correctly?

Full function text:

static ret_code_t gc_swap()

{ uint32_t ret; uint16_t const gc = m_gc.cur_page;

CRITICAL_SECTION_ENTER();
uint16_t const records_open = m_pages[gc].records_open;
CRITICAL_SECTION_EXIT();

if (records_open == 0)
{
    /** The page being GC will be the new swap, and the current swap
     *  will be used as a valid page. */
    uint32_t const * const p_addr = m_swap_page.p_addr;

    m_swap_page.p_addr = m_pages[gc].p_addr;
    m_pages[gc].p_addr = p_addr;

    m_pages[gc].write_offset = m_swap_page.write_offset;

    // Erase the new swap page.
    ret = fs_erase(&fs_config, m_swap_page.p_addr, FDS_PHY_PAGES_IN_VPAGE);

    m_swap_page.write_offset = FDS_PAGE_TAG_SIZE; // [FIX]
    
    m_gc.state = GC_TAG_VALID;
}
else
{
    /** If there are open records, we can't GC the page anymore.
     *  Discard the swap and try to GC another page. */
    ret = gc_erase_swap();
}

return ret;

}

  • Hi,

    Could you post a test-snippet on how you are re-creating this scenario? Is it storing+erasing data, storing+erasing, then running a GC?

    Cheers, Håkon

  • Hi! I save bond data and periodic save my custom parameters. When save my custom parameters and the flash page ends, fds_write() return FDS_ERR_NO_SPACE_IN_FLASH. It runs fds_gc(). In the second iteration, result of fds_gc() is erased page and new page with data at error offset, see pics. This error offset equal length of bond data. FDS_VIRTUAL_PAGES =2 for simplify.

    image description

    bool saveFile (dataFile_t &data)
    

    { ret_code_t retval; fds_record_key_t key; fds_record_chunk_t chunk; fds_record_desc_t descriptor;

    clearFile(data);
    
    // Fill in the record keys.
    key.type     = SETUP_PARAMETERS_TYPE;
    key.instance = data.fileId;
    
    // Initialize the record chunk, pointing it to the data to be stored.
    chunk.p_data       = data.pointer;
    chunk.length_words = data.length;
    
    // Write the record to flash.
    retval = fds_write /*fds_update*/ (&descriptor,
                       key,
                       1,
                       &chunk);
    
    if (retval != NRF_SUCCESS)
    {
        if (retval == FDS_ERR_NO_SPACE_IN_FLASH)
        {
            //Garbage collection reclaims the flash space occupied by records which have been cleared using fds_clear
            fds_gc();
            vTaskDelay(GC_WAIT_100MLS);
            // Write the record to flash.
            retval = fds_write (&descriptor,
                                key,
                                1,
                                &chunk);
            if (retval != NRF_SUCCESS) return false;
        }
        else return false;
    }
    return true;
    

    }

  • Hi Petr,

    I can confirm the issue that you are seeing, and the validity of your workaround.

    I had a chat with the developers of FDS, and looked into the internal repository. They have actually implemented the same fix that you have found, and this will be included in the next release of the SDK.

    Best regards, Håkon

Related