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

How to write, read and store uint8_t data_array via FDS

Hello everybody,

I used SDK14.2.0 , S132 .

I keep the data from nus_data in the uint8_t array. Then I am trying to write the array with use fds_write.

My fds_write function;

static ret_code_t kls_fds_write(uint32_t file_id, uint32_t record_key , uint8_t write_data[])
{		
	fds_record_t        record;
	fds_record_desc_t   record_desc;
	
	// Set up record.
	record.file_id           = file_id;
	record.key               = record_key;
	record.data.p_data       = &write_data;
	record.data.length_words = (sizeof(write_data) + 3) / 4;     //sizeof(write_data);   //(sizeof(write_data) + 3) / sizeof(uint32_t);
	
	ret_code_t rc;
	rc = fds_record_write(&record_desc, &record);
	if (rc != FDS_SUCCESS)
	{
			/* Handle error. */
			NRF_LOG_INFO("FDS Write Handle error.");
			return rc;
	}
	NRF_LOG_INFO("Writing Record ID = %d \r\n",record_desc.record_id);
	return NRF_SUCCESS;
	
}

I use my fds_write function by this way;

static void save_data( uint8_t *p_data)
{
	NRF_LOG_INFO("save_data");
	uint8_t source_data_0[10] ;		
	
	// assign source datas  ********************************	
	for (uint32_t i = 0; i < 10; i++)				
	{
		source_data_0[i] = p_data[i];
	}
	while (flag_write_fds == false);
	kls_fds_write(FILE_ID, RECORD_KEY, source_data_0);
	
	NRF_LOG_HEXDUMP_INFO(source_data_0, sizeof(source_data_0));
	
	allow_advertisement = false;

}

Then I am trying to read and store the data into another array.

My fds_read function;

static ret_code_t kls_fds_read(uint32_t file_id, uint32_t relevant_record_key , uint8_t read_data[])
{	
		fds_flash_record_t  flash_record;
		fds_record_desc_t   record_desc;
		fds_find_token_t    ftok;
		fds_record_t        record;
		/* It is required to zero the token before first use. */
		memset(&ftok, 0x00, sizeof(fds_find_token_t));
		
		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, relevant_record_key, &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);
				
				uint8_t * pointer_to_record_data;
				pointer_to_record_data = (uint8_t *)record.data.p_data; 
				
				if(flash_record.p_header->record_key == relevant_record_key)
				{
					for(uint8_t i = 0; i < 10; i++)
					{
							read_data[i] = *pointer_to_record_data;
							pointer_to_record_data++;
					}
				}
				
				NRF_LOG_INFO("Data = ");
				NRF_LOG_HEXDUMP_INFO(read_data, sizeof(read_data));
				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;		
}

I use my fds_read function by this way;

static void first_Setup(void)
{
    NRF_LOG_INFO("first_Setup Start");
    uint8_t dest_data_0[10]  = {0};
	
    while (flag_write_fds == 0);
    kls_fds_read(FILE_ID, RECORD_KEY, dest_data_0);
    	
    NRF_LOG_INFO("dest_data_0 : ");
    NRF_LOG_HEXDUMP_INFO(dest_data_0, 10);
    
}

I can write and read something but these are not meaningful data. Or I can not read the data I wrote because of anything. I obviously could not figure out exactly where the problem was.

The steps I want to take are as follows;

  • Store particular nus_data into an array (uint8_t source_data_0[10] ) -> I'm already doing this. No problem.
  • Write the stored array(uint8_t source_data_0[10] ) via FDS -> I do that already, but I do not know exactly whether it is successful.
  • Read the stored array(uint8_t source_data_0[10] )via FDS and Store the read array(source_data_0[10] ) in another array (uint8_t dest_data_0[10]  = {0}).

Test Result;

I sent the nus data( "aaaaaaaaaa" ) and I can store it into source_data_0[] successfully. Then I use my fds_write function;

0> <info> app: save_data
0> <info> app: Writing Record ID = 1
0>
0> <info> app: 61 61 61 61 61 61 61 61|aaaaaaaa
0> <info> app: 61 61 |aa

Finally I tried to read and result is;

0> <info> app: first_Setup Start

