Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

FDS read returns junk

I have a BLE application I'm writing using SDK17.0.2, and want to use FDS for some persistent storage. The first thing I want to do is to allow the user to update the name of the device when it is advertising. I have an API call over bluetooth where the new name is given, and it calls the FDS subsystem to store that name, and then later retrieve it.

I use fds_record_find to see if the record already exists. If not, I create it with the name. if it does, I update it with the new name. The fds_record_write, and cds_record_update seem to work. I see the event handler being called with NRF_SUCCESS, and I can see in the details that if I have created it, it will have a record ID of 1, and then every time I update it I can see the record_id increments. So it sure as heck seems like it is working.

If I try and delete it after doing an fds_record_find, I get a successful delete (see it in the event handler). And then I can see if I go to write it again after deletion, it creates the record (as opposed to updating). So it seems like delete is working.

If I go to read the record before I have written it, the read fails (as expected). It says it can't find the ID.

so far, so good.

However, after writing (or updating), and going to read, I will get a successful read (the find works), and then I call fds_record_open.

However, the data that is in that record is complete garbage. It is not what I wrote. It is just random seeming bytes. If I then close it, and call write again (to update it), and then read it back, I get a *different* bunch of garbage back.

So it is telling me it is writing/updating/deleting successfully, but when I read a record that is there, it's garbage. The read data is in fds_flash_record_t object's "p_data" field.

I based my code on the writable_ndef_msg example, but instead of using NFC to trigger creating, reading, and updating, I am doing it via bluetooth commands to my custom characteristic.

What the heck am I doing wrong? how can I be told that the write, update, and delete work, the read is "successful", but the read data is garbage?

In my example, I'm writing the string ABCDEFG (so 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47), but I'm getting absolute random crap back. Every time I will write this same string, and then every time the read is a different set of garbage. If I write it, then every read after that is one set of garbage. If I update it (or delete and recreate it), the garbage I read back is different from the previous garbage.

Parents
  • Note that I am waiting to do the read until AFTER I get the event that says the write is successful.  I even tried doing a garbage collection after the write was successful, and waited for THAT to finish before doing the read.  it's as if the write data just never gets written, but "something" is written, or the pointer to say it's been written has been updated.  but no data.

  • Latest update:  If I turn on CRC checking for writes and reads in sdk_config.h (FDS_CRC_CHECK_ON_READ and FDS_CRC_CHECK_ON_WRITE set to '1'), things get extremely ugly.  I get return code on the read of 34316 (860C) which is an unknown code on the read.  and I have an app_error_check set on that, so the application crashes.  so, clearly CRC is bad to do given whatever else is wrong.


  • Writing. First, see if it exists.

    Code:
    fds_record_t const fds_record = {
    .file_id = tag,
    .key = tag,
    .data.p_data = data,
    .data.length_words = ((uint32_t) length + 3) / sizeof(uint32_t), // The length of a record is always expressed in 4-byte units (words).
    };

    ret_code_t rc = fds_record_find(tag, tag, &desc, &tok);

    Log:
    <I> app: Data NOT found. Write it. Length = 16

    It doesn't find it, so I go to write it (as opposed to update it)

    Code:
    rc = fds_record_write(&desc, &fds_record);

    Resulting Log:
    <I> app: 41 42 43 44 45 46 47 00|ABCDEFG.
    <I> app: 00 00 00 00 00 00 00 00|........
    <I> app: liv_ble_custom_char_completion (livotalCommandsWriteID)
    <I> app: Success

    Result of the event handler:
    <I> app: FDS_EVT_WRITE: Record ID: 0x1
    <I> app: FDS_EVT_WRITE: File ID: 0x8AE
    <I> app: FDS_EVT_WRITE: Record key: 0x8AE

    Many seconds later (command has to come over bluetooth, and is sent via a command from my mobile app):

    Coed:
    ret_code_t rc = fds_record_find(tag, tag, &desc, &tok); >

    Resulting Log:
    <I> app: Try to find tag 2222 with length 16
    <I> app: (Read) FOUND!
    <I> app: (Read) Run Count: 0
    <I> app: (Read) Record ID: 1
    <I> app: (Read) p_record: 1040448
    <I> app: (Read) Record is open: 0

    Since the find was successful, go to open it:

    Code:
    fds_flash_record_t flash_record = {0};
    rc = fds_record_open(&desc, &flash_record);

    This results in NRF_SUCCESS. here is the resulting log.

    First, I dump the info from the flash_record.p_header:

    Log:
    <I> app: (Read) RECORD KEY: 2222
    <I> app: (Read) LENGTH WORDS: 4
    <I> app: (Read) FILE ID: 8AE
    <I> app: (Read) CRC16: 0
    <I> app: (Read) RECORD ID: 1

    Then I dump the flash_record.p_data -> AND IT IS GARBAGE!!!!
    <I> app: Flash record p_data:
    <I> app: 47 50 01 00 00 0B 00 20|GP.....
    <I> app: 00 00 00 00 00 00 00 00|........

  • How have you declared the data you want to store? E.g. do you ensure it's 'static' so that the memory is not optmized and re-used by the compiler before it may be written to flash?

    Kenneth

  • OMG, major face palm.  I can't believe I did something this... basic.  Thank you, Kenneth!

Reply Children
No Data
Related