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

Including Flash Data Storage on light switch example

Hello,

we are using SDK version 15.3 and mesh SDK version 3.2.0, on a nRF52840 DK board using the Segger Embedded Studio IDE version 4.52 (64-bit).

Our goal is to add Flash Data Storage (FDS) capabilities to our products firmware to store some data on nonvolatile memory on demand.

To start off, we tried the FDS example on our hardware using a freshly downloaded SDK and mesh SDK. It might be a problem with our SES configs, but we had to replace the NRF_LOG_INFO occurrences on main.c with printf's to get something on the terminal, but after that, we got to see how many boot sequences occurred since the device was flashed.

Then we got back to the light switch example and tried including everything that was needed from the flash_fds example on the examples/peripheral/flash_fds folder of the mesh SDK.

We show below a comprehensive list of changes made to the light switch example project and files, hoping to get the same behavior on the light switch example that we got on the FDS one:

1 We included fds.h to the top of main.c, declared all the functions needed for the basic working of the FDS example, and added some parts of the FDS example to main.c.

    

#include "fds.h"

static struct
{
    bool delete_next;   //!< Delete next record.
    bool pending;       //!< Waiting for an fds FDS_EVT_DEL_RECORD event, to delete the next record.
} m_delete_all;

/* Flag to check fds initialization. */
static bool volatile m_fds_initialized;

static void fds_evt_handler(fds_evt_t const * p_evt)
{
//    __LOG("Event: %s received (%s)", fds_evt_str[p_evt->id], fds_err_str[p_evt->result]);

    switch (p_evt->id)
    {
        case FDS_EVT_INIT:
            if (p_evt->result == FDS_SUCCESS)
            {
                m_fds_initialized = true;
            }
            break;

        case FDS_EVT_WRITE:
        {
            if (p_evt->result == FDS_SUCCESS)
            {
//                __LOG("Record ID:\t0x%04x",  p_evt->write.record_id);
//                __LOG("File ID:\t0x%04x",    p_evt->write.file_id);
//                __LOG("Record key:\t0x%04x", p_evt->write.record_key);
            }
        } break;

        case FDS_EVT_DEL_RECORD:
        {
            if (p_evt->result == FDS_SUCCESS)
            {
//                __LOG("Record ID:\t0x%04x",  p_evt->del.record_id);
//                __LOG("File ID:\t0x%04x",    p_evt->del.file_id);
//                __LOG("Record key:\t0x%04x", p_evt->del.record_key);
            }
            m_delete_all.pending = false;
        } break;

        default:
            break;
    }
}

/**@brief   Sleep until an event is received. */
static void power_manage(void)
{
#ifdef SOFTDEVICE_PRESENT
    (void) sd_app_evt_wait();
#else
    __WFE();
#endif
}

/**@brief   Wait for fds to initialize. */
static void wait_for_fds_ready(void)
{
    while (!m_fds_initialized)
    {
        power_manage();
    }
}

int main(void)
{
    initialize();
    start();

    /* Register first to receive an event when initialization is complete. */
    (void) fds_register(fds_evt_handler);
    ret_code_t rc = fds_init();
    APP_ERROR_CHECK(rc);
    /* Wait for fds to initialize. */
    wait_for_fds_ready();

    fds_stat_t stat = {0};

    rc = fds_stat(&stat);
    APP_ERROR_CHECK(rc);

    printf("Found %d valid records.", stat.valid_records);
    printf("Found %d dirty records (ready to be garbage collected).", stat.dirty_records);


    for (;;)
    {
        (void)sd_app_evt_wait();
    }
}

2 - Then we tried to compile the program and fixed all the problems the compiler had with not finding a file or function, by adding the following:

2.1 - On the project we added the to c_user_include_directories:

$(SDK_ROOT)/components/libraries/fds;

$(SDK_ROOT)/components/libraries/fstorage;

$(SDK_ROOT)/components/libraries/atomic_fifo;

$(SDK_ROOT)/components/libraries/crc16;

2.2 - We added the following files to the project:

$(SDK_ROOT)/components/libraries/atomic_fifo/nrf_atfifo.c

$(SDK_ROOT)/components/libraries/crc16/crc16.c

$(SDK_ROOT)/components/libraries/fds/fds.c

$(SDK_ROOT)/components/libraries/fstorage/nrf_fstorage.c

$(SDK_ROOT)/components/libraries/fstorage/nrf_fstorage_sd.c

3 - We searched the FDS example for all mentions on "storage" and "flash", and copied all the definitions that matched, so these were the relevant lines that were added/modified:

#ifndef FDS_ENABLED
#define FDS_ENABLED 1
#endif

#ifndef FDS_VIRTUAL_PAGES
#define FDS_VIRTUAL_PAGES 5
#endif

#ifndef FDS_VIRTUAL_PAGES_RESERVED
#define FDS_VIRTUAL_PAGES_RESERVED 2
#endif

#ifndef FDS_CRC_CHECK_ON_READ
#define FDS_CRC_CHECK_ON_READ 1
#endif