0> <info> app: Start searching...
0>
0> <info> app: Found Record ID = 1
0>
0> <info> app: Data =
0> <info> app: 00 04 00 20 |...
0> <info> app:
0>
0> <info> app: dest_data_0 :
0> <info> app: 00 04 00 20 E9 08 00 00|... é...
0> <info> app: 7D 05 |}.

As a result; The data I read is not the same as the data I write . May be I read it in the wrong format, I do not know exactly. 

So, Do you have any suggestion ?

Parents
  • Hey Ugur,

    I believe I found a bug:

    fds_record_t record; // Uninitialized variable
    
    uint8_t * pointer_to_record_data;
    pointer_to_record_data = (uint8_t *)record.data.p_data; // points to an address with unknown data
    
    if(flash_record.p_header->record_key == relevant_record_key)
    {
    	for(uint8_t i = 0; i < 10; i++)
    	{
    		read_data[i] = *pointer_to_record_data; // record has not been used
    		pointer_to_record_data++;
    	}
    }

    You never used the variable 'record' and since it is uninitialized it's content is in an unknown state. The compiler has probably reused the memory of other parts of the program that is no longer in the scope and you will therefore read garbage data.

    Cheers,

    Håkon.

  • Hey Ugur,

    I spoke in error earlier when I said that the record descriptor was not used. It is clearly used in:
    while (fds_record_find(file_id, relevant_record_key, &record_desc, &ftok) == FDS_SUCCESS)

    I believe it's the way you are accessing the fds_flash_record_t flash_record afterwords.

    uint32_t your_data[8] = {0};
    uint8_t your_byte = 0;
    
    for(uint8_t i = 0; i < flash_record->p_header.length_words; i++){
        your_data[i] = flash_record->p_data[0];
    }
    
    your_byte = (uint8_t)your_data[0];

Reply
  • Hey Ugur,

    I spoke in error earlier when I said that the record descriptor was not used. It is clearly used in:
    while (fds_record_find(file_id, relevant_record_key, &record_desc, &ftok) == FDS_SUCCESS)

    I believe it's the way you are accessing the fds_flash_record_t flash_record afterwords.

    uint32_t your_data[8] = {0};
    uint8_t your_byte = 0;
    
    for(uint8_t i = 0; i < flash_record->p_header.length_words; i++){
        your_data[i] = flash_record->p_data[0];
    }
    
    your_byte = (uint8_t)your_data[0];

