Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

fstorage_read and coordination with the Softdevice

nrf52832

SDK 14.2

NVMC and SD backend both

Hi,

I had a question about the nrf_fstorage_read function. In a previous answer, it was mentioned that fstorage_read function is blocking. I would like to know a few
more details about this:

Q1. It was mentioned: "Read operations are implemented using memcpy function, and will block until read is completed." What is meant by block here? If I call fstorage_read, will it really block the CPU
and no other instructions can be performed until the data is read?(even in the SoftDevice backend)

Q2. With the Softdevice backend, if I call fstorage_write, it will break the large write into smaller writes that will be coordinated between NVM and the Radio. Now if I call
fstorage_read when this coordination is going on, I could read NVM and then get interrupted to write to NVM and then come back again into the read. The data read could not be different from
the data in NVM?

Q3. fstorage_read by itself just calls memcpy and doesn't really do any coordination. It is not even queued. So can this be a problem? The smaller writes can occur during fstorage_read and we
could read data that is not actually the real data?

Thanks.

  • Hi,

    One thing one must understand is that the NVMC backend is synchronous and the SD is asynchronous. So if you use the NVMC backend, all your calls to read and write functions will be executed sequentially one after another. In other words, given this code:

    fstorage_write();
    fstorage_write();

    the call to fstorage_write() at line 1 will complete the entire write operation before your application can move on to the second line of code. 

    The SD backend on the other hand is asynchronous, meaning that given the code above, the call to fstorage_write() at line 1 completes immediately and leaves it up to the Softdevice to handle the write operation. When the operation completes you will get a NRF_FSTORAGE_WRITE_RESULT event returned from the Softdevice. If you call fstorage_write() twice one after another as in the code above, the first write operation will not be able to complete and you might run into trouble. What you need to do is to make sure that all fstorage operations are completed before you proceed with the next one. 

    fstorage_write();
    // Wait for the NRF_FSTORAGE_WRITE_RESULT 
    fstorage_write();

     

    The explanation above assumes that you are not starting any fstorage operations from interrupt contexts. If you an interrupt should happen to start an fstorage operation while another one is already in progress you will run into trouble again. As you say, it could e.g. lead to sections of data being overwritten while you are reading. To avoid this you should use a scheduler or flags in your interrupts to make sure to process all fstorage operations from your main context. 

    EDIT 22.03.2018: fstorage_write() instead of fstorage_read() for better example. 

  • Hi MartinBL.

    Thanks for your response. But looking at the nrf_fstorage_sd.c file, it does not seem like that the nrf_fstorage_read(..) operation is handled by the SoftDevice. The read implementation for the NVMC backend and the SD backend are both the same so it doesn't seem like the SD is coming into play for the read operation.

    Also, if you look at the code for the event_send routine in nrf_fstorage_read(..) for the SD backend, it never sends a NRF_FSTORAGE_EVT_READ_RESULT as you mentioned. It only sends results for write and erase events. So if I do call nrf_fstorage_read(..), I will never get a NRF_FSTORAGE_EVT_READ_RESULT on completion because its not even part of the code!

    Please let me know.

    Thanks!

  • Hi

    fstorage_read() was a bad example. The function is indeed always synchronous, is not being handled by the Softdevice, and does not produce any events. I should have used fstorage_write() as an example instead. I'm not sure why the NRF_FSTORAGE_EVT_READ_RESULT event is included in the SDK and documentation at all. I'll take it up with the SDK team. 

    Anyway, my point above regarding interrupt priorities and contexts still stands. Always make sure that your interrupts never start fstorage operations directly. You should rather make them schedule the operations to be executed in the main context after the interrupt is completed. 

  • Thanks Martin. I'll do that. But I had another question regarding your example about:

    fstorage_write()
    fstorage_write()

    You said the first write would not be able to complete if I call fstorage_write() like this one after another. But don't these fstorage_write() calls just get added into a queue and the SD/Fstorage takes care of them when it can?

    For example, if I call fstorage_write() it will go into the queue and then I call fstorage_write() again that will go into the queue as well. Fstorage/SD will complete these requests when it can. Waiting for the callback will only tell me when its complete.

    I thought if they are getting queued I don't need to wait till one gets complete
    and only then issue a second fstorage_write() request. I could call fstorage_write() one after another and as long as the queue is not full, these operations will get added into the queue
    and will be serviced when fstorage/sd decides. So why would waiting for one to complete before another fstorage_write() is called be an issue?

    Thank you for your help Martin!

Related