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

NRF_FSTORAGE_DEF address defined issue with 14.1.0

Hello,

I have some trouble to use fstorage function with dfu function, please help to let me know the solution in order to solve the following issues,

thankful for your support in advance,

thanks.

  1. the method to define the start/end address in NRF_FSTORAGE_DEF,

when checking the memory map with DFU, I can see the memory map with the following link,

infocenter.nordicsemi.com/index.jsp

it means that I need to store data (user data) between the address defined with DFU_APP_DATA_RESERVED and 0x07b000.

in components/libraries/bootloader/dfu/nrf_dfu_types.h,

/** @brief  Size of the flash space reserved for application data.
 */
#ifndef DFU_APP_DATA_RESERVED
#define DFU_APP_DATA_RESERVED               CODE_PAGE_SIZE * 8//love_0130
#endif

CODE_PAGE_SIZE is 0x1000,

so, in this case, I can calculate for start address, it is 0x07b000 - 0x8000, so 0x73000. is it right ?

so I updated the address in my code, please refer it, and help to let me know what problem is, currently, I got the following error,

Error is,

nrf_fstorage_erase => NRF_ERROR_INVALID_ADDR (number : 16) nrf_fstorage_read ==> can't read any data, nrf_fstorage_write => NRF_ERROR_INVALID_LENGTH (number : 9)

what is problem ?

Code is,

please point out the problem with code, I updated the similar issues for many times, really, I need your help to separate correctly issue and to solve in code, thankful for your support in advance,

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

#include "nrf.h"
#include "nrf_soc.h"
#include "nordic_common.h"
#include "boards.h"
#include "app_timer.h"
#include "app_util.h"
#include "nrf_fstorage.h"

#include "nrf_sdh.h"
#include "nrf_sdh_ble.h"
#include "nrf_fstorage_sd.h"

#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

#define FLASHWRITE_EXAMPLE_MAX_STRING_LEN       (62u)
#define FLASHWRITE_EXAMPLE_BLOCK_VALID          (0xA55A5AA5)
#define FLASHWRITE_EXAMPLE_BLOCK_INVALID        (0xA55A0000)
#define FLASHWRITE_EXAMPLE_BLOCK_NOT_INIT       (0xFFFFFFFF)

//love_1211
//refer to infocenter.nordicsemi.com/index.jsp

static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt)
{
	if (p_evt->result != NRF_SUCCESS)
	{
		printf("--> Event received: ERROR while executing an fstorage operation. \r\n");
		return;
	}
	
	switch (p_evt->id)
	{
		case NRF_FSTORAGE_EVT_WRITE_RESULT:
		{
			printf("--> Event received: wrote %d bytes at address 0x%x. \r\n",
			 p_evt->len, p_evt->addr);
		} break;
		
		case NRF_FSTORAGE_EVT_ERASE_RESULT:
		{
			printf("--> Event received: erased %d page from address 0x%x. \r\n",
			 p_evt->len, p_evt->addr);
		} break;
		
		default:
		break;
	}
}

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 = 0x78000, // by 0x800000
    .end_addr   = 0x7F000,
};


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

/**@brief   Helper function to obtain the last address on the last page of the on-chip flash that
 *          can be used to write user data.
 */
static uint32_t nrf5_flash_end_addr_get()
{
    uint32_t const bootloader_addr = NRF_UICR->NRFFW[0];
    uint32_t const page_sz         = NRF_FICR->CODEPAGESIZE;
    uint32_t const code_sz         = NRF_FICR->CODESIZE;

    return (bootloader_addr != 0xFFFFFFFF ?
            bootloader_addr : (code_sz * page_sz));
}