Children
  • Hi haakonsh thanks for answer but unfortunately I got an error like this ;
    "..\..\..\main.c(387): error:  #44: expression must have pointer type"

    Also the missing part is: I want to write and read an array of 10 members, not just a one byte element. If I can not save it all in one go, I need to define something like a buffer. I used pstorage at sdk 8 and it worked very well. But I can not migrate to FDS.

    I did this in SDK 8 as well;

    static void pstorage_save(uint8_t * p_data)
    {
    		pstorage_handle_t       handle;
    		pstorage_handle_t		block_3_handle;
    		pstorage_module_param_t param;
    		uint8_t                 source_data_3[16] = {'\0'};		
    		uint32_t                retval;
    		
    		retval = pstorage_init();
    		if(retval != NRF_SUCCESS){
    				bsp_indication_set(BSP_INDICATE_FATAL_ERROR);
    		}
    	     
    		param.block_size  = 16;                   //Select block size of 16 bytes
    		param.block_count = 53;                    //Select 32 blocks, total of 512 bytes
    		param.cb          = example_cb_handler;   //Set the pstorage callback handler
    			
    		retval = pstorage_register(&param, &handle);
    		if (retval != NRF_SUCCESS){
    				bsp_indication_set(BSP_INDICATE_FATAL_ERROR);
    		}
    		
    //		//Get block identifiers
    		pstorage_block_identifier_get(&handle, 3, &block_3_handle);
    
    // CLEAR ************************		 
    		//Clear 16 bytes, starting from block 3
    		pstorage_wait_handle = block_3_handle.block_id;            //Specify which pstorage handle to wait for
    		pstorage_wait_flag = 1;
    		pstorage_clear(&block_3_handle, 16);  
    		while(pstorage_wait_flag) { power_manage(); }              //Sleep until clear operation is finished.		
    // CLEAR ************************			
    
    // assign source datas  ********************************	
    		for (uint32_t i = 0; i < 6; i++)				
    		{
    			source_data_3[i] = p_data[i];
    		}
    // ******************************************************		
    		// STORE DATA
    		pstorage_wait_handle = block_3_handle.block_id;            //Specify which pstorage handle to wait for
    		pstorage_wait_flag = 1;                                    //Set the wait flag. Cleared in the example_cb_handler
    		pstorage_store(&block_3_handle, source_data_3, 16, 0);     //Write to flash, only one block is allowed for each pstorage_store command
    		if(retval != NRF_SUCCESS)
    		{
    				bsp_indication_set(BSP_INDICATE_RCV_ERROR);
    		}
    		while(pstorage_wait_flag) { power_manage(); }              //Sleep until store operation is finished.
    }

    I then entered any uint8_t some_array[] instead of p_data and it was done in SDK 8. But now I can not reach the data I write with FDS. What I want is actually very simple, but I guess I can not tell because my English is weak.

  • purgoufr said:
    "..\..\..\main.c(387): error:  #44: expression must have pointer type"

    Can you share the relevant code, I do not know what you are referring to.

    The record you want to write needs only a pointer to an address in memory and the length in words(4bytes). You can store as many words in your record as long as you comply with the following requirement:

    length_in_words + FDS_HEADER_SIZE >= FDS_PAGE_SIZE - FDS_PAGE_TAG_SIZE

    They way a C compiler accesses a given element in an array is to use the address of the initial element 0 and add the size of the array type multiplied by the element's index number.

    Say an uint32_t my_array[5]; is located at address 0x2000B000:

    If you want to access element 3 of my_array the compiler will take the address of element 0(0x2000B000) and add 3 * size_of(uint32_t) = 0x2000B000 +  0xC = 0x2000B00C. 

    This means that you can access any array's elements as long as you have the starting address and the type size. 

    // accesing the 3rd element of an array. 
    
    uint32_t my_array[5] = {0x00, 0x01, 0x02, 0x03, 0x04};
    
    // Referencing the the array:
    uint32_t * p_array = &my_array; // p_array = address of element 0 of my_array
    
    // Dereferencing the pointer that points to the array:
    uint32_t data = *p_array[3];

  • my write function;

    static ret_code_t kls_fds_write(uint32_t file_id, uint32_t record_key , uint8_t write_data[])
    {		
    	fds_record_t        record;
    	fds_record_desc_t   record_desc;
    	
    	// Set up record.
    	record.file_id           = file_id;
    	record.key               = record_key;
    	record.data.p_data       = &write_data;
    	record.data.length_words = sizeof(write_data);   //(sizeof(write_data) + 3) / sizeof(uint32_t);
    	
    	ret_code_t rc;
    	rc = fds_record_write(&record_desc, &record);
    	if (rc != FDS_SUCCESS)
    	{
    			/* Handle error. */
    			NRF_LOG_INFO("FDS Write Handle error.");
    			return rc;
    	}
    	NRF_LOG_INFO("Writing Record ID = %d \r\n",record_desc.record_id);
    	return NRF_SUCCESS;
    	
    }

    my read function

    static ret_code_t kls_fds_read(uint32_t file_id, uint32_t relevant_record_key , uint8_t read_data[])
    {	
    		fds_flash_record_t  flash_record;
    		fds_record_desc_t   record_desc;
    		fds_find_token_t    ftok;
    		/* It is required to zero the token before first use. */
    		memset(&ftok, 0x00, sizeof(fds_find_token_t));
    		
    		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, relevant_record_key, &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);
    	
    
    				uint8_t * pointer_to_record_data;
    				pointer_to_record_data = (uint8_t *)flash_record.p_data;
    
    				if(flash_record.p_header->record_key == relevant_record_key)
    				{
    					for(uint8_t i = 0; i <flash_record.p_header->length_words; i++)
    					{
    							read_data[i] = *pointer_to_record_data;
    							pointer_to_record_data++;
    					}
    				}
    
    				NRF_LOG_INFO("Data = ");
    				NRF_LOG_HEXDUMP_INFO(read_data, sizeof(read_data));
    				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;		
    }

    I use my write function in save function

    static void save_data( uint8_t *p_data)
    {
    	NRF_LOG_INFO("save_data");
    	uint8_t source_data_0[10] ;			
    	
    	// assign source datas  ********************************	
    	for (uint32_t i = 0; i < 10; i++)				
    	{
    		source_data_0[i] = p_data[i];
    	}
    	while (flag_write_fds == false);
    	kls_fds_write(FILE_ID, RECORD_KEY ,source_data_0);
    	
    	NRF_LOG_HEXDUMP_INFO(source_data_0, sizeof(source_data_0));
    	
    	allow_advertisement = false;
    
    }

    save function used in nus_data_handler

    static void nus_data_handler(ble_nus_evt_t * p_evt)
    {
    	memset(nus_rx_data, 0, sizeof(nus_rx_data));
    	
        if (p_evt->type == BLE_NUS_EVT_RX_DATA)
        {
            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 (uint8_t i = 0; i < p_evt->params.rx_data.length; i++)
            {
    			nus_rx_data[i]= p_evt->params.rx_data.p_data[i];
    		}
    
    		save_data(nus_rx_data);
    
        }
    }

    So I want to;

    1- write "aaaaaaaaaa" in nRF Toolbox-> UART

    2- store the "aaaaaaaaaa" in static uint8_t nus_rx_data[16]; 

    3- write this nus_rx_data array with save function; "save_ssn(nus_rx_data);"

    4- Read the saved data so that you can use the data again when the power of the device is turned off;

    uint8_t dest_data_0[16] = {0};
    while (flag_write_fds == 0);
    kls_fds_read(FILE_ID, RECORD_KEY, dest_data_0);

  • I tried the memcpy function ;

    static ret_code_t kls_fds_read(uint32_t file_id, uint32_t relevant_record_key , uint8_t read_data[])
    {	
    	fds_flash_record_t  flash_record;
    	fds_record_desc_t   record_desc;
    	fds_find_token_t    ftok;
    	/* It is required to zero the token before first use. */
    	memset(&ftok, 0x00, sizeof(fds_find_token_t));
    		
    	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, relevant_record_key, &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);
    
    		memcpy(read_data, flash_record.p_data, flash_record.p_header->length_words * sizeof(uint32_t));
    				
    		NRF_LOG_INFO("Data: %u, Length: %u", read_data, flash_record.p_header->length_words * sizeof(uint32_t));
    				
    		// 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;		
    }
    

    I sent nus_data"A01100040" to write in fds

    0> <info> app: 41 30 31 31 30 30 30 34|A0110004
    0> <info> app: 30 00 |0. 

    Result;

    0> <info> app: Found Record ID = 1
    0>
    0> <info> app: Data: 536895120, Length: 4

    Unfortunately, I still could not write the data I wanted, and then I could not get the data itself (in uint8_t format). 

  • Hi Haakonsh,

    The write function does not work when there are 8 or more bytes. For example I modified like this;

    static uint8_t m_deadbeef[8] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08}; and it worked.

    static ret_code_t kls_fds_write(uint32_t write_file_id, uint32_t write_record_key , uint8_t write_data[])
    {		
    	//static uint32_t const m_deadbeef[2] = {0xDEADBEEF,0xBAADF00D};
    		static uint8_t m_deadbeef[8] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
    		fds_record_t        record;
    		fds_record_desc_t   record_desc;
    	
    		// Set up record.
    		record.file_id              = write_file_id;
    		record.key              		= write_record_key;
    		record.data.p_data       		= &m_deadbeef;
    		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 kls_fds_read(uint32_t read_file_id, uint32_t relevant_record_key , uint8_t read_data[])
    {	
    		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
    		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(read_file_id, relevant_record_key, &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);
    
    				data = (uint8_t *) flash_record.p_data;
    				for (uint8_t i=0;i<flash_record.p_header->length_words;i++)
    				{
    					read_data[i] = data[i];
    				}
    
    				
    				NRF_LOG_HEXDUMP_INFO(read_data, sizeof(read_data));
    				// 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;	
    }

    But I tried this;

    static uint8_t m_deadbeef[10] = {0x41,0x30,0x31,0x31,0x30,0x30,0x30,0x34,0x30,0x24}; and it did not work. 

    It does not work if it is bigger than eight. 

    Do you have any suggestion for that?

Related