ret_code_t nrf_dfu_settings_write(dfu_flash_callback_t callback) { ret_code_t err_code; NRF_LOG_DEBUG("Writing settings..."); NRF_LOG_DEBUG("Erasing old settings at: 0x%08x", (uint32_t)m_dfu_settings_buffer); // 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, 1, NULL); if (err_code != NRF_SUCCESS) { NRF_LOG_ERROR("Could not erase the settings page!"); return NRF_ERROR_INTERNAL; } s_dfu_settings.crc = nrf_dfu_settings_crc_get(); static nrf_dfu_settings_t temp_dfu_settings; memcpy(&temp_dfu_settings, &s_dfu_settings, sizeof(nrf_dfu_settings_t)); err_code = nrf_dfu_flash_store((uint32_t)m_dfu_settings_buffer, &temp_dfu_settings, sizeof(nrf_dfu_settings_t), callback); if (err_code != NRF_SUCCESS) { NRF_LOG_ERROR("Could not write the DFU settings page!"); return NRF_ERROR_INTERNAL; } return NRF_SUCCESS; }
ret_code_t nrf_dfu_settings_write(dfu_flash_callback_t callback) { NRF_LOG_INFO("Erasing old settings at: 0x%08x\r\n", (uint32_t)&m_dfu_settings_buffer[0]); if (flash_operation_pending == true) { NRF_LOG_INFO("Could not queue writing of DFU Settings\r\n"); return NRF_ERROR_BUSY; } flash_operation_pending = true; m_callback = callback; if(nrf_dfu_flash_erase((uint32_t*)&m_dfu_settings_buffer[0], 1, NULL) != FS_SUCCESS) { flash_operation_pending = false; NRF_LOG_INFO("Failed to erase bootloader settings\r\n"); return NRF_ERROR_BUSY; } 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)); if(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) != FS_SUCCESS) { flash_operation_pending = false; NRF_LOG_INFO("Failed to write bootloader settings\r\n"); return NRF_ERROR_BUSY; } NRF_LOG_INFO("Writing settings...\r\n"); return NRF_SUCCESS; }
/** @brief Function to continue App update * * @details This function will be called after reset if there is a valid application in Bank1 * required to be copied down to bank0. * * @param[in] src_addr Source address of the application to copy from Bank1 to Bank0. * * @retval NRF_SUCCESS Continuation was successful. * @retval NRF_ERROR_NULL Invalid data during compare. * @retval FS_ERR_UNALIGNED_ADDR A call to fstorage was not aligned to a page boundary or the address was not word aliged. * @retval FS_ERR_INVALID_ADDR The destination of a call to fstorage does not point to * the start of a flash page or the operation would * go beyond the flash memory boundary. * @retval FS_ERR_NOT_INITIALIZED The fstorage module is not initialized. * @retval FS_ERR_INVALID_CFG The initialization of the fstorage module is invalid. * @retval FS_ERR_NULL_ARG A call to fstorage had an invalid NULL argument. * @retval FS_ERR_INVALID_ARG A call to fstorage had invalid arguments. * @retval FS_ERR_QUEUE_FULL If the internal operation queue of the fstorage module is full. * @retval FS_ERR_FAILURE_SINCE_LAST If an error occurred in another transaction and fstorage cannot continue before * the event has been dealt with. */ static uint32_t nrf_dfu_app_continue(uint32_t src_addr) { // This function only in use when new app is present in bank 1 uint32_t const image_size = s_dfu_settings.bank_1.image_size; uint32_t const split_size = CODE_PAGE_SIZE; // Arbitrary number that must be page aligned uint32_t ret_val = NRF_SUCCESS; uint32_t target_addr = MAIN_APPLICATION_START_ADDR + s_dfu_settings.write_offset; uint32_t length_left = (image_size - s_dfu_settings.write_offset); uint32_t cur_len; uint32_t crc; NRF_LOG_INFO("Enter nrf_dfu_app_continue\r\n"); // Copy the application down safely do { cur_len = (length_left > split_size) ? split_size : length_left; // Erase the target page 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 ret_val = nrf_dfu_flash_store((uint32_t*)target_addr, (uint32_t*)src_addr, cur_len, NULL); if (ret_val != NRF_SUCCESS) { return ret_val; } ret_val = nrf_dfu_mbr_compare((uint32_t*)target_addr, (uint32_t*)src_addr, cur_len); if (ret_val != NRF_SUCCESS) { // We will not retry the copy NRF_LOG_INFO("Invalid data during compare: target: 0x%08x, src: 0x%08x\r\n", target_addr, src_addr); return ret_val; } // Erase the head (to handle growing bank 0) ret_val = nrf_dfu_flash_erase((uint32_t*) src_addr, split_size / CODE_PAGE_SIZE, NULL); if (ret_val != NRF_SUCCESS) { NRF_LOG_INFO("App update: Failure erasing page at addr: 0x%08x\r\n", src_addr); return ret_val; } s_dfu_settings.write_offset += cur_len; (void)nrf_dfu_settings_write(NULL); target_addr += cur_len; src_addr += cur_len; length_left -= cur_len; } while(length_left > 0); // Check the crc of the copied data. Enable if so. crc = crc32_compute((uint8_t*)MAIN_APPLICATION_START_ADDR, image_size, NULL); if (crc == s_dfu_settings.bank_1.image_crc) { NRF_LOG_INFO("Setting app as valid\r\n"); s_dfu_settings.bank_0.bank_code = NRF_DFU_BANK_VALID_APP; s_dfu_settings.bank_0.image_crc = crc; s_dfu_settings.bank_0.image_size = image_size; } else { NRF_LOG_INFO("CRC computation failed for copied app: src crc: 0x%08x, res crc: 0x08x\r\n", s_dfu_settings.bank_1.image_crc, crc); } nrf_dfu_invalidate_bank(&s_dfu_settings.bank_1); (void)nrf_dfu_settings_write(NULL); return ret_val; }