Skip to content

Commit dffcfd8

Browse files
nvlsianpunashif
authored andcommitted
dfu: introduce progressive erasing
Patch adds option for progressive erase of firmware image. When using this, flash is erased as necessary when receiving new firmware, instead of erasing the whole image slot at once. This is useful on some hardware (like nRF52840) that has long erase times, to prevent long wait times at the beginning of the DFU process. Signed-off-by: Andrzej Puzdrowski <[email protected]>
1 parent 0dd3b42 commit dffcfd8

File tree

5 files changed

+95
-2
lines changed

5 files changed

+95
-2
lines changed

include/dfu/flash_img.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ struct flash_img_context {
1919
const struct flash_area *flash_area;
2020
size_t bytes_written;
2121
u16_t buf_bytes;
22+
#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
23+
off_t off_last;
24+
#endif
2225
};
2326

2427
/**

include/dfu/mcuboot.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@
3030

3131
#define BOOT_IMG_VER_STRLEN_MAX 25 /* 255.255.65535.4294967295\0 */
3232

33+
/* Trailer: */
34+
#define BOOT_MAX_ALIGN 8
35+
#define BOOT_MAGIC_SZ 16
36+
37+
#define BOOT_TRAILER_IMG_STATUS_OFFS(bank_area) ((bank_area)->fa_size -\
38+
BOOT_MAGIC_SZ -\
39+
BOOT_MAX_ALIGN * 2)
3340
/**
3441
* @brief MCUboot image header representation for image version
3542
*

subsys/dfu/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ config IMG_BLOCK_BUF_SIZE
4141
Size (in Bytes) of buffer for image writer. Must be a multiple of
4242
the access alignment required by used flash driver.
4343

44+
config IMG_ERASE_PROGRESSIVELY
45+
bool "Erase flash progressively when receiving new firmware"
46+
depends on MCUBOOT_IMG_MANAGER
47+
select FLASH_PAGE_LAYOUT
48+
help
49+
If enabled, flash is erased as necessary when receiving new firmware,
50+
instead of erasing the whole image slot at once. This is necessary
51+
on some hardware that has long erase times, to prevent long wait
52+
times at the beginning of the DFU process.
53+
4454
module = IMG_MANAGER
4555
module-str = image manager
4656
source "subsys/logging/Kconfig.template.log_config"

subsys/dfu/boot/mcuboot.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@
3232
#define BOOT_HEADER_SIZE_V1 32
3333

3434
/* Trailer: */
35-
#define BOOT_MAX_ALIGN 8
36-
#define BOOT_MAGIC_SZ 16
3735
#define BOOT_FLAG_SET 0x01
3836
#define BOOT_FLAG_UNSET 0xff
3937

subsys/dfu/img_util/flash_img.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
1818
#include <dfu/flash_img.h>
1919
#include <inttypes.h>
2020

21+
#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
22+
#include <dfu/mcuboot.h>
23+
#include <flash.h>
24+
#endif
25+
2126
BUILD_ASSERT_MSG((CONFIG_IMG_BLOCK_BUF_SIZE % DT_FLASH_WRITE_BLOCK_SIZE == 0),
2227
"CONFIG_IMG_BLOCK_BUF_SIZE is not a multiple of "
2328
"DT_FLASH_WRITE_BLOCK_SIZE");
@@ -52,6 +57,63 @@ static bool flash_verify(const struct flash_area *fa, off_t offset,
5257
return (len == 0) ? true : false;
5358
}
5459

60+
#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
61+
62+
static int flash_sector_from_off(struct flash_area const *fap, off_t off,
63+
struct flash_sector *sector)
64+
{
65+
struct flash_pages_info page;
66+
struct device *flash_dev;
67+
int rc = -ENODEV;
68+
69+
flash_dev = flash_area_get_device(fap);
70+
if (flash_dev) {
71+
rc = flash_get_page_info_by_offs(flash_dev, off, &page);
72+
if (rc == 0) {
73+
sector->fs_off = page.start_offset;
74+
sector->fs_size = page.size;
75+
}
76+
}
77+
78+
return rc;
79+
}
80+
81+
/**
82+
* Erase the image slot progressively
83+
*
84+
* This function erases a flash page to which offset belongs if only this page
85+
* wasn't erased before.
86+
*
87+
* @param[in] ctx context of the image collection process.
88+
* @param[in] off offset from the beginning of the image flash area beginning
89+
*
90+
* @return 0 on success, negative errno code on fail.
91+
*/
92+
static int flash_progressive_erase(struct flash_img_context *ctx, off_t off)
93+
{
94+
struct flash_sector sector;
95+
int rc;
96+
97+
rc = flash_sector_from_off(ctx->flash_area, off, &sector);
98+
if (rc) {
99+
LOG_ERR("Unable to determine flash sector size");
100+
} else {
101+
if (ctx->off_last != sector.fs_off) {
102+
ctx->off_last = sector.fs_off;
103+
LOG_INF("Erasing sector at offset 0x%x", sector.fs_off);
104+
rc = flash_area_erase(ctx->flash_area, sector.fs_off,
105+
sector.fs_size);
106+
if (rc) {
107+
LOG_ERR("Error %d while erasing sector", rc);
108+
}
109+
}
110+
}
111+
112+
return rc;
113+
}
114+
115+
#endif /* CONFIG_IMG_ERASE_PROGRESSIVELY */
116+
55117
static int flash_sync(struct flash_img_context *ctx)
56118
{
57119
int rc = 0;
@@ -61,6 +123,11 @@ static int flash_sync(struct flash_img_context *ctx)
61123
CONFIG_IMG_BLOCK_BUF_SIZE - ctx->buf_bytes);
62124
}
63125

126+
#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
127+
flash_progressive_erase(ctx, ctx->bytes_written +
128+
CONFIG_IMG_BLOCK_BUF_SIZE);
129+
#endif
130+
64131
rc = flash_area_write(ctx->flash_area, ctx->bytes_written, ctx->buf,
65132
CONFIG_IMG_BLOCK_BUF_SIZE);
66133
if (rc) {
@@ -121,6 +188,11 @@ int flash_img_buffered_write(struct flash_img_context *ctx, u8_t *data,
121188
return rc;
122189
}
123190
}
191+
#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
192+
/* erase the image trailer area if it was not erased */
193+
flash_progressive_erase(ctx,
194+
BOOT_TRAILER_IMG_STATUS_OFFS(ctx->flash_area));
195+
#endif
124196

125197
flash_area_close(ctx->flash_area);
126198
ctx->flash_area = NULL;
@@ -137,6 +209,9 @@ int flash_img_init(struct flash_img_context *ctx)
137209
{
138210
ctx->bytes_written = 0;
139211
ctx->buf_bytes = 0U;
212+
#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
213+
ctx->off_last = -1;
214+
#endif
140215
return flash_area_open(DT_FLASH_AREA_IMAGE_1_ID,
141216
(const struct flash_area **)&(ctx->flash_area));
142217
}

0 commit comments

Comments
 (0)