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

FDS Update returning FDS_ERR_CRC_CHECK_FAILED in Event Handler

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;

}

Related