static void bootloader_settings_save(bootloader_settings_t * p_settings)
{
    nrf_flash_erase(m_bootsettings_handle,sizeof(bootloader_settings_t));


    nrf_flash_store(m_bootsettings_handle,
                    (uint8_t *)p_settings,
                    sizeof(bootloader_settings_t),
                    0);

    if (m_update_status == BOOTLOADER_SETTINGS_SAVING)
    {
        m_update_status = BOOTLOADER_COMPLETE;
    }
}
static void operation_execute(operation_t* p_op)
{
    switch (p_op->type)
    {
        case FLASH_OP_TYPE_ERASE:
            nrf_flash_erase((uint32_t*) p_op->operation.erase.start_addr, p_op->operation.erase.length);
            break;
        case FLASH_OP_TYPE_WRITE:
            nrf_flash_store((uint32_t*) p_op->operation.write.start_addr,
                            p_op->operation.write.p_data,
                            p_op->operation.write.length, 0);
            break;
        default:
            APP_ERROR_CHECK(NRF_ERROR_INVALID_DATA);
    }
}
/**@brief   Function for preparing of flash before receiving SoftDevice image.
 *
 * @details This function will erase current application area to ensure sufficient amount of
 *          storage for the SoftDevice image. Upon erase complete a callback will be done.
 *          See \ref dfu_bank_prepare_t for further details.
 */
static void dfu_prepare_func_app_erase(uint32_t image_size)
{

    if(m_start_packet.sd_image_size != 0)
    {
        mp_storage_handle_active = m_storage_handle_sd;    
    }
    else
    {
        mp_storage_handle_active = m_storage_handle_app;     
    }

    // Doing a SoftDevice update thus current application must be cleared to ensure enough space
    // for new SoftDevice.
    m_dfu_state = DFU_STATE_PREPARING;
    nrf_flash_erase(mp_storage_handle_active, m_image_size);
    
    m_functions.cleared();
    m_dfu_state = DFU_STATE_RDY;
}
/** Interrupt handling Flash operations. */
void FLASH_HANDLER_IRQHandler(void)
{
    flash_queue_entry_t flash_entry;
    uint32_t op_count = 0;
    while (fifo_pop(&m_flash_fifo, &flash_entry) == NRF_SUCCESS)
    {
        op_count++;
        bl_cmd_t rsp_cmd;
        if (flash_entry.type == FLASH_OP_TYPE_WRITE)
        {
            APP_ERROR_CHECK_BOOL(IS_WORD_ALIGNED(flash_entry.op.write.start_addr));
            APP_ERROR_CHECK_BOOL(IS_WORD_ALIGNED(flash_entry.op.write.length));
            APP_ERROR_CHECK_BOOL(IS_WORD_ALIGNED(flash_entry.op.write.p_data));
            __LOG("WRITING to 0x%x.(len %d)\n", flash_entry.op.write.start_addr, flash_entry.op.write.length);
            if (flash_entry.op.write.start_addr >= 0x20000000)
            {
                uint8_t* p_dst = ((uint8_t*) flash_entry.op.write.start_addr);
                for (uint32_t i = 0; i < flash_entry.op.write.length; ++i, p_dst++)
                {
                    *p_dst = (*p_dst & flash_entry.op.write.p_data[i]);
                }
            }
            else
            {
                nrf_flash_store((uint32_t*) flash_entry.op.write.start_addr,
                                            flash_entry.op.write.p_data,
                                            flash_entry.op.write.length, 0);
            }

            rsp_cmd.type                      = BL_CMD_TYPE_FLASH_WRITE_COMPLETE;
            rsp_cmd.params.flash.write.p_data = flash_entry.op.write.p_data;
        }
        else
        {
            __LOG("ERASING 0x%x.\n", flash_entry.op.erase.start_addr);
            if (flash_entry.op.erase.start_addr >= 0x20000000)
            {
                memset((uint32_t*) flash_entry.op.erase.start_addr, 0xFF, flash_entry.op.erase.length);
            }
            else
            {
                nrf_flash_erase((uint32_t*) flash_entry.op.erase.start_addr,
                                            flash_entry.op.erase.length);
            }
            rsp_cmd.type                      = BL_CMD_TYPE_FLASH_ERASE_COMPLETE;
            rsp_cmd.params.flash.erase.p_dest = (uint32_t*) flash_entry.op.erase.start_addr;
        }
        bl_cmd_handler(&rsp_cmd);
    }

    if (op_count > 0)
    {
        bl_cmd_t idle_cmd;
        idle_cmd.type = BL_CMD_TYPE_FLASH_ALL_COMPLETE;
        bl_cmd_handler(&idle_cmd);
    }
    if (fifo_is_empty(&m_flash_fifo) && m_go_to_app)
    {
        bl_info_entry_t* p_segment_entry = bootloader_info_entry_get(BL_INFO_TYPE_SEGMENT_APP);
        bootloader_util_app_start(p_segment_entry->segment.start);
    }
}