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,

  • Thanks Edvin,

    I have used FDS library and able to flash write and delete data when message received from ble_app_uart.

    But problem getting for read function: I am write this data  const m_deadbeef = 0xDEADBEEF;

    When i call read function after write event generated got this data in read function: "0x      EF"

    Why not getting all write hex data?

    Also will you please tell me how i can write integer value instead of this hex data? 

    Thanks in advanced,....!!!

  • Hello,

     

    The issue is that you cast the flash_record.p_data to a uint8_t, while it is really a uint32_t pointer.

    Try the fds_read function looking something like this:

    void fds_test_read(void)
    {
        ret_code_t err_code = FDS_SUCCESS;
        fds_flash_record_t  flash_record;
        fds_record_desc_t   record_desc;
        fds_find_token_t    ftok;
        memset(&ftok, 0x00, sizeof(fds_find_token_t));
        
        while (fds_record_find(FILE_ID, RECORD_KEY_1, &record_desc, &ftok) == FDS_SUCCESS)
        {
            err_code = fds_record_open(&record_desc, &flash_record);
            if (err_code != FDS_SUCCESS)
            {
                // Handle error
                printf("fds_record_open error %d\r\n", err_code);
            }
            // 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)
            {
                // Handle error
                printf("fds_record_close err_code %d\r\n", err_code);
            }
            uint32_t *data = (uint32_t *) (flash_record.p_data);
            printf("record found:\r\n");
            printf("%08x\r\n", *data);
            
        }
    }

    Of course, use the NRF_LOG_INFO instead of printf. I just started implementing this to the SDK15\examples\peripheral\uart example, so printf was already set up.

     

    You can write int values instead of hex values. Just create an int variable when you write, which you pass the pointer to into the fds_write function:

    record.data.p_data = &m_my_variable;

    The same goes when you read out the variable. Remember that all you read is a register in flash. If I stored an int (int32_t) instead hexadecimal, I would write something like this:

     

    int32_t *data = (int32_t *)(flash_record.data);

    NRF_LOG_INFO("%d", *data);

    And the data will be printed as a number instead of hexadecimal values.

     

    Best regards,

    Edvin

  • Sorry for late response...!!

    We were explored other thing to get more advanced features in our current application. So now i have tested this as you provided above program snippet and it is working able to read proper value as flash on this address. But still got one problem which is

    When i connect my phone to DK and send read command like "r" to DK and call "fds_test_read()" but it stuck and when i disconnect BLE connection then got read data LOG on terminal as write last time.

    Is any problem with BLE activity connected to device and call flash read function. Because i got read data log after disconnect BLE connection. As i read here he said It is fully possible to read/write to flash when you are in a BLE connection. But i got problem with read function while connected BLE, Is any other configuration to need to enable in sdk_config.h file.

    Thank you so much....!!

  • 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

Reply Children
  • 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......!!

  • 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..!!!

Related