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

Problem with fds: Flash read, write, delete calling that function using android phone.

Hello to all,

I am using nRF52832 DK with sd132, v6.0.0 and sdk 15.0.0, segger embedded studio. We want to achieve change application timer time (APP_TIMER_TICKS(update_time)) using android phone. We have a sensor devices it will wake up as per app timer time defined, we want to change this wake up time using Noridc UART tool box app. For that we are using fds example as referred in given sdk 15.0 and other nRF5-flash-storage-examples .

We are able to flash write read and delete but problem is:

  1.  When i call fds_test_find_and_delete(), fds_test_write(), fds_read() whenever received command from nordic UART app it not able to read and write at this time.
  2. I want to change update_time variable of app timer ticks using android phone and store this time in flash. Whenever want to user need to change this time first delete previous and update latest send time. 
  3. Will you please provide me program snippet for How i call flash fds API through android phone and store received time in that app_timer ticks. Confused regarding this.

I am currently using this following functions for FDS read, write, and delete:

static ret_code_t fds_test_write(void)
{
		
    //static uint32_t const m_deadbeef[2] = {0xDEADBEEF,0xBAADF00D};
    static uint8_t const m_deadbeef[1] = {0x14};
//    memcpy(m_deadbeef, write_data, sizeof(m_deadbeef));
    fds_record_t        record;
    fds_record_desc_t   record_desc;

    // Set up data.
    
    // Set up record.
    record.file_id        = FILE_ID_FDS_TEST;
    record.key            = REC_KEY_FDS_TEST;
    record.data.p_data    = &m_deadbeef;
    //record.data.length_words   = sizeof(m_deadbeef)/sizeof(uint32_t);
    record.data.length_words   = sizeof(m_deadbeef)/sizeof(uint8_t);
                    
    ret_code_t ret = fds_record_write(&record_desc, &record);
    if (ret != FDS_SUCCESS)
    {
                    return ret;
    }
     NRF_LOG_INFO("Writing Record ID = %d \r\n",record_desc.record_id);
    return NRF_SUCCESS;
}

static ret_code_t fds_read(void)
{

    fds_flash_record_t  flash_record;
    fds_record_desc_t   record_desc;
    fds_find_token_t    ftok ={0};//Important, make sure you zero init the ftok token
    //uint32_t *data;
    uint8_t *data;
    uint32_t err_code;
    
    NRF_LOG_INFO("Start searching... \r\n");
    // Loop until all records with the given key and file ID have been found.
    while (fds_record_find(FILE_ID_FDS_TEST, REC_KEY_FDS_TEST, &record_desc, &ftok) == FDS_SUCCESS)
    {
                    err_code = fds_record_open(&record_desc, &flash_record);
                    if ( err_code != FDS_SUCCESS)
                    {
                            return err_code;		
                    }
                    
                    NRF_LOG_INFO("Found Record ID = %d\r\n",record_desc.record_id);
                    NRF_LOG_INFO("Data = ");
                    //data = (uint32_t *) flash_record.p_data;
                    data = (uint8_t *) flash_record.p_data;
                    for (uint8_t i=0;i<flash_record.p_header->length_words;i++)
                    {
                            NRF_LOG_INFO("0x%8x ",data[i]);
                    }
                    NRF_LOG_INFO("\r\n");
                    // Access the record through the flash_record structure.
                    // Close the record when done.
                    err_code = fds_record_close(&record_desc);
                    if (err_code != FDS_SUCCESS)
                    {
                            return err_code;	
                    }
    }
    return NRF_SUCCESS;
		
}


