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

Flash Data Storage

hi nordic Have a code project sample shows the typical use Flash applications in data storage? I see

[code](infocenter.nordicsemi.com/index.jsp.
    my code
`
#define FILE_ID     0x1111
#define REC_KEY     0x2222

static void fds_evt_handler(ret_code_t       result,
                            fds_cmd_id_t     cmd,
                            fds_record_id_t  record_id,
                            fds_record_key_t record_key)
{
    // Handle events here
}

ret_code_t module_fds_register(void)
{
    ret_code_t retval = fds_register(fds_evt_handler);
    if(retval != NRF_SUCCESS)
    {
        // Registering of callback handler failed.
        return retval;
    }

    retval = fds_init();
    if (retval != NRF_SUCCESS)
    {
        // Error.
        return retval;
    }
    return retval;
}

ret_code_t module_fds_write(uint32_t *p_data)
{

    ret_code_t         retval;
    fds_record_key_t   key;
    fds_record_chunk_t chunk;
    fds_record_desc_t  descriptor;

    // Fill in the record keys.
    key.type     = REC_KEY;
    key.instance = FILE_ID;

    // Initialize the record chunk, pointing it to the data to be stored.
    chunk.p_data       = p_data;
    chunk.length_words = 1;

    // Write the record to flash.
    retval = fds_write(&descriptor,
                       key,
                       1 ,  /*number of chunks*/
                       &chunk);
    if (retval != NRF_SUCCESS)
    {
        // Error.
    }
    return  retval;
    // The command was queued. Wait for a callback signalling its completion.

}

ret_code_t module_fds_read(uint32_t p_data ,fds_length_t length_words)
{
    fds_type_id_t     type;
    fds_instance_id_t inst;
    fds_find_token_t  tok;
    fds_record_desc_t descriptor;
    fds_record_t      record;

    // Set the record keys.
    type = REC_KEY;
    inst = FILE_ID;

    //SEGGER_RTT_printf(0, " module_fds_read\n");
    // Loop until all records with the given key pair has been found.
    if(fds_find(type, inst, &descriptor, &tok) == NRF_SUCCESS)
    {
        // A record was found. Open the record to check its contents.
        fds_open(&descriptor, &record);

        // Cast the data.
        *p_data = (uint32_t)(*record.p_data); 

        // When you are done, close the record using its descriptor.
        fds_close(&descriptor);
    }

}
`

Writing down a record and Retrieving data is no SOME_VALUE.

  • Hi Bui, Now It does work and I just erase whole flash and re-download again. Before error happen in peer_manager_init always. I will keep try this FDS funs.

    Thanks a lot.

  • Hi, I also mask these code because your command. // call the garbage collector to empty them, don't need to do this all the time, this is just for demonstration //ret_code_t ret = fds_gc(); //if (ret != FDS_SUCCESS) //{ // return ret; //}

    Does it matter?

  • Hi, Now I separate the example code one is read and other is write.

    the source code are below and I just define global uint32_t array name is m_tbd_obj.fds_para, len is 12. When MCU pwr on it will does

    err_code =fds_test_init(); APP_ERROR_CHECK(err_code); m_fds_read ();

    in main fun, and when I got new parameter write to flash in other section but I got crash. It seems init(fds_register/fds_init) -> read and write or write and read this kinds order done. Then no matter how many just write or read in other section then no error happen.

    Does that right?

    static void my_fds_evt_handler(fds_evt_t const * const p_fds_evt)
    {
        switch (p_fds_evt->id)
        {
            case FDS_EVT_INIT:
                if (p_fds_evt->result != FDS_SUCCESS)
                {
                    // Initialization failed.
                }
                break;
    				case FDS_EVT_WRITE:
    						if (p_fds_evt->result == FDS_SUCCESS)
    						{
    							write_flag=1;
    						}
    						break;
            default:
                break;
        }
    }
    
    void m_fds_write(void)
    {
    	ret_code_t err_code;
    	err_code = fds_test_find_and_delete();
    	APP_ERROR_CHECK(err_code);
    	
    	err_code =fds_test_write();
    	APP_ERROR_CHECK(err_code);
    	while (write_flag==0);//wait until the write is finished. 
    }
    
    void m_fds_read(void)
    {
    	ret_code_t err_code;
    	err_code = fds_read();
    	APP_ERROR_CHECK(err_code);
    }
    
    static ret_code_t fds_read(void)
    {
    		#define FILE_ID     0x1111
    		#define REC_KEY     0x2222
    		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
    		uint32_t *data;
    		uint32_t err_code;
    		
    		printf("Start searching... \r\n");
    		// Loop until all records with the given key and file ID have been found.
    		while (fds_record_find(FILE_ID, REC_KEY, &record_desc, &ftok) == FDS_SUCCESS)
    		{
    				err_code = fds_record_open(&record_desc, &flash_record);
    				if ( err_code != FDS_SUCCESS)
    				{
    					return err_code;		
    				}
    				
    				printf("Found Record ID = %d\r\n",record_desc.record_id);
    				printf("Data = ");
    				data = (uint32_t *) flash_record.p_data;
    				for (uint8_t i=0;i<flash_record.p_header->tl.length_words;i++)
    				{
    					  m_tbd_obj.fds_para[i] = data[i];
    					  printf("%d ",m_tbd_obj.fds_para[i]);
    				}
    				printf("\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;
    }
    
    static ret_code_t fds_test_write(void)
    {
    		#define FILE_ID     0x1111
    		#define REC_KEY     0x2222
    		//static uint32_t const m_deadbeef[2] = {0x98765432,0x23456789};
    		fds_record_t        record;
    		fds_record_desc_t   record_desc;
    		fds_record_chunk_t  record_chunk;
    	
    	  for(int i=0; i<12; i++){
    			  m_tbd_obj.fds_para[i]= i*100;
    		}
    	
    		// Set up data.
    		record_chunk.p_data      = m_tbd_obj.fds_para;//m_deadbeef;
    		record_chunk.length_words= 12;
    		// Set up record.
    		record.file_id           = FILE_ID;
    		record.key               = REC_KEY;
    		record.data.p_chunks     = &record_chunk;
    		record.data.num_chunks   = 1;
    				
    		ret_code_t ret = fds_record_write(&record_desc, &record);
    		if (ret != FDS_SUCCESS)
    		{
    				return ret;
    		}
    		 printf("Writing Record ID = %d \r\n",record_desc.record_id);
    		return NRF_SUCCESS;
    }
    
    static ret_code_t fds_test_find_and_delete (void)
    {
    	  #define FILE_ID     0x1111
    		#define REC_KEY     0x2222
    		fds_record_desc_t   record_desc;
    		fds_find_token_t    ftok;
    	
    		ftok.page=0;
    		ftok.p_addr=NULL;
    		// Loop and find records with same ID and rec key and mark them as deleted. 
    		while (fds_record_find(FILE_ID, REC_KEY, &record_desc, &ftok) == FDS_SUCCESS)
    		{
    			fds_record_delete(&record_desc);
    			printf("Deleted record ID: %d \r\n",record_desc.record_id);
    		}
    		// call the garbage collector to empty them, don't need to do this all the time, this is just for demonstration
    		ret_code_t ret = fds_gc();
    		if (ret != FDS_SUCCESS)
    		{
    				return ret;
    		}
    		return NRF_SUCCESS;
    }
    
    static ret_code_t fds_test_init (void)
    {
    		ret_code_t ret = fds_register(my_fds_evt_handler);
    		if (ret != FDS_SUCCESS)
    		{
    					return ret;	
    		}
    		
    		ret = fds_init();
    		if (ret != FDS_SUCCESS)
    		{
    				return ret;
    		}
    		return NRF_SUCCESS;
    }
    
    int main(void)
    {
    	  ret_code_t err_code;
        bool     erase_bonds;
    	  //===Init Whole Object=============================================
    	  memset(&status_obj,  0, sizeof(status_obj));//system use object
    	  memset(&ur_obj,      0, sizeof(ur_obj));
    	  memset(&sc_obj,      0, sizeof(sc_obj));
        memset(&dev_obj,     0, sizeof(dev_obj));
    	  memset(&hr_obj,      0, sizeof(hr_obj));//client object
    	  memset(&cp_obj,      0, sizeof(cp_obj));
    	  memset(&spd_obj,     0, sizeof(spd_obj));
    	  memset(&cad_obj,     0, sizeof(cad_obj));
    	  memset(&cmb_obj,     0, sizeof(cmb_obj));
    	  memset(&m_spd_obj,   0, sizeof(m_spd_obj));//data object
    	  memset(&m_cad_obj,   0, sizeof(m_cad_obj));
    	  memset(&m_cmb_obj,   0, sizeof(m_cmb_obj));
    	  memset(&m_tbd_obj,   0, sizeof(m_tbd_obj));
    	  memset(m_tbd_obj.fds_para, 0xFFFFFFFF, 12);
    	
    	  tbd_parameter_default(&m_tbd_obj);
        flash_word_read((uint32_t *)0x10001080, &UICR_ADDR_0x80);//Read the Device number
    	  
    	  //===Sys Init======================================================
    		timers_init   ();
        uart_init     ();
    		
    		saadc_sampling_event_init();
        saadc_init();
        saadc_sampling_event_enable();
    		
        ble_stack_init();
        peer_manager_init(erase_bonds);
        db_discovery_init();
    		
        //===BLE Device Init===============================================
        hrs_c_init    ();//Heart Rate
    	  speed_c_init  ();//CSC-Speed
    	  cadence_c_init();//CSC-Cadence
    	  combo_c_init  ();//CSC-Combo
    		//Still wait for HW CP-Not yet
    		timers_start    ();
        gap_params_init ();
        conn_params_init();
        services_init   ();
        advertising_init();
    		
    		//===Read The parameter ===========================================
    	  
        err_code =fds_test_init();
    		APP_ERROR_CHECK(err_code);
    		m_fds_read ();
    	  m_fds_write();//Here I force write the same data again avoid crash
    		
    	 
        adv_start();
    		//===nRF52832 every thing is ready=================================
    	  printf("TBD SYS ON\r\n");
    		
        for (;;)
        {
            power_manage();// Wait for BLE events.
        }
    }
    
  • @Vincent: You should call fds_gc() when there is no space in flash.

    It's not easy to read the code when you paste it without code tag (the 101010 button on the bar). Anyway, it's only to post a small snippet not the full main.c code. It's very hard to read and follow.

    It's better that you attach the file instead of posting the code. You can create a new case to do that.

    I am still not quite sure I fully understand what your problem is. What do you mean by "got crash"? If you can explain it shortly with small step by step it's easier to understand.

    This case is already too long, please open a new question.

  • OK.... For now it does work fine and I will keep try and test. Thanks a lot.

Related