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;
}

Parents
  • You cannot call the fds API through an android phone!

    What you will need to do is to devise some sort of command that your app will send to instruct your nRF code to update the parameters, and store in Flash

    please provide me program snippet for How i call flash fds

    That is exactly what the example project does - but it does it for an interactive human user at a terminal.

    So you just need to get rid of the interactive CLI stuff, and implement a command over the BLE link ...

  • Thanks for fast response,

    So you just need to get rid of the interactive CLI stuff, and implement a command over the BLE link ...

    But as you said above how i can implement CLI stuff over BLE link will you please provide me tutorial or example.

    If i call flash write function like this is it have any restriction:

    When Nordic UART tool box connected to device then we send 3 commnd-->

    static void nus_data_handler(ble_nus_evt_t * p_evt)
    {
    
    if (p_evt->type == BLE_NUS_EVT_RX_DATA)
    {
    uint32_t err_code;
    NRF_LOG_INFO("nus_data_handler call");
    // send_to_central();
    NRF_LOG_DEBUG("Received data from BLE NUS. Writing data on UART.");
    NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
    
    for (uint32_t i = 0; i < p_evt->params.rx_data.length; i++)
    {
    do
    {
    err_code = app_uart_put(p_evt->params.rx_data.p_data[i]);
    if(p_evt->params.rx_data.p_data[i] == '3')
    {
    NRF_LOG_INFO("Start flashing....");
    err_code = fds_test_find_and_delete();
    APP_ERROR_CHECK(err_code);
    nrf_delay_ms(1000);
    fds_test_write();
    nrf_delay_ms(1000);
    // fds_read();
    break;
    }

    Thanks,

  • I have not seen any problems with the fds read functionality while in a BLE connection. 

    The fds_record_open shouldn't hang. If it does, are you able to find out which function it can't get past?

    Best regards,

    Edvin

  • Hi,

    Thank you so much for share this LOG related issue with me. So now after replaced existing idle_state_handle() function with this corrected function

     

    static void idle_state_handle(void)
    {
        if (NRF_LOG_PROCESS() == false)
        {
            nrf_pwr_mgmt_run();
        }
    }

    Then my code is worked and i am able to read and write simple value in flash. Now i will go head to write other flash read/write functionality for wake up time change.

    Thank you so much Edvin and awneil for your great help..

  • You're welcome!

    - in the linked thread,  said that an internal ticket was raised for this to be fixed. Has it been fixed in 15.2.0 ?

    PS

    How do I @mention a name with a space in it - like " " ??

  • Hi ,

    I am sorry to see that the bug has not been fixed in SD 15.2. I have bumped the internal bug report.

    Regarding how to mention names with space I see the problem, but I don't know if there is any way. I will try to find out and update this comment if I do.

  • Hi,

    If got server error due to any connection problem, so that time sensor device is not able to transmit data to server, since we want to store that time  sensor readings in flash. Once readings stored in flash and whenever sensor wkae up want to read stored data from flash and sent it to server.

    For achieving this i am confused & struggling how i can write this logic and i set file ID, record_key for each reading and also once reading transmitted to server after that delete specific reading.

    Will you please help me how i can achieved this and also can you provide tutorial or any other useful data for understanding flash api use in detail like what is record_key, file_id, data write address location etc.

    Thank you......!!

Reply
  • Hi,

    If got server error due to any connection problem, so that time sensor device is not able to transmit data to server, since we want to store that time  sensor readings in flash. Once readings stored in flash and whenever sensor wkae up want to read stored data from flash and sent it to server.

    For achieving this i am confused & struggling how i can write this logic and i set file ID, record_key for each reading and also once reading transmitted to server after that delete specific reading.

    Will you please help me how i can achieved this and also can you provide tutorial or any other useful data for understanding flash api use in detail like what is record_key, file_id, data write address location etc.

    Thank you......!!

Children
  • 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