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

Problem implementing fstorage in my application

I am trying to implement fstorage in my application using nRF52840, soft device 140, SDK for Mesh v4.0.0. and SDK 16.0.0 and Segger Studio.

Based on the fstorage example I moved the bits of the needed code to a file, which I will use to interact with flash. I am using a softdevice implementation of fstorage. In short I did the following:

  1. Declare fstorage with NRF_FSTORAGE_DEF(nrf_fstorage_t fstorage)
  2. Prepared a local pointer to fstorage_api: static nrf_fstorage_api_t * mp_fs_api;
  3. Packed command for initialization and flash write into public functions:
    1. void tm_flash_init(void)
    2. void tm_flash_write()
  4. I call tm_flash_init() from main before  ble_stack_init() and tm_flash_write() from main on "f" press using RTT. Mesh is not started to enable debugging.

The code builds without errors or warnings, tm_flash_init returns without errors, but finally tm_flash_write returns Mesh error 16 at 0x0002A5F5 (...\tm_flash.c:82) - Bad Memory Address, because start and end addresses are not set properly in nrf_fstorage_t (*p_fs)

Stepping through the and entering sub-calls (namely nrf_storage.c, ret_code_t nrf_fstorage_write) also reveals that start and end addresses are not set properly in nrf_fstorage_t (*p_fs). Also in line 71, the Go To Definition does not resolve nrf_storage_sd in nfr_storage_sd.c.

I think that the problem must lie somewhere in the usage of NRF_FSTORAGE_DEF or some invalid pointer use. Thank you for any help in advance!

Here is the code (based on fstorage example):

/** @file
 *
 * @This is flashfstorage implementation.
 *
 * It is based on the peripheral/flash_storage example
 *
 * Preprocessor include must include:
 * $(SDK_ROOT:../../../../nRF5_SDK_16.0.0_98a08e2)/components/libraries/fstorage
 * $(SDK_ROOT:../../../../nRF5_SDK_16.0.0_98a08e2)/components/libraries/atomic_fifo
 *
 * app_config.h must include:
 * #define NRF_FSTORAGE_ENABLED 1
 *
 * .c files must be added to the project:
 * nrf_fstorage.c
 * nrf_fstorage_sd.c
 * nrf_atfifo.c
 *
 */

#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#include "log.h"
#include "nrf_soc.h" // for sd_app_evt_wait

#include "mesh_app_utils.h" // for error check

#include "nrf_fstorage.h"
#include "nrf_fstorage_sd.h"


/* Dummy data to write to flash. */
static uint32_t m_data          = 0xBADC0FFE;
static char     m_hello_world[] = "hello world";

// Forward declarations of private functions:
static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt);

static void print_flash_info(nrf_fstorage_t * p_fstorage);
void wait_for_flash_ready(nrf_fstorage_t const * p_fstorage);


//fstorage declaration:
NRF_FSTORAGE_DEF(nrf_fstorage_t fstorage) =
{
    /* Set a handler for fstorage events. */
    .evt_handler = fstorage_evt_handler,

    /* These below are the boundaries of the flash space assigned to this instance of fstorage.
     * You must set these manually, even at runtime, before nrf_fstorage_init() is called.
     * The function nrf5_flash_end_addr_get() can be used to retrieve the last address on the
     * last page of flash available to write data. */
    .start_addr = 0xA0000, //TODO these should be set elswhere
    .end_addr   = 0xAFFFF, //TODO these should be set elswhere
};

static nrf_fstorage_api_t * mp_fs_api;


/****************************
 * Public functions
 ****************************/

void tm_flash_init(void)
{
    ret_code_t rc;
    // Initialize an fstorage instance using the nrf_fstorage_sd backend (to be used with soft device)
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Initializing fstorage.\n");
    mp_fs_api = &nrf_fstorage_sd; //NOTE alt+g does not resolve nrf_storage_sd in nfr_storage_sd.c!
    rc = nrf_fstorage_init(&fstorage, mp_fs_api, NULL);
    ERROR_CHECK(rc);

    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Fstorage init done. Info:\n");
    print_flash_info(&fstorage);
}

void tm_flash_write()
{
    ret_code_t rc;
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Writing \"%x\" to flash\n.", m_data);
    rc = nrf_fstorage_write(&fstorage, 0xA0004, &m_data, sizeof(m_data), NULL);
    ERROR_CHECK(rc);

    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Cmd sent, waiting to complete...\n");
    wait_for_flash_ready(&fstorage);
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Done.\n");
}


/****************************
 * Private functions
 ****************************/

static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt)
{
    if (p_evt->result != NRF_SUCCESS)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "--> Event received: ERROR while executing an fstorage operation.\n");
        return;
    }

    switch (p_evt->id)
    {
        case NRF_FSTORAGE_EVT_WRITE_RESULT:
        {
            __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "--> Event received: wrote %d bytes at address 0x%x.\n",
                         p_evt->len, p_evt->addr);
        } break;

        case NRF_FSTORAGE_EVT_ERASE_RESULT:
        {
            __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "--> Event received: erased %d page from address 0x%x.\n",
                         p_evt->len, p_evt->addr);
        } break;

        default:
            break;
    }
}

static void print_flash_info(nrf_fstorage_t * p_fstorage)
{
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "========| flash info |========\n");
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "erase unit: \t%d bytes\n",      p_fstorage->p_flash_info->erase_unit);
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "program unit: \t%d bytes\n",    p_fstorage->p_flash_info->program_unit);
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "==============================\n");
}

void wait_for_flash_ready(nrf_fstorage_t const * p_fstorage)
{
    /* While fstorage is busy, sleep and wait for an event. */
    while (nrf_fstorage_is_busy(p_fstorage))
    {
        (void)sd_app_evt_wait();
    }
}

Parents Reply Children
  • Hi Joakim,

    Thank you for your reply. I have missed the notification e-mail.

    I was considering flash options from the basic SDK: Flash write, FDS and FStorage. The first one was too basic, the second one too complicated and the FStorage looked just on the right level for our needs. Our needs are storing approximately one 32 bit counter value and about 64 bytes of configuration data. My intetion was to make a simple wear leveling algorithm by using one page consecutive write for the counter and erase the page when it is full. And similar for the configuration data.

    I confess, I did not look into the mesh SDK for flash options. In any case, due to power constraints, we decided not to use the mesh protocol and will revert back to basic SDK. I just wanted to implement this flash storage before migrating back to the SDK without mesh.

    Could it be that the mesh SDK is causing our issues? I was dealing with this problem last week and I think that there is a problem with definition of the fstorage (NRF_FSTORAGE_DEF(nrf_fstorage_t fstorage) =...). To my understanding, it stores the pointer to the event handles, the start and the end addresses to the "fs_data" section in flash. It does so in the Nordic example, but not in my implementaiton.

    Should I first revert to the bare SDK?
    What are the things I could check to pinpoint the problem?
    Which flash interface would you recommend for our needs?

    Thank you and best regards,
    Matevz

  • Hi.

    Sorry about the delay here.

    Have you made any progress on this, or do you still need assistance?

    Br,
    Joakim

  • Hi,

    I just managed to flash our board with the modified BLE UART  example from SDK 17.0.2 and added extracted fstorage functionality to it. It works as it should.

    Obviously, the problem was attempt to use fstorage with the Mesh SDK.

    So for our particular case, no assistance is needed anymore.

    Best regards,
    Matevz

  • I'm glad to hear that it works!

    If you don't need any further assistance I will close the ticket.

    You are welcome to create another ticket if you face any problems in the future.

    Br,
    Joakim

Related