static void print_flash_info(nrf_fstorage_t * p_fstorage)
{
    printf("========| flash info |========\r\n");
    printf("erase unit: \t%d bytes\r\n",      p_fstorage->p_flash_info->erase_unit);
    printf("program unit: \t%d bytes\r\n",    p_fstorage->p_flash_info->program_unit);
    printf("==============================\r\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 flash_test(void)
{//nrfjprog --memrd 0x0007F000 --n 0x70  nrfjprog --memrd 0x10000010 --n 0x10
	ret_code_t rc;
	
	nrf_fstorage_api_t * p_fs_api;
//	static uint32_t pages_to_erase = 1;
	
	NRF_LOG_INFO("SoftDevice is present.");
	NRF_LOG_INFO("Initializing nrf_fstorage_sd implementation...");
	/* Initialize an fstorage instance using the nrf_fstorage_sd backend.
	* nrf_fstorage_sd uses the SoftDevice to write to flash. This implementation can safely be
	* used whenever there is a SoftDevice, regardless of its status (enabled/disabled). */
	p_fs_api = &nrf_fstorage_sd;
	
	rc = nrf_fstorage_init(&fstorage, p_fs_api, NULL);
	APP_ERROR_CHECK(rc);
	
	print_flash_info(&fstorage);
	
	/* It is possible to set the start and end addresses of an fstorage instance at runtime.
	* They can be set multiple times, should it be needed. The helper function below can
	* be used to determine the last address on the last page of flash memory available to
	* store data. */
	(void) nrf5_flash_end_addr_get();
	
	rc = nrf_fstorage_erase(
		&fstorage,   /* The instance to use. */
		fstorage.start_addr,     /* The address of the flash pages to erase. */
		pages_to_erase, /* The number of pages to erase. */
		NULL            /* Optional parameter, backend-dependent. */
	);
	APP_ERROR_CHECK(rc);

	wait_for_flash_ready(&fstorage);
	NRF_LOG_INFO("Done.");
    
	uint8_t    flash_data2[4] = {0};
	rc = nrf_fstorage_read(&fstorage, 0x78100, flash_data2, sizeof(flash_data2));
	APP_ERROR_CHECK(rc);
        printf("\r\nread %s \r\n", flash_data2);
        	    
	/* Let's write to flash. */
	printf("Writing \"%x\" to flash.", m_data);
	rc = nrf_fstorage_write(&fstorage, 0x78100, &m_data, sizeof(m_data), NULL);
	APP_ERROR_CHECK(rc);
	
	wait_for_flash_ready(&fstorage);
	NRF_LOG_INFO("Done.");
                   
}

thanks.

  • Hi,

    I believe you are running into a bug in the SDK. See this post.

    In order to fix the bug you need to move the initialization of p_flash_info outside the if condition in the init() function in the file nrf_fstorage_sd.c

    After you have changed this, the function should look like this:

    static ret_code_t init(nrf_fstorage_t * p_fs, void * p_param)
    {
        UNUSED_PARAMETER(p_param);
    
        p_fs->p_flash_info = &m_flash_info;
    
        if (!nrf_atomic_flag_set_fetch(&m_flags.initialized))
        {
            
    
    #if NRF_SDH_ENABLED
            m_flags.sd_enabled = nrf_sdh_is_enabled();
    #endif
    
            (void) NRF_ATFIFO_INIT(m_fifo);
        }
    
        return NRF_SUCCESS;
    }

  • Hi, Sigurd,

    after modifying the code by referring your information, I can write/read user data,

    I set the start/end address like below, and no set dfu function,

    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 = 0x73000, // by 0x800000
    .end_addr = 0x7d000,
    };

    after setting dfu, I will experiment again tomorrow, and then update the result for you,

    thankful for your support,

    thanks.

  • Hello, Sigurd,

    as promised, I update the test result, it is no problem,

    when setting the start/end address like below, 

    NRF_FSTORAGE_DEF(nrf_fstorage_t fstorage) =//love_0220 DFU_APP_DATA_RESERVED
    {
    /* 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 = 0x60000, // by 0x800000 CODE_PAGE_SIZE * 16
    .end_addr = 0x6f000,
    };

    and then I tried to write/read data in DFU environment,

    m_data = 0x34567891;
    /* Let's write to flash. */
    printf("Writing \"%x\" to flash.", m_data);
    rc = nrf_fstorage_write(&fstorage, 0x6f000 - 0x100, &m_data, sizeof(m_data), NULL);
    APP_ERROR_CHECK(rc);

    wait_for_flash_ready(&fstorage);
    NRF_LOG_INFO("Done.");

    uint8_t flash_data2[256] = {0};
    rc = nrf_fstorage_read(&fstorage, 0x6f000 - 0x100, flash_data2, sizeof(flash_data2));
    APP_ERROR_CHECK(rc);
    printf("\r\nread 0x%x \r\n", flash_data2[0]);
    printf("\r\nread 0x%x \r\n", flash_data2[1]);
    printf("\r\nread 0x%x \r\n", flash_data2[2]);
    printf("\r\nread 0x%x \r\n", flash_data2[3]);

    I think the size of memory that I set in NRF_FSTORAGE_DEF is enough to save my data,

    I only need to upload the application package, 

    and when I check the memory from 0x6f000 to 0x7d000, the memory is already used or I can see the make like "DEADCODE".. so I set my memory like above, how about ? is it no problem?

    after doing dfu, I can write/read the same region with the same data,

    thankful for your support in advance,

    thanks.

  • Hello, Sigurd,

    I experimented fstorage in dfu environment, I can confirm to read / write data after doing DFU with fstorage, after modifying the code of nrf_fstorage_sd.c, I can do it,

    please help to review my settings, I set the start/end address because when I check memory, I can see "DEADCODE" Mark (maybe after 0x6f000). and some region was already used....

    anyway I think that the size of the following setting memory is enough to save my data....

    NRF_FSTORAGE_DEF(nrf_fstorage_t fstorage) =//love_0220 DFU_APP_DATA_RESERVED
    {
    /* 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 = 0x60000, // by 0x800000 CODE_PAGE_SIZE * 16
    .end_addr = 0x6f000,
    };

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    read/write example :

    1)

    m_data = 0x23456781;
    /* Let's write to flash. */
    printf("Writing \"%x\" to flash.", m_data);
    rc = nrf_fstorage_write(&fstorage, 0x6f000 - 0x100, &m_data, sizeof(m_data), NULL);
    APP_ERROR_CHECK(rc);

    wait_for_flash_ready(&fstorage);
    NRF_LOG_INFO("Done.");

    uint8_t flash_data2[256] = {0};
    rc = nrf_fstorage_read(&fstorage, 0x6f000 - 0x100, flash_data2, sizeof(flash_data2));
    APP_ERROR_CHECK(rc);
    printf("\r\nread 0x%x \r\n", flash_data2[0]);
    printf("\r\nread 0x%x \r\n", flash_data2[1]);
    printf("\r\nread 0x%x \r\n", flash_data2[2]);
    printf("\r\nread 0x%x \r\n", flash_data2[3]);

    2)

    NRF_LOG_INFO("Writing \"%s\" to flash.", m_hello_world);
    rc = nrf_fstorage_write(&fstorage, 0x60000 + 0x100, m_hello_world, sizeof(m_hello_world), NULL);
    APP_ERROR_CHECK(rc);

    wait_for_flash_ready(&fstorage);
    NRF_LOG_INFO("Done.");

    uint8_t flash_data[256] = {0};
    rc = nrf_fstorage_read(&fstorage, 0x60000 + 0x100, flash_data, sizeof(flash_data));
    APP_ERROR_CHECK(rc);

    printf("love777 %s \r\n", flash_data);

    thankful for your support...

    thanks.

  • The Peer Manager uses FDS to store bond information, so 3 of the pages below DFU_APP_DATA_RESERVED will be reserved for that. That means that you should be able to store your custom data starting from page 4. If you are using the non-debug bootloader(start at 0x78000), and reserved 16 pages, that means that you have 13 pages to safely store your custom data during a DFU, from start address 0x68000 to end address 0x75000. (0x75000 to 0x78000 is used by Peer Manager/FDS.)

Related