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

fds write not working FDS_ERR_NOT_INITIALIZED

Hi I am using the custom_bluetooth_service tutorial from https://github.com/bjornspockeli/custom_ble_service_example with SDK v15 and nrf52840 DK.

I am now trying to use fds to write data to flash storage and then access it later to assign the value to characteristics.

.

#include "sdk_common.h"
#include "ble_cus.h"
#include <string.h>
#include "ble_srv_common.h"
#include "nrf_gpio.h"
#include "boards.h"
#include "nrf_log.h"

#include "fds.h"

#define FILE_ID 0x1111
#define REC_KEY 0x2220

static uint8_t eight = 8
static uint8_t nine = 9

static fds_record_t const m_dummy_record =
{
    .file_id = FILE_ID,
    .key = REC_KEY,
    .data.p_data = &eight,
    .data.length_words = (sizeof(eight) + 3) / sizeof(uint32_t),
};

...

static uint32_t custom_value_char_add(ble_cus_t * p_cus, const ble_cus_init_t * p_cus_init)
{
    uint32_t            err_code;
    ble_gatts_char_md_t char_md;
    ble_gatts_attr_md_t cccd_md;
    ble_gatts_attr_t    attr_char_value;
    ble_uuid_t          ble_uuid;
    ble_gatts_attr_md_t attr_md;
    
    ret_code_t ret = fds_init();
    fds_flash_record_t config = {0};
    fds_record_desc_t desc = {0};
    
    ret_code_t rc_write = fds_record_write(&desc, &m_dummy_record);
    
    if (rc_write != FDS_SUCCESS){
        return rc_write;
    }
    
    
    

    // Add Custom Value characteristic
    memset(&cccd_md, 0, sizeof(cccd_md));

    //  Read  operation on cccd should be possible without authentication.
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
    
    cccd_md.write_perm = p_cus_init->custom_value_char_attr_md.cccd_write_perm;
    cccd_md.vloc       = BLE_GATTS_VLOC_STACK;

    memset(&char_md, 0, sizeof(char_md));

    char_md.char_props.read   = 1;
    char_md.char_props.write  = 1;
    char_md.char_props.notify = 1; 
    char_md.p_char_user_desc  = NULL;
    char_md.p_char_pf         = NULL;
    char_md.p_user_desc_md    = NULL;
    char_md.p_cccd_md         = &cccd_md; 
    char_md.p_sccd_md         = NULL;
		
    ble_uuid.type = p_cus->uuid_type;
    ble_uuid.uuid = CUSTOM_VALUE_CHAR_UUID;

    memset(&attr_md, 0, sizeof(attr_md));

    attr_md.read_perm  = p_cus_init->custom_value_char_attr_md.read_perm;
    attr_md.write_perm = p_cus_init->custom_value_char_attr_md.write_perm;
    attr_md.vloc       = BLE_GATTS_VLOC_STACK;
    attr_md.rd_auth    = 0;
    attr_md.wr_auth    = 0;
    attr_md.vlen       = 0;

    memset(&attr_char_value, 0, sizeof(attr_char_value));

    attr_char_value.p_uuid    = &ble_uuid;
    attr_char_value.p_attr_md = &attr_md;
    attr_char_value.init_len  = sizeof(uint8_t);
    attr_char_value.init_offs = 0;
    attr_char_value.max_len   = sizeof(uint8_t);

    err_code = sd_ble_gatts_characteristic_add(p_cus->service_handle, &char_md,
                                               &attr_char_value,
                                               &p_cus->custom_value_handles);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    return NRF_SUCCESS;
}

But when I try to write a fds record, I have an error "FDS_ERR_NOT_INITIALIZED" which means the module is not initialized. I check other Nordic Devzone post and one post (https://devzone.nordicsemi.com/f/nordic-q-a/23742/fds_err_not_initialized) said the error is due to fs_sys_event_handler() being missing from sys_evt_dispatch(). That post referenced SDK v11 and I am using SDK v15. In the tutorial example code I am using I also cannot find the sys_evt_dispatch() call in main.c.  

The tutorial example code uses peer manager which also uses fds. The peer manager code registers an event handler and initializes the fds module. I am putting my custom code in ble_cus.c and I also do my own initialization of the fds module there. I checked in sdk_config.h and the max users for the fds module is set to 4 so I think I can use the fds_module in ble_cus.c.

I have tried calling peer_manager_init() before service_init() because the peer manage code needs to register the fds event handler before the fds module can be initialized. However, that did not fix the error. I have also added fds event handler code and registered it before I call fds_init() in ble_cus.c, but that also did not change the error.

Interestingly, when I checked the ret_code for my call in fds_init() in ble_cus.c the ret_code was FDS_SUCCESS. I get the same success code from the call that registered the fds event handler.So if my call to fds_init() was successful I am not sure why I am getting the error that the fds module was not successfully initialized. 

How should I fix this? Thank you!

 

 

Parents Reply Children
  • Hi,

    I think I would need the modified source files to replicate the exact same issue. Guess the code snippet you included includes most of the relevant code, but the part where the FDS user gets registered appears to be missing. Anyway, instead, I took the template example from SDK 15.3.0 and added main.c and the ble service from Bjørn's git repo. Then moved the PM init before the service init and added the fds code.

    My test project:

      ble_app_template.zip

  • Hi Vidar,

    I flashed the code you added, with some modifications that assigned the ret code of the fds write to the BLE custom characteristic. I attached the modified source and project files below. I am still getting a FDS_ERR_NOT_INITIALIZED error after I flash the code to my NRF52840 DK. But when I turn the DK off then back on the error I get is FDS_ERR_UNALIGNED_ADDR. I am not sure why I am still getting these errors using the code you provided.

    I've also tried writing to new FILE_ID and REC_KEY, but I still get the same fds_write error. Do you have any suggestions on what else I should try to resolve these errors? Thanks!

    nordic_fds.zip

  • Hi,

    I see the problem now; as you indicated earlier, the initialization is asynchronous, and the completion is reported to the registered FDS callback(s). This takes a bit longer on initial boot because FDS need to "tag" each of the allocated flash pages first. An easy solution to this is to add a busy-wait delay between FDS init in pm_init and when you initialize the service. 

    A better solution maybe is to restructure the code so that FDS related code is placed outside of the BLE service. Then you can more easily register the FDS users before fds_init(). ble_cus_custom_value_update() can be used to update the characteristic value once FDS is ready

    The address of a "uin8_t" variable is not guaranteed to be word-aligned so you should prefix the variable definitions with __ALIGN(4):

    __ALIGN(4) static uint8_t eight = 8;
    __ALIGN(4) static uint8_t nine = 9; 

  • After moving the FDS related code outside of the BLE service, say to another function custom_fds(), would I still need a busy_wait between FDS init in pm_init and custom_fds()?

Related