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,

  • Ok. so two issues, then:

    1: fds_file_delete() will trigger the FDS_EVT_DEL_RECORD event, which will set fds_delete_success = true. You are waiting for the fds_write_success to become true. It never will.

    2: In your fds_delete_file(). If one of the function calls inside here returns ret != NRF_SUCCESS, your FDS operations aren't queued. 

    So let us say that inside fds_delete_files() returns e.g. FDS_ERR_NO_SPACE_IN_QUEUES, then fds_delete_file() returns FDS_ERR_NO_SPACE_IN_QUEUE, but your delete operation is not queued, and you will never get the FDS_EVT_DEL_RECORD (or the FDS_EVT_WRITE, for that matter. See issue 1.)

    However, you wait for this event (the wrong one) before you check the return value of fds_file_delete();

    You should check the return value before you wait for the event. Something like this:

    ret_code_t fds_delete_file(uint16_t file_ID)
    {
        ret_code_t ret = fds_file_delete(file_ID);
        if (ret != FDS_SUCCESS)
        {
            return ret;
        }
        wait_for_next_delete(); // PLEASE NOTE THIS CHANGE. not wait_for_next_write()
        ...
    }

  • Thanks for quick response..!!!

    I have made changes as you suggested and error code is 0 means NRF_SUCCESS

    But still same issue.. it continuous in forever loop.

    Any other suggestion please...

  • Do you get the return value NRF_SUCCESS (= 0) from fds_file_delete()? And you are sure that the wait_for_next_delete() function is hit?

    Maybe you get the FDS_EVT_DEL_FILE event with p_fds_evt->result != FDS_SUCCESS? Can you check this?

    Also, can you try to remove the idle_state_handle(); from inside the while loop in the wait_for_next_delete() function?

  • Do you get the return value NRF_SUCCESS (= 0) from fds_file_delete()? And you are sure that the wait_for_next_delete() function is hit?

    Yes I got NRF_SUCESS from fds_file_delete(), and sure bout wait_for_next_delete() function hit.

    I have check by set break point with FDS_EVT_DEL_RECORD and FDS_EVT_DEL_FILE but nothing get.

    Also, can you try to remove the idle_state_handle(); from inside the while loop in the wait_for_next_delete() function?

    this already i have tried.

    This happening only when if used wait_for_next_delete() If I comment this then got all event and also clean flash. Here is my below logs without wait for next delete:

    <debug> app: Received data from BLE NUS. Writing data on UART.
    <debug> app:  38                     |8       
    <info> app: 8 cmd received
    <info> app: Deleted record ID: 8 
    
    <info> app: Deleted front & rear value
    <info> app: Deleting File no:1
    <info> app: Deleting File no:2
    <info> app: Deleting File no:3
    <info> app: Deleting File no:4
    <info> app: Deleting File no:5
    <info> app: Deleting File no:6
    <info> app: Deleting File no:7
    <info> app: Deleting File no:8
    <info> app: Deleted record ID: 1 
    
    <info> app: FDS mach-ID delete success
    <info> app: Deleted record ID: 2 
    
    <info> app: FDS Cron-Sch delete success
    <info> app: Deleted record ID: 30 
    
    <info> app: FDS Any Stored ERROR delete success
    <info> app: Garbage Collection completed
    <info> app: Flash data File deleted
    <info> app: Disconnected
    <debug> app: Started Advertisng timeout timer
    <info> app: Garbage Collection completed
    <info> app: Flash data File deleted
    <info> app: Garbage Collection completed
    <info> app: Flash data File deleted
    <info> app: Garbage Collection completed
    <info> app: Flash data File deleted
    <info> app: Garbage Collection completed
    <info> app: Flash data File deleted
    <info> app: Garbage Collection completed
    <info> app: Flash data File deleted
    <info> app: Garbage Collection completed
    <info> app: Flash data File deleted
    <info> app: Garbage Collection completed
    <info> app: Flash data File deleted
    <info> app: Garbage Collection completed
    <info> app: Flash data record deleted
    <info> app: Garbage Collection completed
    <info> app: Flash data record deleted
    <info> app: Garbage Collection completed
    <info> app: Flash data record deleted
    <info> app: Garbage Collection completed
    <info> app: Flash data record deleted
    <info> app: Garbage Collection completed

    I have read some ques and answer from Nordic forum link here someone suggest the intrrupt priority of FDS module is lower than BLE priority is this correct? 

    If yes how I can change the priority to get fds event with ble connected to device?

    Thanks.......

  • The priority is lower for FDS than for BLE, yes, but it has to be that way. The BLE will not block you all the time. Only short interrupts. 

    What is your connection state when you try to delete? I assume it is connected? If so, what is your connection interval?

