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:
- Declare fstorage with NRF_FSTORAGE_DEF(nrf_fstorage_t fstorage)
- Prepared a local pointer to fstorage_api: static nrf_fstorage_api_t * mp_fs_api;
- Packed command for initialization and flash write into public functions:
- void tm_flash_init(void)
- void tm_flash_write()
- 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();
}
}