This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

fstorage read and write failures

Hello, 

I am figuring out the fstorage functionality and I'm running basic example flash_fstorage from SDK 17.1.0 on my nRF52-DK. And I got the issues just on start.

At first, there the cli commands didnt work:  read hex 0x3e000 4 didn't return 0xBADC0FEE or whatever, but instead some nonsense like "0xFE 0xF 0xDC 0xBA 0xFF"

Then I tried to look around and found similar issues in the DevZone:

I added the waiting function wait_for_flash_ready() after all my operations, and it didn't help.

I changed my NRF_FSTORAGE_SD_MAX_WRITE_SIZE to 256 and increased NRF_FSTORAGE_SD_MAX_RETRIES to 16. Didn't help.

Then I read somewhere that I need to erase the page before any writing cycle, but it didn't help either. So, I'd be helpful for an advice on what to try next. 

My current code in main is:

int main(void)
{
    ret_code_t rc;
    uint8_t    data[32] = {0};

#ifndef SOFTDEVICE_PRESENT
    clock_init();
#endif

    timer_init();
    log_init();
    cli_init();

    NRF_LOG_INFO("fstorage example started.");

    nrf_fstorage_api_t * p_fs_api;

#ifdef SOFTDEVICE_PRESENT
    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;
#else
    NRF_LOG_INFO("SoftDevice not present.");
    NRF_LOG_INFO("Initializing nrf_fstorage_nvmc implementation...");
    /* Initialize an fstorage instance using the nrf_fstorage_nvmc backend.
     * nrf_fstorage_nvmc uses the NVMC peripheral. This implementation can be used when the
     * SoftDevice is disabled or not present.
     *
     * Using this implementation when the SoftDevice is enabled results in a hardfault. */
    p_fs_api = &nrf_fstorage_nvmc;
#endif

    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();

    /* Erasing some flash pages */
    rc = nrf_fstorage_erase(&fstorage, 0x3e000, 1, NULL);
    APP_ERROR_CHECK(rc);
    wait_for_flash_ready(&fstorage);
    NRF_LOG_INFO("Erasing Done.");

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

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

#ifdef SOFTDEVICE_PRESENT
    /* Enable the SoftDevice and the BLE stack. */
    NRF_LOG_INFO("Enabling the SoftDevice.");
    ble_stack_init();

    m_data = 0xDEADBEEF;

    NRF_LOG_INFO("Writing \"%x\" to flash.", m_data);
    rc = nrf_fstorage_write(&fstorage, 0x3e100, &m_data, sizeof(m_data), NULL);
    APP_ERROR_CHECK(rc);

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

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

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

    /* Read data. */
    rc = nrf_fstorage_read(&fstorage, 0x3e000, data, sizeof(data));
    APP_ERROR_CHECK(rc);
    NRF_LOG_INFO("1. Reading from Flash: %X", data);
    
    wait_for_flash_ready(&fstorage);    
    rc = nrf_fstorage_read(&fstorage, 0x3e100, data, sizeof(data));
    APP_ERROR_CHECK(rc);
    NRF_LOG_INFO("2. Reading from Flash: %X", data);
    
    wait_for_flash_ready(&fstorage);
    rc = nrf_fstorage_read(&fstorage, 0x3f000, data, sizeof(data));
    APP_ERROR_CHECK(rc);
    NRF_LOG_INFO("3. Reading from Flash: %s", data);

    NRF_LOG_INFO("Use 'read' to read bytes from the flash.");
    NRF_LOG_INFO("Use 'write' to write bytes to the flash.");
    NRF_LOG_INFO("Use 'erase' to erase flash pages.");
    NRF_LOG_INFO("Use 'flasharea' to print and configure the flash read boundaries.");

    cli_start();

    /* Enter main loop. */
    for (;;)
    {
        if (!NRF_LOG_PROCESS())
        {
            power_manage();
        }
        cli_process();
    }
}

and my debug output is the following:

