Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/dfu/flash_img.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ struct flash_img_context {
const struct flash_area *flash_area;
size_t bytes_written;
u16_t buf_bytes;
#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
off_t off_last;
#endif
};

/**
Expand Down
7 changes: 7 additions & 0 deletions include/dfu/mcuboot.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@

#define BOOT_IMG_VER_STRLEN_MAX 25 /* 255.255.65535.4294967295\0 */

/* Trailer: */
#define BOOT_MAX_ALIGN 8
#define BOOT_MAGIC_SZ 16

#define BOOT_TRAILER_IMG_STATUS_OFFS(bank_area) ((bank_area)->fa_size -\
BOOT_MAGIC_SZ -\
BOOT_MAX_ALIGN * 2)
/**
* @brief MCUboot image header representation for image version
*
Expand Down
10 changes: 10 additions & 0 deletions subsys/dfu/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ config IMG_BLOCK_BUF_SIZE
Size (in Bytes) of buffer for image writer. Must be a multiple of
the access alignment required by used flash driver.

config IMG_ERASE_PROGRESSIVELY
bool "Erase flash progressively when receiving new firmware"
depends on MCUBOOT_IMG_MANAGER
select FLASH_PAGE_LAYOUT
help
If enabled, flash is erased as necessary when receiving new firmware,
instead of erasing the whole image slot at once. This is necessary
on some hardware that has long erase times, to prevent long wait
times at the beginning of the DFU process.

module = IMG_MANAGER
module-str = image manager
source "subsys/logging/Kconfig.template.log_config"
Expand Down
2 changes: 0 additions & 2 deletions subsys/dfu/boot/mcuboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@
#define BOOT_HEADER_SIZE_V1 32

/* Trailer: */
#define BOOT_MAX_ALIGN 8
#define BOOT_MAGIC_SZ 16
#define BOOT_FLAG_SET 0x01
#define BOOT_FLAG_UNSET 0xff

Expand Down
75 changes: 75 additions & 0 deletions subsys/dfu/img_util/flash_img.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#include <dfu/flash_img.h>
#include <inttypes.h>

#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
#include <dfu/mcuboot.h>
#include <flash.h>
#endif

BUILD_ASSERT_MSG((CONFIG_IMG_BLOCK_BUF_SIZE % DT_FLASH_WRITE_BLOCK_SIZE == 0),
"CONFIG_IMG_BLOCK_BUF_SIZE is not a multiple of "
"DT_FLASH_WRITE_BLOCK_SIZE");
Expand Down Expand Up @@ -52,6 +57,63 @@ static bool flash_verify(const struct flash_area *fa, off_t offset,
return (len == 0) ? true : false;
}

#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY

static int flash_sector_from_off(struct flash_area const *fap, off_t off,
struct flash_sector *sector)
{
struct flash_pages_info page;
struct device *flash_dev;
int rc = -ENODEV;

flash_dev = flash_area_get_device(fap);
if (flash_dev) {
rc = flash_get_page_info_by_offs(flash_dev, off, &page);
if (rc == 0) {
sector->fs_off = page.start_offset;
sector->fs_size = page.size;
}
}

return rc;
}

/**
* Erase the image slot progressively
*
* This function erases a flash page to which offset belongs if only this page
* wasn't erased before.
*
* @param[in] ctx context of the image collection process.
* @param[in] off offset from the beginning of the image flash area beginning
*
* @return 0 on success, negative errno code on fail.
*/
static int flash_progressive_erase(struct flash_img_context *ctx, off_t off)
{
struct flash_sector sector;
int rc;

rc = flash_sector_from_off(ctx->flash_area, off, &sector);
if (rc) {
LOG_ERR("Unable to determine flash sector size");
} else {
if (ctx->off_last != sector.fs_off) {
ctx->off_last = sector.fs_off;
LOG_INF("Erasing sector at offset 0x%x", sector.fs_off);
rc = flash_area_erase(ctx->flash_area, sector.fs_off,
sector.fs_size);
if (rc) {
LOG_ERR("Error %d while erasing sector", rc);
}
}
}

return rc;
}

#endif /* CONFIG_IMG_ERASE_PROGRESSIVELY */

static int flash_sync(struct flash_img_context *ctx)
{
int rc = 0;
Expand All @@ -61,6 +123,11 @@ static int flash_sync(struct flash_img_context *ctx)
CONFIG_IMG_BLOCK_BUF_SIZE - ctx->buf_bytes);
}

#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
flash_progressive_erase(ctx, ctx->bytes_written +
CONFIG_IMG_BLOCK_BUF_SIZE);
#endif

rc = flash_area_write(ctx->flash_area, ctx->bytes_written, ctx->buf,
CONFIG_IMG_BLOCK_BUF_SIZE);
if (rc) {
Expand Down Expand Up @@ -121,6 +188,11 @@ int flash_img_buffered_write(struct flash_img_context *ctx, u8_t *data,
return rc;
}
}
#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
/* erase the image trailer area if it was not erased */
flash_progressive_erase(ctx,
BOOT_TRAILER_IMG_STATUS_OFFS(ctx->flash_area));
#endif

flash_area_close(ctx->flash_area);
ctx->flash_area = NULL;
Expand All @@ -137,6 +209,9 @@ int flash_img_init(struct flash_img_context *ctx)
{
ctx->bytes_written = 0;
ctx->buf_bytes = 0U;
#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
ctx->off_last = -1;
#endif
return flash_area_open(DT_FLASH_AREA_IMAGE_1_ID,
(const struct flash_area **)&(ctx->flash_area));
}
6 changes: 6 additions & 0 deletions subsys/usb/class/usb_dfu.c
Original file line number Diff line number Diff line change
Expand Up @@ -731,11 +731,17 @@ static void dfu_work_handler(struct k_work *item)

switch (dfu_data_worker.worker_state) {
case dfuIDLE:
/*
* If progressive erase is enabled, then erase take place while
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* If progressive erase is enabled, then erase take place while
* If progressive erase is enabled, erase takes place during

* image collection, so not erase whole bank at DFU beginning
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* image collection, so not erase whole bank at DFU beginning
* image collection, in order not to erase whole bank at DFU beginning

*/
#ifndef CONFIG_IMG_ERASE_PROGRESSIVELY
if (boot_erase_img_bank(DT_FLASH_AREA_IMAGE_1_ID)) {
dfu_data.state = dfuERROR;
dfu_data.status = errERASE;
break;
}
#endif
case dfuDNLOAD_IDLE:
dfu_flash_write(dfu_data_worker.buf,
dfu_data_worker.worker_len);
Expand Down