Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
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

FDS: Updating existing records with fds_record_update fails on re-flash/reset

Hi,

I am using the FDS API to perform operations on flash. What I intend to achieve is: A zero initialised array like data structure in the flash. Initially zeroes are written to a fixed region in the flash later on valid data is updated using FDS API. Just like zero initialisation of array in C, but in this case I am zero initialising a region of the flash. 

Zero initialisation:

#define SIZE 5

# This block of code is called only once after initialising the FDS.

fds_file_delete(FILE_ID);
fds_gc();
for (uint16_t key = 0x0001; key < SIZE; key++) {
	record.file_id		 = FILE_ID;
	record.key		 = key;
	record.data.p_data	 = "0";
	record.data.length_words = 1;

	fds_record_write(&record_desc, &record);
}

Update:

record.file_id = FILE_ID;
record.key = 0x0001;
record.data.p_data = &m_hello; //Global char array
record.data.length_words = sizeof(m_hello);

memset(&ftok, 0x00, sizeof(fds_find_token_t));
fds_record_find_by_key(0x0001, &record_desc, &ftok);
fds_record_update(&record_desc, &record);


Read:

fds_record_find_by_key(0x0001, &record_desc, &ftok);
fds_record_open(&record_desc, &flash_record);


What I notice is, update works fine when Soft device is disabled (I don't use nrf_sdh_enable_request() and no observers are initalised)

But when I enable the Soft device, the update works on the first instance of flashing the soft device and the user application. On subsequent resets or flashing the soft device and the user app when I read the output is always "0", while I expect the output to be the updated data. 

How I enable the Soft Device:

#define OBSERVER_PRIO 1

bool request_evt_handler(nrf_sdh_req_evt_t request, void * p_context)
{
    switch (request)
    {
        case NRF_SDH_EVT_ENABLE_REQUEST:
            break;
        case NRF_SDH_EVT_DISABLE_REQUEST:
            break;
    }
    return true;
}

NRF_SDH_REQUEST_OBSERVER(m_req_observer, OBSERVER_PRIO) =
{
    .handler   = request_evt_handler,
    .p_context = NULL
};

uint32_t soft_dev_enable(void)
{
	ret_code_t ret;
	uint32_t ram_start;

	ret = nrf_sdh_enable_request();
	VERIFY_SUCCESS(ret);
	if (!nrf_sdh_is_enabled()) {
			NRF_LOG_INFO("Failed to enable SD");
	}

	return 0;
}

sdk_config.h:

#define NRF_SDH_ENABLED 1
#define NRF_SDH_SOC_ENABLED 1
#define FDS_BACKEND 2


In short:

1. Write to flash using fds_record_write()

2. Update record at same key using fds_record_update()

3. Read record at same key using fds_record_find_by_key, fds_record_open

4. Flash once, update works as expected. After reflashing/resetting device update doesn't work


Soft device enabled: 
Above sequence 1-3 works when device is flashed for first time, output is as expected. Subsequently flashing/reseting device the output is not as expected.

Soft device disabled: Works always. 

I am not sure how FDS works when Soft Device is not enabled but this is what I experienced.

A similar issue is discussed here

Development environment:

1. NRF52833 DK
2. SDK version:: 17.1.0

  • Hello,

    The softdevice flash API used by the fstorage backend becomes asynchronous once the Softdevice is enabled, not blocking as it is when the Softdevice is disabled. This basically means the actual flash operation (erase or write) initiated by FDS will first be added to a scheduler queue before it gets executed (Using flash with the Softdevice enabled).

    The completion of a scheduled flash operation is signaled to the application through the Softdevice NRF_EVT_FLASH_OPERATION_SUCCESS or the NRF_EVT_FLASH_OPERATION_ERROR event.

    But when I enable the Soft device, the update works on the first instance of flashing the soft device and the user application. On subsequent resets or flashing the soft device and the user app when I read the output is always "0", while I expect the output to be the updated data. 

    Can you place a breakpoint in nrf_fstorage_sd.c::nrf_fstorage_sys_evt_handler() to see if it receives the SoC events from the Softdevice? Also, have you included the nrf_sdh_soc.c file in your project? This is the file responsible for propagating SoC events to the registered SoC observers (SoftDevice Handler library).

    Best regards,

    Vidar

  • Hi, 

    Thank you for your timely response. I had the nrf_sdh_soc.c file in my project. Also the issue was I wasn't aware of the write, read, update being asynchronous when soft device is enabled. I added a wait for the write and update to finish as described here and update worked as expected with the soft device enabled on multiple boots. 

    Sorry about that. 

    If possible can you suggest me the best way to wait for the write/update event completion, because I want to write to the flash when a button press event is triggered. 
    This button press event is valid only when the button is held for more than 3 seconds, I am achieving the same using app_timer_* functionality. So right now I have the button press logic ready and if I call the fds_record_write() when the button is pressed for more than 3 seconds, I don't see any log messages or anything further. The application code seems to stop. 

    Hence I would be happy if you guide me on different ways to wait for the async event to complete such that a button press is able to write to flash or a BLE EVT writes/updates/reads from flash.

  • Hi,

    No problem Slight smile

    iamkkushal said:
    If possible can you suggest me the best way to wait for the write/update event completion, because I want to write to the flash when a button press event is triggered. 

    It's generally not necessary to insert a wait function for the write/update to complete as the FDS module can queue up multiple write and update tasks (queue size defind by FDS_OP_QUEUE_SIZE). You will get the FDS callback for each write/update that is completed. 

    iamkkushal said:
    So right now I have the button press logic ready and if I call the fds_record_write() when the button is pressed for more than 3 seconds, I don't see any log messages or anything further. The application code seems to stop. 

    The FDS callback will become blocked if you have place the wait function inside an interrupt.

  • Alright, I think I got it. Thank you for helping me out.

Related