#ifndef NRF_FSTORAGE_ENABLED
#define NRF_FSTORAGE_ENABLED 1
#endif


FDS_VIRTUAL_PAGES was originally set to 3, but since we are using mesh and from our nrf_mesh_config_app.h file we have

#define ACCESS_FLASH_PAGE_COUNT (1)
#define DSM_FLASH_PAGE_COUNT (1)


and since we know that the FDS uses the same flash area that the DSM and ACCESS Layer stuff, we chose to add to the default 3 VIRTUAL_PAGES the 2 that the mesh stuff seem to be using.
Also, to offset the available flash area from the one used by the mesh, we also set FDS_VIRTUAL_PAGES_RESERVED to 2, where it was 0 originally.

4- We also found this resource that advised us to include the following code to nrf_mesh_config_app.h

#include "fds.h" 
#include "fds_internal_defs.h" 
#define FLASH_MANAGER_RECOVERY_PAGE_OFFSET_PAGES FDS_PHY_PAGES

After all these modifications, the light switch example could be compiled, but upon booting on debug mode, the program halted without logging any assert error.
The debugger showed the program halted on address 0xA60 of the program and that, for us, was very weird because that low on the memory stack, that is MBR region.

5- Finally we tried copying the entirety of the contents of linker_section_placement_macros and linker_section_placements_segments properties from the FDS project to the light switch example:

FDS:
linker_section_placement_macros:
FLASH_PH_START=0x0;
FLASH_PH_SIZE=0x100000;
RAM_PH_START=0x20000000;
RAM_PH_SIZE=0x40000;
FLASH_START=0x26000;
FLASH_SIZE=0xda000;
RAM_START=0x20002210;
RAM_SIZE=0x3ddf0

linker_section_placements_segments:
FLASH RX 0x0 0x100000;
RAM RWX 0x20000000 0x40000


light switch:
linker_section_placement_macros:
FLASH_PH_START=0x0;
FLASH_PH_SIZE=0xf8000;
RAM_PH_START=0x20000000;
RAM_PH_SIZE=0x3f000;
FLASH_START=0x26000;
RAM_START=0x20002da0;

linker_section_placements_segments:
FLASH RX 0x0 0xf8000;
RAM RWX 0x20000000 0x3f000

But even after the light switch project had these properties matching the ones of the FDS, the error was the same.


6- As we were desperate to solve this issue, we tried increasing both FDS_VIRTUAL_PAGES to 30 and FDS_VIRTUAL_PAGES_RESERVED to 10 so that there was not a possibility of having overlaps, the error was still the same

We suspect there might be a problem with defining memory areas, but I'm afraid we cannot proceed anymore alone and would require some help from you guys solving this issue.

For that purpose, we are adding the zipped project so you can take a look at it: light_switch.zip

Thank you in advance,

Rúben Marques

Parents
  • Hi,

    I am afraid we are entering summer vacation season in Norway and so things may take some more time than usual from our end.

    Initially, I have a couple of remarks / suggestions:

    • There is a section of the nRF5 SDK for Mesh documentation, named Integrating Mesh into nRF5 SDK examples.
    • Among the topics handled in the above documentation is flash, and specifically what settings are required for Flash Manager (from nRF5 SDK for Mesh) and fstorage/FDS (from nRF5 SDK) to coexist. There, instead of setting FDS_VIRTUAL_PAGES_RESERVED, it is suggested to add "#define FLASH_MANAGER_RECOVERY_PAGE_OFFSET_PAGES FDS_PHY_PAGES" in order for the flash manager not to use the flash pages used by FDS.
    • Setting FDS_VIRTUAL_PAGES to 30 is way too high, as it would set aside (at least) 120 kB of flash space to FDS. Depending on the size of virtual pages (multiple of "real" pages, by default equal to "real" pages) it can be any multiple of that. The define sets how much space on the device should be used by FDS.
    • If you have a flash dump from a device, it is possible to figure out what exact pages are used for FDS, what pages are used by flash manager, etc, by looking at the flash contents. You can generate a flash dump using "nrfjprog --readuicr --readcode dump.hex", which would save a dump of flash (including the UICR page) to a new file named "dump.hex". If you provide such dumps it would be possible for me to investigate the state of flash and what corruption (if any) is seen in FDS pages.

    Regards,
    Terje

  • We cannot determine the conditions that trigger the error on the program that stops it on address 0xA60, but it happened again.

    We have noticed on the link you provided that using fstorage (used by FDS) might be problematic with mesh activity, and to instead use the Flash manager module to write to the flash. From our understanding, the DSM uses Flash manager to store mesh data and we don't have a particular requirement to use FDS, we just want to write to and read from the flash.

    Is there a working example of basic Flash manager use in the mesh SDK? I will create a new ticket if we need to discuss its implementation.

    Thank you,

    Rúben Marques

  • Hi,

    I am afraid there is no SDK example dedicated to flash manager usage from the application. That means you need to consult the documentation on Infocenter for your implementation.

    Regards,
    Terje

Reply Children
No Data
Related