static ret_code_t fds_test_find_and_delete (void)
{
    fds_record_desc_t   record_desc;
    fds_find_token_t    ftok;

    ftok.page=0;
    ftok.p_addr=NULL;
    // Loop and find records with same ID and rec key and mark them as deleted. 
    while (fds_record_find(FILE_ID_FDS_TEST, REC_KEY_FDS_TEST, &record_desc, &ftok) == FDS_SUCCESS)
    {
        fds_record_delete(&record_desc);
        NRF_LOG_INFO("Deleted record ID: %d \r\n",record_desc.record_id);
    }
    // call the garbage collector to empty them, don't need to do this all the time, this is just for demonstration
    ret_code_t ret = fds_gc();
    if (ret != FDS_SUCCESS)
    {
        return ret;
    }
    return NRF_SUCCESS;
}

  • Hello,

    There is a user guide for the fds library on infocenter:

    http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.2.0%2Flib_fds_usage.html

    Alternatively, there is also a user guide for fstorage:

    http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.2.0%2Flib_fstorage.html

    The advantage of using the FDS library is that it will handle the flash storage for you, ensuring an even "wear and tear" for the flash.

    A thing that isn't mentioned specifically in the fds guide is that when you e.g. write a record, you should wait for a write and a delete event after using the suggested write or delete functions before you do another fds function. These events are described here.

    So if you call your write function fds_write_test() (which is doing what is described in the "writing a record" snippet), you should wait for the event before writing a new record:

    volatile bool m_fds_init_success = false;
    volatile bool m_fds_write_success = false;
    
    static void fds_evt_handler(fds_evt_t const * p_fds_evt)
    {
        switch (p_fds_evt->id)
        {
            case FDS_EVT_INIT:
                if (p_fds_evt->result != FDS_SUCCESS)
                {
                    //initialization failed.
                }
                else
                {
                    m_fds_init_succeess = true;
                }
                break;
            case FDS_EVT_WRITE:
                if (p_fds_evt->result == FDS_SUCCESS)
                {
                    m_fds_write_success = true;
                }
        }
    }
    
    int main(void)
    {
        fds_init();
        while (!m_fds_init_succes){};
        fds_test_write();
        while (!m_fds_init_success){};
        m_fds_init_success = false;
        
    }

    Best regards,

    Edvin

  • Hello,

    Thanks for providing links and tutorial...

    I am able to write some data into flash using fds as per call write function like this:

    fds_write(0x0001, 0x1111);

    But still confused for update this already stored data on same address(file ID and rec_key)

    Can you please tell me how i can do that?

    Another ques:

    1. What is maximum size of File ID & record key?
    2. We want to store near about 24KB data which is one sensor reading data, So if define specific file ID and record key for that. Is it stored in single file ID OR i need to add next file ID once memory NO memory error got.
    3. Will you please explain Or provide program snippet for update flash data & store large amount of data in single operation.

    Thanks for great supporting...!!

  • Hello,

    You can't re-write to the same address. The bits in the flash can only be changed from '1's to '0's. To rewrite to the same address, you need to erase the entire flash page (only one page, not the entire flash).

    The advantage of FDS is that it uses records, so you can update a record using fds_record_update(). When you do this, the FDS module will write this record to a new place in flash, and mark the old one for deletion. Note that it is not yet deleted. If you get an error message at some point saying that the flash is full, you must do an FDS Garbage Collection (fds_gc()). This function will go through all the records. If the record is still valid, it will copy it to a new flash page, and invalidate the old copy. When it has gone through the entire page, and everything that is still valid is copied, it will delete the old page, so that you can use it again. 

    Note that records that you delete with fds_record_delete() are also not completely deleted. They are marked for deletion, and will be deleted on the next fds_gc().

    1: The maxiumum size is 1018. That is one page size (1024) minus some headers. You can read about it here.

    2: You can read about the IDs and record keys on infocenter (link to fds_record_write())

    3: See the first part of this post. You can update records, and run fds_gc() to delete old copies.

    Best regards,

    Edvin

  • Thanks for this providing this information..!!

    We got one issue which is When i select debug configuration in seeger embedded St.(SES) the flash write operation is success. But When i select release config. in SES the flash write operation is failed and getting error code 3 in NRF_LOG.

    Why this error coming what is the meaning of error 3 only when select release config. build?

    Is any other configuration do i need in SES or in program to work for release build please let me know..!!

    Thanks..!!!

  • Where do you get the error 3? 

    The only difference between Release and Debug is your project settings. 

    Try to define "DEBUG" in your preprocessor defines while you use the "Release" build, and see if the log prints any info on where error_code 3 is coming from.

Related