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

Ndef library: multiple records update issue

Hello,

I have multiple records that I want to update during the runtime of the program.

What is working:

1. I can write in memory for the first time initial values.

2. I can update all records and it works.

3. I can load all records and it works.

Problem:

When I update for the first time one of the records. All other records points the same "default" location, like they are de-referenced.

However if I update each record one time, it work fine forever.

#define FILE_ID         0x1111  
#define REC_KEY         0x1908
#define TOTAL_RECORDS       3

static fds_record_desc_t  m_record_desc[TOTAL_RECORDS];
static fds_record_t       m_record[TOTAL_RECORDS];

ret_code_t ndef_file_load(uint8_t * p_buff, uint32_t size, uint8_t id)
{
    ret_code_t         err_code;
    fds_find_token_t   ftok;
    fds_flash_record_t flash_record;

    // Always clear token before running new file/record search.
    memset(&ftok, 0x00, sizeof(fds_find_token_t));

    // Search for NDEF message in FLASH.
    err_code = fds_record_find(FILE_ID, REC_KEY+id, &m_record_desc[id], &ftok);

    // If there is no record with given key and file ID,
    // create default message and store in FLASH.
    if (err_code == NRF_SUCCESS)
    {
        NRF_LOG_INFO("Found NDEF file record for id %d", id);

        // Open record for read.
        err_code = fds_record_open(&m_record_desc[id], &flash_record);
        VERIFY_SUCCESS(err_code);

        // Access the record through the flash_record structure.
        memcpy(p_buff,
               flash_record.p_data,
               flash_record.p_header->length_words * sizeof(uint32_t));

        // Print file length and raw message data.
        NRF_LOG_DEBUG("NDEF file data length: %u bytes.",
                      flash_record.p_header->length_words * sizeof(uint32_t));

        NRF_LOG_HEXDUMP_DEBUG(p_buff, flash_record.p_header->length_words * sizeof(uint32_t));

        // Close the record when done.
        err_code = fds_record_close(&m_record_desc[id]);
    }
    else if (err_code == FDS_ERR_NOT_FOUND)
    {
        NRF_LOG_INFO("NDEF file record not found, default NDEF file created.", err_code);

        // Create default NDEF message.
        ndef_file_default_message(p_buff, size, id);

        // Create record with default NDEF message.
        err_code = ndef_record_create(p_buff, size, id);
    }

    return err_code;
}

static void ndef_file_default_message(uint8_t * p_buff, uint32_t p_size, uint8_t id)
{
    for(int i=0; i<p_size; i++)
    {
        p_buff[i] = 0xFF;
    }
}

static void ndef_file_prepare_record(uint8_t const * p_buff, uint32_t size, uint8_t id)
{
    // Set up record.
    m_record[id].file_id           = FILE_ID;
    m_record[id].key               = REC_KEY + id;
    m_record[id].data.p_data       = p_buff;
    m_record[id].data.length_words = BYTES_TO_WORDS(size); // Align data length to 4 bytes.
}

static ret_code_t ndef_record_create(uint8_t const * p_buff, uint32_t size, uint8_t id)
{
    ret_code_t err_code;

    // Prepare record structure.
    ndef_file_prepare_record(p_buff, size, id);

    err_code = fds_record_write(&m_record_desc[id], &m_record[id]);
    VERIFY_SUCCESS(err_code);

    return err_code;
}

ret_code_t ndef_file_update(uint8_t const * p_buff, uint32_t size, uint8_t id)
{
    ret_code_t err_code;

    // Prepare record structure.
    ndef_file_prepare_record(p_buff, size, id);

    // Update FLASH file with new NDEF message.
    err_code = fds_record_update(&m_record_desc[id], &m_record[id]);
    VERIFY_SUCCESS(err_code);

    return err_code;
}

Records are stored in a static fds_record_t array and they got their own individual key.

Any idea on the direction to explore ?

Thanks

  • Hi,

    I am having problems getting a full understanding. Can you elaborate a bit, and perhaps show us your code?

  • Hi,

    I do not see anything problematic in the code snippet. Your ndef_file_update() only modifies the element given by "id" of m_record_desc and m_record, and fds_record_update() will not change any other record. The only thing it will do is write a new record with the same key and file ID as the old (but with new content), and mark the old as dirty. Existing records will not be touched, and will remain in the same flash location until garbage collection is performed.

    Can you make a more complete example that demonstrates the issue that I can run on a DK on my side?

  • 1. In an init function called once before the main loop, you load the data stored in flash. If the records are already there, then they are loaded, otherwise a default value is written in flash with value 0xFF * size of the data.

    2. Now let's say that the memory was empty, now we have 3 records like this in memory:

    uint8_t data1 = 0xff;
    uint16_t data2 = 0xffff;
    uint8_t data_array[3] = {0xff,0xff,0xff};

    3. I want to update data1:

    static buffer_for_data1[1];
    
    data1 = 0x69;
    
    buffer_for_data1[0] = data1;
    ndef_file_update(buffer_for_data1, 1, record_id_of_data1);

    4. if I load data1 I get the correct value:

    data1 = 0;
    
    uint8_t load_buffer[1];
    
    rc = ndef_file_load(load_buffer, 1, record_id_of_data1);
    
    data1 = load_buffer[0]; // now we get data1 = 0x69 which is correct

    5. If I now load data2 and data_array, I get a wrong value:

    // loading data2 and data_array:
    
    data2 = 0x0434; // wrong! expecting 0xFFFF
    data_array = 0x043412 // wrong! expecting 0xFFFFFF

    6. If I update data2 and data_array, every thing is fine, no more error.

  • I fail to see the logic. Can you make a simple (but complete) that reproduces this that I can test?

Related