Hello, I am working on storing words to flash using fds. I am working with the nRF52 DK and SDK V15.2.0. As mentioned in my earlier post, I am storing some critical state information throughout power cycles that relates to calibration data of a sensor. If the device turns on from a power cycle, it needs to check if calibration has or has not been performed. This needs to work very reliably.
I learned that upon initialization, fds will report 4 used words. I then thought I could use this as a point of logic to determine whether my program has stored calibration data or not; if there are more than 4 words used then this means I have manually stored words (calibration data), but if there are only 4 words then I have not. However, it now appears that the amount of used words increases through every cycle even when I am not manually writing to or updating any records. I have included the relevant pieces of code below. All the application should be doing is initializing fds, checking fds_stat for words used, and read the calibration data if more than 4 words are used.
// FDS init helper function, event handler, and function to // check calibration state static void fds_init_helper(void) { ret_code_t ret = fds_register(my_fds_evt_handler); if (ret != FDS_SUCCESS) { NRF_LOG_INFO("ERROR, COULD NOT REGISTER FDS\n"); } ret = fds_init(); if (ret != FDS_SUCCESS) { NRF_LOG_INFO("ERROR, COULD NOT INIT FDS\n"); } NRF_LOG_INFO("FDS INIT\n"); } void my_fds_evt_handler(fds_evt_t const * const p_fds_evt) { NRF_LOG_INFO("INSIDE FDS EVENT HANDLER"); NRF_LOG_INFO(" FDS ID: %d, FDS RESULT: %d \n", p_fds_evt->id, p_fds_evt->result); NRF_LOG_FLUSH(); switch (p_fds_evt->id) { case FDS_EVT_INIT: if (p_fds_evt->result != FDS_SUCCESS) { NRF_LOG_INFO("ERROR IN EVENT HANDLER\n"); NRF_LOG_FLUSH(); } break; case FDS_EVT_WRITE: if (p_fds_evt->result == FDS_SUCCESS) { write_flag=1; } break; default: break; } } // MVAL/BVAL/RVAL_CALIBRATION are global variables static void check_calibration_state(void) { fds_stat_t fds_info; fds_stat(&fds_info); NRF_LOG_INFO("open records: %u, words used: %u\n", fds_info.open_records, fds_info.words_used); if(fds_info.words_used > 4) { CAL_PERFORMED = true; NRF_LOG_INFO("Setting CAL_PERFORMED to true\n"); // Read values stored in flash and set to respective global variables MVAL_CALIBRATION = fds_read(MVAL_FILE_ID, MVAL_REC_KEY); BVAL_CALIBRATION = fds_read(BVAL_FILE_ID, BVAL_REC_KEY); RVAL_CALIBRATION = fds_read(RVAL_FILE_ID, RVAL_REC_KEY); NRF_LOG_INFO("MVAL: " NRF_LOG_FLOAT_MARKER " \n", NRF_LOG_FLOAT(MVAL_CALIBRATION)); NRF_LOG_INFO("BVAL: " NRF_LOG_FLOAT_MARKER " \n", NRF_LOG_FLOAT(BVAL_CALIBRATION)); NRF_LOG_INFO("RVAL: " NRF_LOG_FLOAT_MARKER " \n", NRF_LOG_FLOAT(RVAL_CALIBRATION)); } }
// main function. int main(void) { bool erase_bonds = false; log_init(); timers_init(); power_management_init(); // Initialize fds and check for calibration values fds_init_helper(); check_calibration_state(); // Continue with adjusted calibration state as appropriate ble_stack_init(); gap_params_init(); gatt_init(); services_init(); advertising_init(); conn_params_init(); peer_manager_init(); advertising_start(erase_bonds); // Enter main loop. while (true) { idle_state_handle(); } }
I put some logging into the fds event handler and relevant functions, and see that the fds module is writing and updating words. This only occurs after I connect to a mobile application, and I have quadruple checked and made sure I am not manually making any calls to fds_record_write or fds_record_update anywhere in my application. These writes/updates seem somewhat related to the peer manager events, as you can see in the log statements I have also included. Before connecting to a mobile app, 4 words are reported as used through fds_stat. After connecting and bonding to the phone, you can see in the log output that there are 4 successful fds writes (p_fds_evt.id 0 = initialize, 1 = write, 2 = update, p_fds_evt.result 0 = success). You can also see there is one final fds update, which is also successful. The program then continues as normal, with no more reads/writes/updates. Here is the log:
<info> app: INSIDE FDS EVENT HANDLER <info> app: FDS ID: 0, FDS RESULT: 0 <info> app: FDS INIT <info> app: open records: 0, words used: 4 <info> app: INSIDE FDS EVENT HANDLER <info> app: FDS ID: 0, FDS RESULT: 0 <info> app: CONNECTION MADE (ble_gap_evt) <info> app: Data len is set to 0xF4(244) <info> app: ENTERED PM_EVT_HANDLER <info> app: ENTERED PM_EVT_HANDLER <info> app: BLE_GAP_EVT_SEC_PARAMS_REQUEST <info> app: ENTERED PM_EVT_HANDLER <info> peer_manager_handler: Connection secured: role: Peripheral, conn_handle: 0, procedure: Bonding <info> app: PM_EVT_CONN_SEC_SUCCEEDED <info> app: BLE_GAP_EVT_AUTH_STATUS: status=0x0 bond=0x1 lv4: 0 kdist_own:0x3 kdist_peer:0x3 <info> app: INSIDE FDS EVENT HANDLER <info> app: FDS ID: 1, FDS RESULT: 0 <info> app: ENTERED PM_EVT_HANDLER <info> app: INSIDE FDS EVENT HANDLER <info> app: FDS ID: 1, FDS RESULT: 0 <info> app: ENTERED PM_EVT_HANDLER <info> app: INSIDE FDS EVENT HANDLER <info> app: FDS ID: 1, FDS RESULT: 0 <info> app: ENTERED PM_EVT_HANDLER <info> app: INSIDE FDS EVENT HANDLER <info> app: FDS ID: 1, FDS RESULT: 0 <info> app: ENTERED PM_EVT_HANDLER <info> app: INSIDE FDS EVENT HANDLER <info> app: FDS ID: 2, FDS RESULT: 0 <info> app: ENTERED PM_EVT_HANDLER
Then, I disconnect from the mobile app, stop the debugging function in Segger Embedded Studio, and run the debugging tool again. Before connecting to the mobile app, fds_stat now reports 56 used words. I connect to the mobile application, and then you can see 3 updates are made within the fds module. Here is that log (power cycle 2):
<info> app: INSIDE FDS EVENT HANDLER <info> app: FDS ID: 0, FDS RESULT: 0 <info> app: FDS INIT <info> app: open records: 0, words used: 56 <info> app: Setting CAL_PERFORMED to true <info> app: Start searching... <info> app: SUCCESS CLOSING RECORD <info> app: Start searching... <info> app: SUCCESS CLOSING RECORD <info> app: Start searching... <info> app: SUCCESS CLOSING RECORD <info> app: MVAL: 0.00000000 <info> app: BVAL: 0.00000000 <info> app: RVAL: 0.00000000 <info> app: INSIDE FDS EVENT HANDLER <info> app: FDS ID: 0, FDS RESULT: 0 <info> app: ENTERED PM_EVT_HANDLER <info> app: ENTERED PM_EVT_HANDLER <info> app: ENTERED PM_EVT_HANDLER <info> app: PM_EVT_BONDED_PEER_CONNECTED <info> app: ENTERED PM_EVT_HANDLER <info> app: CONNECTION MADE (ble_gap_evt) <info> app: Data len is set to 0xF4(244) <info> app: ENTERED PM_EVT_HANDLER <info> app: ENTERED PM_EVT_HANDLER <info> app: ENTERED PM_EVT_HANDLER <info> app: PM_EVT_CONN_SEC_CONFIG_REQ <info> app: BLE_GAP_EVT_SEC_PARAMS_REQUEST <info> app: ENTERED PM_EVT_HANDLER <info> peer_manager_handler: Connection secured: role: Peripheral, conn_handle: 0, procedure: Bonding <info> app: ENTERED PM_EVT_HANDLER <info> app: PM_EVT_CONN_SEC_SUCCEEDED <info> app: BLE_GAP_EVT_AUTH_STATUS: status=0x0 bond=0x1 lv4: 0 kdist_own:0x3 kdist_peer:0x3 <info> app: INSIDE FDS EVENT HANDLER <info> app: FDS ID: 2, FDS RESULT: 0 <info> app: ENTERED PM_EVT_HANDLER <info> app: INSIDE FDS EVENT HANDLER <info> app: FDS ID: 2, FDS RESULT: 0 <info> app: ENTERED PM_EVT_HANDLER <info> app: INSIDE FDS EVENT HANDLER <info> app: FDS ID: 2, FDS RESULT: 0 <info> app: ENTERED PM_EVT_HANDLER
I stop the debugger in SES, disconnect, and then run the application with the debugging tool one more time. Before connecting to the phone, fds_stat now reports that 100 words are used. After connecting to the phone, you can again see that 3 more updates are made with the fds module. Here is that log (3rd power cycle):
<info> app: INSIDE FDS EVENT HANDLER <info> app: FDS ID: 0, FDS RESULT: 0 <info> app: FDS INIT <info> app: open records: 0, words used: 100 <info> app: Setting CAL_PERFORMED to true <info> app: Start searching... <info> app: SUCCESS CLOSING RECORD <info> app: Start searching... <info> app: SUCCESS CLOSING RECORD <info> app: Start searching... <info> app: SUCCESS CLOSING RECORD <info> app: MVAL: 0.00000000 <info> app: BVAL: 0.00000000 <info> app: RVAL: 0.00000000 <info> app: INSIDE FDS EVENT HANDLER <info> app: FDS ID: 0, FDS RESULT: 0 <info> app: ENTERED PM_EVT_HANDLER <info> app: ENTERED PM_EVT_HANDLER <info> app: ENTERED PM_EVT_HANDLER <info> app: PM_EVT_BONDED_PEER_CONNECTED <info> app: ENTERED PM_EVT_HANDLER <info> app: CONNECTION MADE (ble_gap_evt) <info> app: Data len is set to 0xF4(244) <info> app: ENTERED PM_EVT_HANDLER <info> app: ENTERED PM_EVT_HANDLER <info> app: ENTERED PM_EVT_HANDLER <info> app: PM_EVT_CONN_SEC_CONFIG_REQ <info> app: BLE_GAP_EVT_SEC_PARAMS_REQUEST <info> app: ENTERED PM_EVT_HANDLER <info> peer_manager_handler: Connection secured: role: Peripheral, conn_handle: 0, procedure: Bonding <info> app: ENTERED PM_EVT_HANDLER <info> app: PM_EVT_CONN_SEC_SUCCEEDED <info> app: BLE_GAP_EVT_AUTH_STATUS: status=0x0 bond=0x1 lv4: 0 kdist_own:0x3 kdist_peer:0x3 <info> app: INSIDE FDS EVENT HANDLER <info> app: FDS ID: 2, FDS RESULT: 0 <info> app: ENTERED PM_EVT_HANDLER <info> app: INSIDE FDS EVENT HANDLER <info> app: FDS ID: 2, FDS RESULT: 0 <info> app: ENTERED PM_EVT_HANDLER <info> app: INSIDE FDS EVENT HANDLER <info> app: FDS ID: 2, FDS RESULT: 0 <info> app: ENTERED PM_EVT_HANDLER
Now, I can't use the simple logic if "if > 4 words, read calibration data. Else, continue as normal". I could just write another word to flash when performing calibration, a boolean that I could read after initialization to check if calibration has been performed. I.E. look for a specific word/record (maybe "CALIBRATION_DONE"), and if it is there and the value is 1/true, read calibration values. If the word/record is not there, or if the value of the word is 0/false, don't try to read calibration values.
However, I am still concerned and confused as to why so many words are being written to flash when I am not manually making calls to do so. This could be problematic, as over time the flash could fill up with these words and I may need to use flash storage for additional data later in development. Can anyone help me out with why this is happening? The number of words used in flash does not appear to be consistent either. The very first reported # of words used is always 4, but subsequent power cycles report varying numbers of words used. If I erase the nRF52 DK, this behavior restarts. I have no idea what is going on, so any help would be super super useful!
Thanks :)