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;