Can't seem to get the fstorage library to work properly.

I'm trying to get some data written and read from flash memory using the fstorage library as explained in the examples provided with the sdk.

I write to flash and get the callback saying that the bytes were written and try to read them back with garbage returned, not sure what i'm missing. I also try to read the memory using the memory viewer in segger embedded studio which is also showing nothing being modified.

I've attached the code for reference just trying to write a 32 bit integer value as i failed to get it to work with anything so i went back to exactly what the example had.
Can someone provide some insights on how to get this working?

#include <string.h>
#include "flash_module.h"
#include "nrf.h"
#include "app_error.h"
#include "nrf_fstorage_sd.h"
#include "nrf_log.h"

static nrf_fstorage_api_t * p_fs_api;
static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt);
__ALIGN(4) static uint32_t mac = 0xBADC0FFE;

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 = 0x3e000,
    .end_addr   = 0x3ffff,
};

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

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

        case NRF_FSTORAGE_EVT_ERASE_RESULT:
        {
            NRF_LOG_INFO("--> Event received: erased %d page from address 0x%x.",
                         p_evt->len, p_evt->addr);
        } break;
        
        case NRF_FSTORAGE_EVT_READ_RESULT:
        {
          NRF_LOG_INFO("--> Event received: read %d bytes at address 0x%x.",
                         p_evt->len, p_evt->addr);

        } break;
        default:
            break;
    }
}

void flash_setup(){
  ret_code_t err_code;
  p_fs_api = &nrf_fstorage_sd;
  err_code = nrf_fstorage_init(&fstorage, p_fs_api, NULL);
  APP_ERROR_CHECK(err_code);
}

void flash_write_bytes(uint8_t array[]){
  ret_code_t err_code;

  err_code = nrf_fstorage_write(&fstorage, 0x3e000, &mac, sizeof(mac), NULL);
  APP_ERROR_CHECK(err_code);
}

uint32_t *flash_read_bytes()
{
  uint8_t array[256] = {0};
  ret_code_t err_code;

  err_code = nrf_fstorage_read(&fstorage, 0x3e000, array, sizeof(array));
  APP_ERROR_CHECK(err_code);

  return array;
}

Parents
  • Hi,

    I don't immediately see the problem here. Did you remember to do a full erase before testing this code? That is important in case the address you write to was not erased from before, and a write can only flip bits from '1' to '0'. If that is not the problem, then perhaps you can upload a full failing example so that I can have a closer look?

  • Ok we got it sorted.
    The problem was the actual memory addresses used, so for anyone who comes across this in the future, the way I solved it was to use this method to adjust the memory used:

    static uint32_t nrf5_flash_end_addr_get()
    {
        uint32_t const bootloader_addr = BOOTLOADER_ADDRESS;
        uint32_t const page_sz         = NRF_FICR->CODEPAGESIZE;
        uint32_t const code_sz         = NRF_FICR->CODESIZE;
        
        uint32_t returnvalue = 0;
        returnvalue = (bootloader_addr != 0xFFFFFFFF ? bootloader_addr : (code_sz * page_sz));
        return returnvalue;
    }


    This method is used to return the end of the memory taking into account the bootloader position.
    So this method returns the end address and i subtracted the size of memory that I wanted and got the start address like this:


    end_addr = nrf5_flash_end_addr_get();
    fstorage.end_addr = end_addr;
    start_addr = end_addr - 0x400;
    fstorage.start_addr = start_addr; 


    This has to be done before the nrf_fstorage_init command.

    After that I used the start address to write the bytes i needed and as mentioned everywhere it has to be 32 bit values so multiples of 4 bytes, anything less would return error 0x09.

Reply
  • Ok we got it sorted.
    The problem was the actual memory addresses used, so for anyone who comes across this in the future, the way I solved it was to use this method to adjust the memory used:

    static uint32_t nrf5_flash_end_addr_get()
    {
        uint32_t const bootloader_addr = BOOTLOADER_ADDRESS;
        uint32_t const page_sz         = NRF_FICR->CODEPAGESIZE;
        uint32_t const code_sz         = NRF_FICR->CODESIZE;
        
        uint32_t returnvalue = 0;
        returnvalue = (bootloader_addr != 0xFFFFFFFF ? bootloader_addr : (code_sz * page_sz));
        return returnvalue;
    }


    This method is used to return the end of the memory taking into account the bootloader position.
    So this method returns the end address and i subtracted the size of memory that I wanted and got the start address like this:


    end_addr = nrf5_flash_end_addr_get();
    fstorage.end_addr = end_addr;
    start_addr = end_addr - 0x400;
    fstorage.start_addr = start_addr; 


    This has to be done before the nrf_fstorage_init command.

    After that I used the start address to write the bytes i needed and as mentioned everywhere it has to be 32 bit values so multiples of 4 bytes, anything less would return error 0x09.

Children
No Data
Related