Hi,
I am having an issue with the FDS update command returning a CRC error as above. Any advice on how to fix this issue would be greatly appreciated.
Steps to recreate:
- Init FDS - receive Init success event
- Delete file (for completeness) - receive delete success event
- Run GC - receive GC success event
- Check for record using fds_record_find() - file not found
- Create and write record - receive write success event
- Wait a while ~20 seconds
- Update record with no timer - returns NRF_SUCCESS but receive FDS_ERR_CRC_CHECK_FAILED event
If I disable the CRC checks, the data is indeed incorrect and garbled when read back.
I am using the nRF52840, SDK 17.0, S140
Init code:
void Storage_Init( void ) { ret_code_t err_code; if( _initialised == true ) { return; } ( void )fds_register( fds_evt_handler ); err_code = fds_init( ); APP_ERROR_CHECK( err_code ); while( !m_fds_initialised ) ; NRF_LOG_INFO( "FDS Initialised" ); fds_file_delete( DEVICE_SETTINGS_FILE ); fds_stat_t stat = { 0 }; err_code = fds_stat( &stat ); APP_ERROR_CHECK( err_code ); NRF_LOG_INFO( "Found %d valid records.", stat.valid_records ); NRF_LOG_INFO( "Found %d dirty records (ready to be garbage collected).", stat.dirty_records ); if( stat.dirty_records > 0 ) { err_code = fds_gc( ); APP_ERROR_CHECK( err_code ); } fds_record_desc_t desc = { 0 }; fds_find_token_t tok = { 0 }; // Set Defaults if needed err_code = fds_record_find( DEVICE_SETTINGS_FILE, DEVICE_SETTINGS_KEY, &desc, &tok ); if( err_code == NRF_SUCCESS ) { fds_flash_record_t deviceSettingsRecord = { 0 }; deviceSettings_t deviceSettings; // Open the record and read its contents err_code = fds_record_open( &desc, &deviceSettingsRecord ); APP_ERROR_CHECK( err_code ); memcpy( &deviceSettings, deviceSettingsRecord.p_data, sizeof( deviceSettings_t ) ); // TODO: Print data NRF_LOG_INFO( "[STORAGE] Device Settings File Found" ); } else { NRF_LOG_INFO( "[STORAGE] Device Settings Not Found" ); err_code = fds_record_write( &desc, &defaultRecord ); APP_ERROR_CHECK( err_code ); } _initialised = true; }
Update Code:
static void Storage_WriteDeviceSettings( DeviceSettings_t deviceSettings ) { ret_code_t err_code; fds_record_desc_t desc = { 0 }; fds_find_token_t tok = { 0 }; fds_record_t const _newDeviceSettingsRecord = { .file_id = DEVICE_SETTINGS_FILE, .key = DEVICE_SETTINGS_KEY, .data.p_data = &deviceSettings, // The length of a record is always expressed in 4-byte units (words). .data.length_words = ( sizeof( deviceSettings ) ) / sizeof( uint32_t ) }; // Check the record exists err_code = fds_record_find( DEVICE_SETTINGS_FILE, DEVICE_SETTINGS_KEY, &desc, &tok ); if( err_code == NRF_SUCCESS ) { // If it does, update it err_code = fds_record_update( &desc, &_newDeviceSettingsRecord ); APP_ERROR_CHECK( err_code ); NRF_LOG_INFO( "[STORAGE] Device Settings Updated" ); } else { // If it doesn't, create it NRF_LOG_INFO( "[STORAGE] Device Settings Not Found" ); err_code = fds_record_write( &desc, &_newDeviceSettingsRecord ); APP_ERROR_CHECK( err_code ); NRF_LOG_INFO( "[STORAGE] Device Settings Written" ); } }
Thanks!
EDIT: After some debugging, it turns out that the update function stops working if it is called after BLE is initialised (The FDS is initialised before the BLE). This occurs with or without the Peer Manager being initialised in the BLE initialisation call. BLE Init code is below:
void Bluetooth_Init( void ( *Services_Init )( ), char* deviceName ) { if( _initialised == true ) { return; } if( deviceName != NULL ) { uint32_t nameLength = strlen( deviceName ); if( nameLength >= 32 ) { nameLength = 31; } memcpy( _deviceName, deviceName, nameLength ); _deviceName[nameLength] = '\0'; } // Initialise the general Power configuration if( !nrf_drv_power_init_check( ) ) { nrf_drv_power_init( NULL ); } // Load the default configuration Bluetooth_LoadDefaultConfiguration( ); // Enable the Bluetooth SoftDevice ret_code_t errorCode; errorCode = nrf_sdh_enable_request( ); APP_ERROR_CHECK( errorCode ); // Configure the Bluetooth stack for the primary connection // (BLUETOOTH_CONNECTION_CONFIGURATION_TAG/1) and retrieve the application RAM start address // (the rest is used by the SoftDevice) Note: Settings are obtained from the SoftDevice handler // BLE configuration. uint32_t ramStart = 0; errorCode = nrf_sdh_ble_default_cfg_set( BLUETOOTH_CONNECTION_CONFIGURATION_TAG, &ramStart ); APP_ERROR_CHECK( errorCode ); // Configure the Stack to hold multiple concurrent notifications and additional 128-bit UUIDs to // maximise throughput ble_cfg_t configuration; memset( &configuration, 0, sizeof( configuration ) ); configuration.conn_cfg.conn_cfg_tag = BLUETOOTH_CONNECTION_CONFIGURATION_TAG; configuration.conn_cfg.params.gatts_conn_cfg.hvn_tx_queue_size = BLUETOOTH_NOTIFICATION_QUEUE_SIZE; errorCode = sd_ble_cfg_set( BLE_CONN_CFG_GATTS, &configuration, ramStart ); APP_ERROR_CHECK( errorCode ); NRF_ATFIFO_INIT( _notificationQueue ); // Enable the Bluetooth Stack errorCode = nrf_sdh_ble_enable( &ramStart ); APP_ERROR_CHECK( errorCode ); // Register the BLE event handler NRF_SDH_BLE_OBSERVER( m_ble_observer, BLUETOOTH_OBSERVER_PRIORITY, Bluetooth_GeneralEventHandler, NULL ); // Configure the GAP settings within the Nordic Bluetooth Stack Bluetooth_ConfigureGAP( ); // Initialise the GATT Module Bluetooth_InitialiseGATT( ); // Configure Services Services_Init( ); // Initialise the Advertising Module Bluetooth_LoadDefaultAdvertisingConfiguration( ); Bluetooth_InitialiseAdvertising( ); errorCode = sd_ble_gap_tx_power_set( BLE_GAP_TX_POWER_ROLE_ADV, nRFAdvertisingModule.adv_handle, 4 ); // 8 );// Add support in config and for other modes APP_ERROR_CHECK( errorCode ); // Configure Connection Parameters Bluetooth_InitialiseConnectionParameters( ); // Initialise the peer manager Bluetooth_InitialisePeerManager( ); _initialised = true; }