Hi, I'm working on porting my application from SDK 11.0 to 12.2.0 and I have a problem initializing the buttonless DFU service. I've flashed the secure bootloader and appropriate settings. The bootloader itself is working correctly (I can upload a Nordic test image just fine).
If I add the BLE DFU service during services_init()
the device resets. I've narrowed the fault down to this portion of the nrf_dfu_settings.c
:
void nrf_dfu_settings_init(void)
{
NRF_LOG_INFO("running nrf_dfu_settings_init\r\n");
volatile uint32_t crc;
flash_operation_pending = false;
// Copy the DFU settings out of flash and into a buffer in RAM.
memcpy((void*)&s_dfu_settings, &m_dfu_settings_buffer[0], sizeof(nrf_dfu_settings_t));
if(s_dfu_settings.crc != 0xFFFFFFFF)
{
// CRC is set. Content must be valid
crc = nrf_dfu_settings_calculate_crc();
if(crc == s_dfu_settings.crc)
{
return;
}
}
// Reached if nothing is configured or if CRC was wrong
NRF_LOG_INFO("!!!!!!!!!!!!!!! Resetting bootloader settings !!!!!!!!!!!\r\n");
memset(&s_dfu_settings, 0x00, sizeof(nrf_dfu_settings_t));
s_dfu_settings.settings_version = NRF_DFU_SETTINGS_VERSION;
APP_ERROR_CHECK(nrf_dfu_settings_write(NULL));
}
ret_code_t nrf_dfu_settings_write(dfu_flash_callback_t callback)
{
ret_code_t err_code = FS_SUCCESS;
NRF_LOG_INFO("Erasing old settings at: 0x%08x\r\n", (uint32_t)&m_dfu_settings_buffer[0]);
// Wait for any ongoing operation (because of multiple calls to nrf_dfu_settings_write)
wait_for_pending();
flash_operation_pending = true;
m_callback = callback;
do
{
wait_for_queue();
// Not setting the callback function because ERASE is required before STORE
// Only report completion on successful STORE.
err_code = nrf_dfu_flash_erase((uint32_t*)&m_dfu_settings_buffer[0], 1, NULL);
} while (err_code == FS_ERR_QUEUE_FULL);
if (err_code != FS_SUCCESS)
{
NRF_LOG_ERROR("Erasing from flash memory failed.\r\n");
flash_operation_pending = false;
return NRF_ERROR_INTERNAL;
}
s_dfu_settings.crc = nrf_dfu_settings_calculate_crc();
NRF_LOG_INFO("Writing 0x%08x words\r\n", sizeof(nrf_dfu_settings_t)/4);
static nrf_dfu_settings_t temp_dfu_settings;
memcpy(&temp_dfu_settings, &s_dfu_settings, sizeof(nrf_dfu_settings_t));
do
{
wait_for_queue();
err_code = nrf_dfu_flash_store((uint32_t*)&m_dfu_settings_buffer[0],
(uint32_t*)&temp_dfu_settings,
sizeof(nrf_dfu_settings_t)/4,
dfu_settings_write_callback);
} while (err_code == FS_ERR_QUEUE_FULL);
if (err_code != FS_SUCCESS)
{
NRF_LOG_ERROR("Storing to flash memory failed.\r\n");
flash_operation_pending = false;
return NRF_ERROR_INTERNAL;
}
NRF_LOG_INFO("Writing settings...\r\n");
return NRF_SUCCESS;
}
The stored CRC is just 0, so it does not match the calculated one. Thus the application resets the bootloader settings. This alarms me since nrfutil
reports a CRC when I generate the settings hex file.
But anyway, the value returned by this line:
err_code = nrf_dfu_flash_erase((uint32_t*)&m_dfu_settings_buffer[0], 1, NULL);
is FS_ERR_UNALIGNED_ADDR
, and I'm not quite sure what's going on. The bootloader settings address is configured as 0x0007F000
, which should be aligned with a a page boundary.