<info> app: fstorage example started.
<info> app: SoftDevice is present.
<info> app: Initializing nrf_fstorage_sd implementation...
<info> app: ========| flash info |========
<info> app: erase unit:         4096 bytes
<info> app: program unit:       4 bytes
<info> app: ==============================
<info> app: --> Event received: erased 1 page from address 0x3E000.
<info> app: Erasing Done.
<info> app: Writing "BADC0FFE" to flash.
<info> app: --> Event received: wrote 4 bytes at address 0x3E000.
<info> app: Done.
<info> app: Enabling the SoftDevice.
<info> app: Writing "DEADBEEF" to flash.
<info> app: --> Event received: wrote 4 bytes at address 0x3E100.
<info> app: Done.
<info> app: Writing "hello world" to flash.
<info> app: --> Event received: wrote 12 bytes at address 0x3F000.
<info> app: Done.
<info> app: 1. Reading from Flash: 2000FFB0
<info> app: 2. Reading from Flash: 2000FFB0
<info> app: 3. Reading from Flash: hello world
<info> app: Use 'read' to read bytes from the flash.
<info> app: Use 'write' to write bytes to the flash.
<info> app: Use 'erase' to erase flash pages.
<info> app: Use 'flasharea' to print and configure the flash read boundaries.

As you can see the read outputs are not what was expected.  

  • Hi,

    The problem here is how you are reading from flash. Where you print 2000FFB0, that is the address where the data is located (so you are printing the pointer value and not what it points to). If you instead print the array like this you will get the raw data (no need to print the whole array, but just doing it for simplicity):

        NRF_LOG_INFO("1. Reading from Flash:");
        NRF_LOG_HEXDUMP_INFO(data, sizeof(data));

    Making this change for 1 and 2 the resulting output is this, which is correct:

    <info> app: fstorage example started.
    <info> app: SoftDevice is present.
    <info> app: Initializing nrf_fstorage_sd implementation...
    <info> app: ========| flash info |========
    <info> app: erase unit:         4096 bytes
    <info> app: program unit:       4 bytes
    <info> app: ==============================
    <info> app: --> Event received: erased 1 page from address 0x3E000.
    <info> app: Erasing Done.
    <info> app: Writing "BADC0FFE" to flash.
    <info> app: --> Event received: wrote 4 bytes at address 0x3E000.
    <info> app: Done.
    <info> app: Enabling the SoftDevice.
    <info> app: Writing "DEADBEEF" to flash.
    <info> app: --> Event received: wrote 4 bytes at address 0x3E100.
    <info> app: Done.
    <info> app: Writing "hello world" to flash.
    <info> app: --> Event received: wrote 12 bytes at address 0x3F000.
    <info> app: Done.
    <info> app: 1. Reading from Flash:
    <info> app:  FE 0F DC BA FF FF FF FF|........
    <info> app:  FF FF FF FF FF FF FF FF|........
    <info> app:  FF FF FF FF FF FF FF FF|........
    <info> app:  FF FF FF FF FF FF FF FF|........
    <info> app: 2. Reading from Flash:
    <info> app:  EF BE AD DE FF FF FF FF|........
    <info> app:  FF FF FF FF FF FF FF FF|........
    <info> app:  FF FF FF FF FF FF FF FF|........
    <info> app:  FF FF FF FF FF FF FF FF|........
    <info> app: 3. Reading from Flash: hello world
    <info> app: Use 'read' to read bytes from the flash.
    <info> app: Use 'write' to write bytes to the flash.
    <info> app: Use 'erase' to erase flash pages.
    <info> app: Use 'flasharea' to print and configure the flash read boundaries.

  • Hello Einar, thanks for the explanation!

    How do I keep the data from the flash in my variable for further use? Is it enough to to keep the line:

    rc = nrf_fstorage_read(&fstorage, 0x3e000, data, sizeof(data));

  • To be honest, the nrf_fstorage_read() is a bit useless. It is reading from normal flash after all, and is just a memcpy. If you have (say) a uint32_t at address 0x3e000 then it would be easier to just make a pointer to that location. Something like this:

    uint32_t * p_data = (uint32_t *)0x3e000;

    and read the data like:

    *p_data

Related