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

FDS Write: Wrong Written Data

Good Afternoon,

I'm writing some config data on an empty record the first time I turn on my board and updating that same record every next time I turn on the board.

While the writing of the first data is correctly written with fds_record_write() - when I check the data with fds_record_open() -, the data is totally wrongly written when I update the record with new config data, with fds_record_update().

When the board initialises I initialise FDS and call flash_write_record_setup(&DEVICE_struct_w_config2write) after initialising the softdevice.

By looking into the code below, do you have any cue why the data is not correctly written when I update the record?

Thank you,

João Oliveira

/* Declarations in flash.h */

/* File ID and Key used for the configuration record. */

#define CONFIG_FILE     (0xF010)
#define CONFIG_REC_KEY  (0x7010)

typedef struct
{
	uint8_t enable;
	uint8_t time_adv;
}ADVERTISE;

typedef struct
{
	uint8_t state;
	ADVERTISE adv2;
}DEVICE;

/* flash_write_record_setup function in flash.c */

void flash_write_record_setup(DEVICE * config2write)
{
    ret_code_t rc;

    fds_record_desc_t desc = {0};
    fds_find_token_t  tok  = {0};

    //CONFIG_FILE and CONFIG_REC_KEY defined in flash.h
    rc = fds_record_find(CONFIG_FILE, CONFIG_REC_KEY, &desc, &tok);

    if (rc == FDS_SUCCESS) //record exists => update it
    {
        /* A config file is in flash. Let's update it. */
        fds_flash_record_t config = {0};

        /* Open the record and read its contents. */
        rc = fds_record_open(&desc, &config);
        APP_ERROR_CHECK(rc);

        /* Close the record when done reading. */
        rc = fds_record_close(&desc);
        APP_ERROR_CHECK(rc);
 
        //compare existing config in flash with new one
        uint8_t ret = memcmp(config2write, config.p_data, sizeof(DEVICE));

        if(ret != 0) //if different update config in flash
        {
            /* Write the updated record to flash. */
			fds_record_t const rec =
			{
				.file_id           = CONFIG_FILE,
				.key               = CONFIG_REC_KEY,
				.data.p_data       = config2write,
				.data.length_words = (sizeof(DEVICE) + 3) / sizeof(uint32_t)
			};

            rc = fds_record_update(&desc, &rec);
            APP_ERROR_CHECK(rc);

            m_write_finished = false;
        }
        else
        {
            /* Same config data as previous, nothing to be done */
        }
    }
    else  /* System config not found; write a new one. */
    {
        fds_record_t const rec =
        {
            .file_id           = CONFIG_FILE,
            .key               = CONFIG_REC_KEY,
            .data.p_data       = config2write,
            .data.length_words = (sizeof(DEVICE) + 3) / sizeof(uint32_t)
        };

        rc = fds_record_write(&desc, &rec);
        APP_ERROR_CHECK(rc);

        m_write_finished = false;
    }
}

Parents
  • Hi again Rune,

     

    After struggling a lot I just found out that the problem occurs when I try to write any userid string that has a number of bytes multiple of 4 (that is 4bytes, 8bytes, 12bytes, etc). It writes without any error but when I try to read that flash data afterwards the app gets stuck without reporting erros.

    I found it very weird and tested it then in the flash_fds example directly and the same issue occurs.

    Just try to write any multiple of 4 bytes string with the command "write fid key "multiple_of_4_bytes_string"" and then read the data by calling the "print all" command but with a NRF_LOG_INFO("%s", (char*)frec.p_data) line (or any other line that makes use of frec.p_data) inside the print_all_cmd function.

     

    I guess this is a very weird bug in the FDS API that might be related to word-unalignment in flash.

     

    Looking forward to hear about your clarification about this issue,

    Best regards,

    João

  • Hi,

    Very sorry for the late reply.

    I have tried reproducing this issue as you described, but there seems to be no problem writing the string to flash and reading it back. I added the log statement as you described and wrote the string and read it back without any issues. I performed my test on SDK 15.

    I also discussed the issue with one of the developers working on FDS, and he was not familiar with the issue you are describing. Am I understanding it correctly, you are not getting any error while writing the record, but when you read it back it's not working as expected?

    Any information you have which may help us recreating the issue is very welcome.

    Best regards,
    Rune Holmgren

  • Hi Rune,

    What I meant is for you to please to consider writing a string with 4 bytes, such as "test" or "test1234".

    When reading it back and printing frec.p_data as you did with print all it should halt the application - at least on my side it does, everytime.

    Thank you again,

    João

  • Sorry, I should have realized this when first looking at your post. The problem is not the flash, but rather that you are trying to print strings which are not null terminated.

    The reason you are successfully able to write and later print strings that are not a length divisible by 4 is that the flash memory will be padded with '0's. When you write "tes" to flash, the actual flash will be padded with a 0 byte at the end. In flash the following values will be present [116, 101, 115, 0]. To C this is the string "tes" with the final byte telling sprintf that the string has ended. When you write the string "test" to flash, the actual content of flash will be [116, 101, 115, 116] with no null terminator. When you send a reference to this flash address to the logging framework, nrf_log will attempt to print all the bytes it can find until a '0' is found. This may be an incredibly long string and the buffers overflow and cause the device to hang.

    To resolve the issue, simply ensure that the data you are writing to flash is either null terminated, or that you add a null terminator after reading it out.

    In this image, I have changed the printing to print specifically the first 4 characters present in flash. As you can see the word "test" is present, but there is no null terminator. You can't send this string as is to sprintf without adding a null terminator.

    Best regards,
    Rune Holmgren

Reply Children
No Data
Related