Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

About FDS module data power-off protection

Development environment:

NRF52832

SDK:15.3

SOFTDEVICE:NONE

When testing the FDS module power-off data protection feature, the FDS module is abnormal.

During the FDS module garbage collection process, performing a software reset may cause the FLASH data to be abnormal.
I checked the source code of the FDS and found that the following problems might exist:
Stage 1: FDS garbage collection execution, copy data_page to swap_page
Stage 2: Erase data_page
Stage 3: Perform a software reset
Stage 4: First find the erase_page in the execution of the functions pages_init(), and then tag the erase_page as swap_page. This will cause m_gc.cur_page not to be set.

            case FDS_PAGE_UNDEFINED:
            {
                if (page_is_erased(p_page_addr))
                {
                    if (m_swap_page.p_addr != NULL)
                    {
                        // If a swap page is already set, flag the page as erased (in m_pages)
                        // and try to tag it as data (in flash) later on during initialization.
                        m_pages[page].page_type    = FDS_PAGE_ERASED;
                        m_pages[page].p_addr       = p_page_addr;
                        m_pages[page].write_offset = FDS_PAGE_TAG_SIZE;
                        
                        // This is a candidate for a potential new swap page, in case the
                        // current swap is going to be promoted to complete a GC instance.
                        m_gc.cur_page = page;
                        page++;
                    }
                    else
                    {
                        /*********************************************/
                        // m_gc.cur_page not to be set
                        /********************************************/
                        
                        // If there is no swap page yet, use this one.
                        m_swap_page.p_addr       = p_page_addr;
                        m_swap_page.write_offset = FDS_PAGE_TAG_SIZE;
                        swap_set_but_not_found   = true;
                    }

                    ret |= PAGE_ERASED;
                }
                else
                {
                    // The page contains non-FDS data.
                    // Do not initialize or use this page.
                    total_pages_available--;
                    m_pages[page].p_addr    = p_page_addr;
                    m_pages[page].page_type = FDS_PAGE_UNDEFINED;
                    page++;
                }
            } break;

Stage 5: After page_init() is executed, init_opts = 0x0B, and then the following code is executed:

        case FDS_OP_INIT_PROMOTE_SWAP:
        {
            p_op->init.step       = FDS_OP_INIT_TAG_SWAP;

            // When promoting the swap, keep the write_offset set by pages_init().
            ret = page_tag_write_data(m_swap_page.p_addr);
            
            /******************************************************/
            //m_gc.cur_page has not been set
            /******************************************************/
            
            uint16_t const         gc         = m_gc.cur_page;
            uint32_t const * const p_old_swap = m_swap_page.p_addr;

            // Execute the swap.
            m_swap_page.p_addr = m_pages[gc].p_addr;
            m_pages[gc].p_addr = p_old_swap;

            // Copy the offset from the swap to the new page.
            m_pages[gc].write_offset = m_swap_page.write_offset;
            m_swap_page.write_offset = FDS_PAGE_TAG_SIZE;

            m_pages[gc].page_type = FDS_PAGE_DATA;
        } break;

Stage 6:FDS module data is abnormal, SWAP_PAGE will not be found

Please confirm this question, thank you!

Parents
  • I modified the FDS code and executed the power-off data protection test. It is normal. increased:m_gc.cur_page = page;

                case FDS_PAGE_SWAP:
                {
                    NRF_LOG_DEBUG("fds_init find swap page\r\n");
                    
                    if (swap_set_but_not_found)
                    {
                        m_pages[page].page_type    = FDS_PAGE_ERASED;
                        m_pages[page].p_addr       = m_swap_page.p_addr;
                        m_pages[page].write_offset = FDS_PAGE_TAG_SIZE;
                        m_gc.cur_page = page;
                        page++;
                    }
    
                    m_swap_page.p_addr = p_page_addr;
                    // If the swap is promoted, this offset should be kept, otherwise,
                    // it should be set to FDS_PAGE_TAG_SIZE.
                    page_scan(p_page_addr, &m_swap_page.write_offset, NULL);
    
                    ret |= (m_swap_page.write_offset == FDS_PAGE_TAG_SIZE) ?
                            PAGE_SWAP_CLEAN : PAGE_SWAP_DIRTY;
                } break;

Reply
  • I modified the FDS code and executed the power-off data protection test. It is normal. increased:m_gc.cur_page = page;

                case FDS_PAGE_SWAP:
                {
                    NRF_LOG_DEBUG("fds_init find swap page\r\n");
                    
                    if (swap_set_but_not_found)
                    {
                        m_pages[page].page_type    = FDS_PAGE_ERASED;
                        m_pages[page].p_addr       = m_swap_page.p_addr;
                        m_pages[page].write_offset = FDS_PAGE_TAG_SIZE;
                        m_gc.cur_page = page;
                        page++;
                    }
    
                    m_swap_page.p_addr = p_page_addr;
                    // If the swap is promoted, this offset should be kept, otherwise,
                    // it should be set to FDS_PAGE_TAG_SIZE.
                    page_scan(p_page_addr, &m_swap_page.write_offset, NULL);
    
                    ret |= (m_swap_page.write_offset == FDS_PAGE_TAG_SIZE) ?
                            PAGE_SWAP_CLEAN : PAGE_SWAP_DIRTY;
                } break;

Children
No Data
Related