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

Problems with using Flash and fstorage

I am playing with flash and fstorage lib. I finally got it up and running - I can write and read to flash without having fatal errors. But it's not working as expected. I write "hello world" to 0x3E000 and right after I read some crappy string from that address.

So I tried the flash_fstorage example, compiled and run and I can see the same behaviour. See the output from the logs:

What is going wrong? Do I have my flash somehow corrupted?

Thank you.

EDIT 1:

I tested with another board. I erased the memory (make erase) and then flashed and run the flash_fstorage. The result is the same, only the string that I read back is different: "hL(o world".

EDIT 2:

nrf_fstorage_write() fires a NRF_FSTORAGE_EVT_WRITE_RESULT event which I can handle with evt_handler() from NRF_STORAGE_DEF. But nrf_fstorage_read() DOES NOT fire any event of this type - the evt_handler is not called. Why?

This is my evt_handler implementation:

  switch (p_evt->id) {
    case NRF_FSTORAGE_EVT_WRITE_RESULT:
      NRF_LOG_INFO("--> storage 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("--> storage 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("--> storage Event received: erased %d page from address 0x%x.", p_evt->len, p_evt->addr);
    break;
    default:
      NRF_LOG_INFO("--> storage Event received: unknown action %d, %d page @ address 0x%x.", p_evt->id, p_evt->len, p_evt->addr);
    break;
  }

Parents
  • FormerMember
    0 FormerMember

    The reason for this behavior is the following: When flash is erased, all bits in flash is set to '1'. Writing to flash consists of setting the necessary bits to '0'. Setting bits back to '1' can only be done by erasing the flash page.

    When the "flash_fstorage" example runs, it starts by writing 0xBADCOFFE to address 0x3E000 and "hello world" to address 0x3F000.

    If you then try to write "hello world" to address 0x3E000, the necessary bits at that address will be set to '0'. Some of them will already be '0', and some new ones will have to be switched. In addition, some bits that should be '1' will also be '0', because 0xBADCOFFE is already written there. Therefore, if you then read 11 bytes starting from 0x3E000, the "hello world" string will be "corrupted".

  • Well, ok, thank you for the clarification. But isn't this:

    • bug in the fstorage library?
    • imperfection in the flash_fstorage example? If it is needed to do something special for the secure write, the example should explain this.

    As a non-expert user of a lib I would expect "standard" behaviour - when I write some value to the flash then all bits will be set as necessary.

    What is the solution now for my problem? Do I have to erase the data each time I'm going to write something? Is it possible to erase arbitrary amount of bits/bytes? E.g. when I want to write some 6 bytes then I will erase only those 6 bytes?

    And why is not the NRF_FSTORAGE_EVT_READ_RESULT event fired when I do the nrf_fstorage_read()? See the "EDIT 2" in the original question.

Reply
  • Well, ok, thank you for the clarification. But isn't this:

    • bug in the fstorage library?
    • imperfection in the flash_fstorage example? If it is needed to do something special for the secure write, the example should explain this.

    As a non-expert user of a lib I would expect "standard" behaviour - when I write some value to the flash then all bits will be set as necessary.

    What is the solution now for my problem? Do I have to erase the data each time I'm going to write something? Is it possible to erase arbitrary amount of bits/bytes? E.g. when I want to write some 6 bytes then I will erase only those 6 bytes?

    And why is not the NRF_FSTORAGE_EVT_READ_RESULT event fired when I do the nrf_fstorage_read()? See the "EDIT 2" in the original question.

Children
  • FormerMember
    0 FormerMember in reply to Dusan Daniska
    1. No, it is not a bug in the fstorage library, it is how flash works (bits can only be reset by erasing the flash page they are located in.)
    2. To get around/avoid this problem, the solution is to use FDS.

    The reason that NRF_FSTORAGE_EVT_READ_RESULT never occurs, is that it is never sent, see the read() function in nrf_fstorage_nvmc.c.

     

  • Dusan,

    You will need to keep an image of your Flash page in RAM (like an array, or structure).  Then, when you write to a section of that Flash page you will need to:

    1. First, update the image in RAM with the new data.

    2. Erase your whole Flash page.

    3. Write the updated RAM image to Flash.

    Like Kristin pointed out, this is how Flash works.  You may also create your own middleware "write_to_Flash()" function that does all of these 3 steps in one call.

    Cheers,

    Gil

Related