Reply Children
  • Yes, the connection state is connected when i call to delete function,

    #define APP_BLE_CONN_CFG_TAG 1                           /**< A tag identifying the SoftDevice BLE configuration. */
    #define DEVICE_NAME "Device_test"                         /**< Name of device. Will be included in the advertising data. */
    #define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service (vendor specific). */
    
    #define APP_BLE_OBSERVER_PRIO 3 /**< Application's BLE observer priority. You shouldn't need to modify this value. */
    #define APP_ADV_INTERVAL 64     /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */
    
    #define APP_ADV_DURATION 0   /* Set 0 for contineous advertisng time & handle their timeout by sperate app timer.*/ 
    
    #define MIN_CONN_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS)   //20           /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */
    #define MAX_CONN_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS)   //75           /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */
    #define SLAVE_LATENCY 0                                      /**< Slave latency. */
    #define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS)     /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */
    #define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
    #define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(90000) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
    #define MAX_CONN_PARAMS_UPDATE_COUNT 3                       /**< Number of attempts before giving up the connection parameter negotiation. */

    Please note I have already tried with connection interval below:

    #define MIN_CONN_INTERVAL MSEC_TO_UNITS(20, UNIT_1_25_MS)   //20           /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */
    #define MAX_CONN_INTERVAL MSEC_TO_UNITS(75, UNIT_1_25_MS)   //75 

    Thanks

  • Can you try to increase the connection interval even more? E.g. try to set both min and max to 100. 

    Can you try to do the delete function without being in a connection and without advertising? Does it work then?

  • I have tried min and max to 100ms, but still same problem.

    Can you try to do the delete function without being in a connection and without advertising? Does it work then?

    Yes actually if i have called this function without any BLE activity it has worked and also got all fds event.

    Why this happening only when BLE advertising OR with connected?

  • From where are you calling the fds_delete_file()? Is it inside a softdevice interrupt? If so, you may block the FDS. You should set a flag from the SD interrupt, and then call the FDS functions from the main context. 

  • I am calling  fds_delete_file() from main here is below snippet:

    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_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);
        switch (p_evt->params.rx_data.p_data[0]) {
        ...
        case '8': // To detach configured machine info.
          NRF_LOG_INFO("8 cmd received");
          delete_all_reading_process();
          ...
    
    /* This function is used for delete all stored reading availble in flash even if any not available then clean flash for that file number*/
    void delete_all_reading_process() {
      uint16_t file_no;
      ret_code_t ret;
      ret = fds_find_and_delete(FILE_ID_FRONT_REAR_VAL, REC_KEY_FRONT_REAR_VAL);
      if (ret == FDS_SUCCESS) {
        NRF_LOG_INFO("Deleted front & rear value");
      }
      for (file_no = 1; file_no <= READINGS_STORE; file_no++) {
        NRF_LOG_INFO("Deleting File no:%d", file_no);
        ret = fds_delete_file(file_no);
      }
      if (ret != FDS_SUCCESS) {
        ble_nus_data_send(&m_nus, DETACH_MACH_FAILED, &msg_code_len, m_conn_handle); // send message to connected phone
      }
      detached_machine_info();
    }

    If this wrong how I can set flag from the SD interrupt. I am not understand how i can check this is it inside a soft-device interrupt. 

    I am calling this function from nus_data_handler(..);

    Thanks...

Related