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

DFU - problem with moving data from external to internal flash

Hi,

I'm working on modification of DFU Bootloader to use external flash instead of standard Dual-bank or Single-bank version. Now it works quite well, but I have problems with moving data received over BT and stored in external memory to Bank 0 (in MCU flash).

I have edited function nrf_dfu_app_continue() to my needs. But there was a problem.

I tested it with blinky example hex as an update package. When I loaded 4096 bytes from external memory and wanted to store them in internal memory (using function nrf_dfu_flash_store) it looks that store function called in first iteration of the loop is performed only when second iteration is already running – therefore it uses wrong data (stored yet in page_buff array), but it is written into first page of internal memory. In that case I have data from second page of external memory both in first and second page of internal memory - and it's wrong. I expect, that I have to wait until store operation is completely finished and then start second iteration - but how to do it? Temporarily I solved it using two buffers which are switched each iteration of the loop, but I don't think it's correct solution.

And second question: I have to use wait_for_queue() function before each operation with internal flash - otherwise I'm getting errors that it cannot erase data on specified address etc. In original function these function calls are not necessary, but for me it's only option - why?

Thank you in advance for your help!

There is my code of modified function:

    uint32_t image_size = image_info[0];
    uint32_t const split_size  = CODE_PAGE_SIZE;

    uint32_t ret_val            = NRF_SUCCESS;
    uint32_t target_addr        = MAIN_APPLICATION_START_ADDR;
    uint32_t length_left        = image_size;
    uint32_t cur_len;
    uint32_t crc;
	uint32_t external_memory_address = 0;
	uint16_t external_memory_offset;
	uint16_t i;
	uint8_t	rx_buff[256];
	bool use_buff_2 = false;

    NRF_LOG_DEBUG("Enter nrf_dfu_app_continue\r\n");
    do
    {

        cur_len = (length_left > split_size) ? split_size : length_left;
		
		// Change used buffer
		if(!use_buff_2)
		{
			memset(page_buff, 0, 4096);
		}
		
		else 
		{
			memset(page_buff2, 0, 4096);
		}

		// Get 4096 bytes from external memory		
		external_memory_offset = 0;
		while(external_memory_offset < 4096)
		{
			memset(rx_buff,0,256);
			
			// My function to read data from external memory over SPI
			ReadPage(rx_buff, external_memory_address+external_memory_offset, 256);

			for(i=0;i<256;i++)
			{
				if(use_buff_2)
				{
					page_buff2[i+external_memory_offset] = rx_buff[i]; 
				}
				else 
				{
					page_buff[i+external_memory_offset] = rx_buff[i]; 
				}
			}
			external_memory_offset += 256;
		}
		 	
        // Erase the target page
		wait_for_queue();		
        ret_val = nrf_dfu_flash_erase((uint32_t*) target_addr, split_size / CODE_PAGE_SIZE, NULL);
        if (ret_val != NRF_SUCCESS)
        {
            return ret_val;
        }
		
        // Flash one page
		wait_for_queue();		
		ret_val = nrf_dfu_flash_store((uint32_t*)target_addr, (!use_buff_2) ? (uint32_t*)page_buff : (uint32_t*)page_buff2, cur_len, NULL);
        if (ret_val != NRF_SUCCESS)
        {
            return ret_val;
        }

		// TODO: compare copied data with original in external memory
		
        s_dfu_settings.write_offset += cur_len;
        ret_val = nrf_dfu_settings_write(NULL);

        target_addr += cur_len;
		external_memory_address += cur_len;
        length_left -= cur_len;
		use_buff_2 = !use_buff_2;
    }
    while(length_left > 0);

	wait_for_queue();		
	crc = crc32_compute((uint8_t*)MAIN_APPLICATION_START_ADDR, image_size, NULL);
	s_dfu_settings.bank_0.image_crc = crc;
	s_dfu_settings.bank_0.image_size = image_size;

    ret_val = nrf_dfu_settings_write(NULL); 
    return ret_val;
Parents
  • I'm using SDK 13.0.0, bootloader is based on example bootloader_secure_ble. My modified function nrf_dfu_app_continue() is called in nrf_dfu_data_req(), right before nrf_dfu_postvalidate() call.

    I'm not sure if softdevice is running during the call, but I think so, because BT communication is still working.

    wait_for_queue() is function from nrf_dfu_settings.c, which I only made extern to use in other functions. Its code:

    while (fs_queue_is_full())
    {
            delay_operation();
    }
    

    When I write only one page, it is OK - one page is correctly written.

    In SDK documentation there is comment to nrf_dfu_flash_store(): With SoftDevice, the operation is complete when the fstorage event is received. But I don't now how to work with that, I tried to use shared bool variable, which was set true when event occured, but it didn't work.

Reply
  • I'm using SDK 13.0.0, bootloader is based on example bootloader_secure_ble. My modified function nrf_dfu_app_continue() is called in nrf_dfu_data_req(), right before nrf_dfu_postvalidate() call.

    I'm not sure if softdevice is running during the call, but I think so, because BT communication is still working.

    wait_for_queue() is function from nrf_dfu_settings.c, which I only made extern to use in other functions. Its code:

    while (fs_queue_is_full())
    {
            delay_operation();
    }
    

    When I write only one page, it is OK - one page is correctly written.

    In SDK documentation there is comment to nrf_dfu_flash_store(): With SoftDevice, the operation is complete when the fstorage event is received. But I don't now how to work with that, I tried to use shared bool variable, which was set true when event occured, but it didn't work.

Children
No Data
Related