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

FDS swap page not found

nRF5 SDK v15.2.0, nRF52840

This issue occurs on reset, most often after cycling power.

There are 4 pages reserved and 4 data pages are found.  Since a swap page isn't found, the initialization of FDS fails.

Changes made to debug this issue:

fds.c line 96 - static fds_page_t m_pages[FDS_DATA_PAGES+1]; // add one for the swap page in the event it isn't recognized as swap

fds_internal_defs - line 112 - Make default values bad state

typedef enum
{
FDS_PAGE_UNDEFINED = 0, // Undefined page type.
FDS_PAGE_DATA, // Page is ready for storage.
FDS_PAGE_SWAP, // Page is reserved for garbage collection.
FDS_PAGE_ERASED, // Page is erased.
} fds_page_type_t;


typedef enum
{
FDS_HEADER_CORRUPT = 0, // Header contains corrupt information, not related to CRC.
FDS_HEADER_VALID, // Valid header.
FDS_HEADER_DIRTY // Header is incomplete, or record has been deleted.
} fds_header_status_t;

What are possible paths for this state to occur? Is it most likely an interrupted garbage collection?

Is there a reason FDS_PAGE_TAG_SWAP and FDS_PAGE_TAG_DATA only differ by one bit?

If there is an empty page, can it be converted to a swap page?  There are 3 empty pages in my case.

/resized-image/__size/320x240/__key/support-attachments/beef5d1b77644c448dabff31668f3a47-9cd8a7416485476db0b604e483852e1c/noSwap.png

Parents
  • Hello,

    Is it possible to send a flash dump of the chip?

     

    If there is an empty page, can it be converted to a swap page?  There are 3 empty pages in my case.

     You mean data pages that doesn't have any data except from the data tag?

    If so, that would be the suggested procedure yes.

    According to the flow diagram for the FDS this is a situation that really shouldn't happen, but we have seen similar cases earlier. It is likely caused by a garbage collection that is not finished due to a power cut. 

    We recommend to not call fds_gc() except if a fds function returns a return value indicating that the fds pages are full. It is not(!) recommended to run fds_gc() on startup. This will beat up the flash, and use up the number of flash write/erase cycles faster than necessary. In addition, it increases the risk of this happening.

    However, if you find yourself in the situation where you have 4 data pages and no swap pages, I recommend that you find one that is empty, delete it, and set it as swap page. 

     

    Is there a reason FDS_PAGE_TAG_SWAP and FDS_PAGE_TAG_DATA only differ by one bit?

     It is not by coincidence. The reason is that it is only possible to set 1's to 0's in the flash without erasing an entire flash page. (flash page != fds page, but a flash page is larger than just the page tag).

    So in order to ensure that the swap page can become a data page, one of the 1's is flipped to 0. That is why the data tag and swap tag are so similar.

    Either way, I would like to see a flash dump of the chip for research purposes. Did you start with 4 or 5 data pages?

    Best regards,

    Edvin

    Best regards,

    Edvin

Reply
  • Hello,

    Is it possible to send a flash dump of the chip?

     

    If there is an empty page, can it be converted to a swap page?  There are 3 empty pages in my case.

     You mean data pages that doesn't have any data except from the data tag?

    If so, that would be the suggested procedure yes.

    According to the flow diagram for the FDS this is a situation that really shouldn't happen, but we have seen similar cases earlier. It is likely caused by a garbage collection that is not finished due to a power cut. 

    We recommend to not call fds_gc() except if a fds function returns a return value indicating that the fds pages are full. It is not(!) recommended to run fds_gc() on startup. This will beat up the flash, and use up the number of flash write/erase cycles faster than necessary. In addition, it increases the risk of this happening.

    However, if you find yourself in the situation where you have 4 data pages and no swap pages, I recommend that you find one that is empty, delete it, and set it as swap page. 

     

    Is there a reason FDS_PAGE_TAG_SWAP and FDS_PAGE_TAG_DATA only differ by one bit?

     It is not by coincidence. The reason is that it is only possible to set 1's to 0's in the flash without erasing an entire flash page. (flash page != fds page, but a flash page is larger than just the page tag).

    So in order to ensure that the swap page can become a data page, one of the 1's is flipped to 0. That is why the data tag and swap tag are so similar.

    Either way, I would like to see a flash dump of the chip for research purposes. Did you start with 4 or 5 data pages?

    Best regards,

    Edvin

    Best regards,

    Edvin

Children
  • I have always had 4 data pages.

    In this specific case the problem with the code is on line ~695.  If the swap page is seen as a data page, then m_pages[page] can reference memory that is beyond what was allocated.  That is why I added the +1. 

    It doesn't change the number of pages because that is controlled by the defines, but it makes the variable big enough to handle this error condition.

  • Hello,

    I see. Well. Increasing the page size here is probably a bit sketchy, because it will increase the number of pages for this startup, and the next time it tries to initialize the FDS, if the swap page is within the first 4 pages, this page will not be included, right? If so, you may miss some records, right?

    I suggest that if you find yourself in the situation with 4 FDS pages where all of them are data pages, and none of them are flash pages, you look for a data page that doesn't have any records (the rest of the page is 0xFF's), and then delete this page. Then do a reboot, or call fds_init() again. Then this empty page without any tags will be initialized as a swap page on the next call to fds_init(). 

  • I am not increasing the page size or the number of pages.

    Let me try to explain the problem again.

    static fds_page_t m_pages[3];  // FDS_DATA_PAGES == 3, FDS_VIRTUAL_PAGES == 4

    // when all three pages and swap look like a data page

    line ~695 m_pages[3].page_type = FDS_PAGE_DATA;  // this is bad because m_pages only has locations 0, 1, and 2.

  • What function(s) do you recommend using for deleting the page?

  • Hello,

    ahedin25 said:
    static fds_page_t m_pages[3];  // FDS_DATA_PAGES == 3, FDS_VIRTUAL_PAGES == 4

     Of course. I see.

    I suggest that you look at the functions gc_swap_erase() and gc_page_erase() in fds.c. Since you have a data page (not swap), the gc_page_erase() is probably the closest. Alternatively, use nrf_fstorage_erase() directly, like it is done in gc_page_erase(). You may want to avoid the state machine in fds, so maybe avoid setting the state, like it does in nrf_fstorage_erase(), but you do want to wait for the page erase to finish. fs_event_handler should be called when this is done, with the p_evt->id == NRF_FSTORAGE_EVT_ERASE_RESULT, and hopefully p_evt->result == NRF_SUCCESS.

    When this has returned, the page is erased. From here, you can either try to initiate FDS once more (It should repair itself if it has N-1 Data pages and one empty page, where N = FDS_VIRTUAL_PAGES). Alternatively, in case the fds state machine is difficult to deal with, you can run NVIC_SystemReset(); to reset the application, which then will run fds_init() again. Now with the empty page it should repair itself.

    Best regards,

    Edvin

Related