Skip to content

Commit 514cbbf

Browse files
committed
mgmt: mcumgr: grp: img_mgmt: Skip erased sectors when erasing
Skips erasing sectors that are already erased in a slot erase or image upload command Signed-off-by: Jamie McCrae <[email protected]>
1 parent 8d6ab28 commit 514cbbf

File tree

4 files changed

+122
-2
lines changed

4 files changed

+122
-2
lines changed

subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig

+17
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,23 @@ config MCUMGR_GRP_IMG_SLOT_INFO_HOOKS
216216
This will enable the slot info function hooks which can be used to add additional
217217
information to responses.
218218

219+
config MCUMGR_GRP_IMG_IMAGE_SKIP_ERASED_SECTORS
220+
bool "Skip erasing sectors that are already erased"
221+
default y
222+
help
223+
If enabled, will skip erasing already erased sectors in the flash area when an image
224+
upload command or slot erase command is issued.
225+
226+
config MCUMGR_GRP_IMG_IMAGE_SKIP_ERASED_SECTORS_BUFFER_SIZE
227+
int "Skip erasing sectors buffer size"
228+
depends on MCUMGR_GRP_IMG_IMAGE_SKIP_ERASED_SECTORS
229+
range 8 32768
230+
default 64
231+
help
232+
The size of the on-stack buffer which is used for checking if data in flash is erased.
233+
This much data will be read from the flash at a time, a higher value will increase
234+
performance at cost of higher stack usage. This value must be a multiple of 4.
235+
219236
module = MCUMGR_GRP_IMG
220237
module-str = mcumgr_grp_img
221238
source "subsys/logging/Kconfig.template.log_config"

subsys/mgmt/mcumgr/grp/img_mgmt/include/mgmt/mcumgr/grp/img_mgmt/img_mgmt_priv.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* Copyright (c) 2018-2021 mcumgr authors
3-
* Copyright (c) 2022-2023 Nordic Semiconductor ASA
3+
* Copyright (c) 2022-2025 Nordic Semiconductor ASA
44
*
55
* SPDX-License-Identifier: Apache-2.0
66
*/
@@ -201,6 +201,13 @@ void img_mgmt_take_lock(void);
201201
*/
202202
void img_mgmt_release_lock(void);
203203

204+
/**
205+
* @brief Performs an erase of the pending upload slot but skips erasing sectors that are
206+
* already erased. Requires @CONFIG_MCUMGR_GRP_IMG_IMAGE_SKIP_ERASED_SECTORS be
207+
* enabled.
208+
*/
209+
int img_mgmt_erase_pending_upload_slot(void);
210+
204211
#define ERASED_VAL_32(x) (((x) << 24) | ((x) << 16) | ((x) << 8) | (x))
205212
int img_mgmt_erased_val(int slot, uint8_t *erased_val);
206213

subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -892,9 +892,13 @@ defined(CONFIG_MCUMGR_SMP_COMMAND_STATUS_HOOKS)
892892
#endif
893893

894894
#ifndef CONFIG_IMG_ERASE_PROGRESSIVELY
895-
/* erase the entire req.size all at once */
895+
/* Erase the entire req.size or flash slot all at once */
896896
if (action.erase) {
897+
#if defined(CONFIG_MCUMGR_GRP_IMG_IMAGE_SKIP_ERASED_SECTORS)
898+
rc = img_mgmt_erase_pending_upload_slot();
899+
#else
897900
rc = img_mgmt_erase_image_data(0, req.size);
901+
#endif
898902
if (rc != 0) {
899903
IMG_MGMT_UPLOAD_ACTION_SET_RC_RSN(&action,
900904
img_mgmt_err_str_flash_erase_failed);

subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c

+92
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ BUILD_ASSERT(FIXED_PARTITION_EXISTS(SLOT4_PARTITION) &&
5151
"Missing partitions?");
5252
#endif
5353

54+
#if defined(CONFIG_MCUMGR_GRP_IMG_IMAGE_SKIP_ERASED_SECTORS)
55+
BUILD_ASSERT(CONFIG_MCUMGR_GRP_IMG_IMAGE_SKIP_ERASED_SECTORS_BUFFER_SIZE % 4 == 0,
56+
"CONFIG_MCUMGR_GRP_IMG_IMAGE_SKIP_ERASED_SECTORS_BUFFER_SIZE must be multiple of 4");
57+
#endif
58+
5459
/**
5560
* Determines if the specified area of flash is completely unwritten.
5661
*
@@ -274,6 +279,89 @@ int img_mgmt_vercmp(const struct image_version *a, const struct image_version *b
274279
return 0;
275280
}
276281

282+
#if defined(CONFIG_MCUMGR_GRP_IMG_IMAGE_SKIP_ERASED_SECTORS)
283+
static int img_mgmt_erase_unerased_slot_data(const struct flash_area *fa)
284+
{
285+
struct flash_pages_info fpi;
286+
int rc;
287+
off_t off = 0;
288+
uint8_t erased_val;
289+
uint32_t erased_val_32;
290+
291+
assert(fa->fa_size % 4 == 0);
292+
erased_val = flash_area_erased_val(fa);
293+
erased_val_32 = ERASED_VAL_32(erased_val);
294+
295+
while (off < fa->fa_size) {
296+
uint32_t data[CONFIG_MCUMGR_GRP_IMG_IMAGE_SKIP_ERASED_SECTORS_BUFFER_SIZE];
297+
off_t addr;
298+
int bytes_to_read;
299+
int i;
300+
bool needs_erase = false;
301+
302+
rc = flash_get_page_info_by_offs(fa->fa_dev, (fa->fa_off + off), &fpi);
303+
304+
if (rc) {
305+
return rc;
306+
}
307+
308+
for (addr = 0; addr < fpi.size; addr += sizeof(data)) {
309+
if ((fpi.size - addr) < sizeof(data)) {
310+
bytes_to_read = (fpi.size - addr);
311+
} else {
312+
bytes_to_read = sizeof(data);
313+
}
314+
315+
rc = flash_area_read(fa, (addr + off), data, bytes_to_read);
316+
317+
if (rc < 0) {
318+
LOG_ERR("Failed to read data from flash area: %d", rc);
319+
return rc;
320+
}
321+
322+
for (i = 0; i < bytes_to_read / sizeof(erased_val_32); i++) {
323+
if (data[i] != erased_val_32) {
324+
needs_erase = true;
325+
goto perform_erase;
326+
}
327+
}
328+
}
329+
330+
perform_erase:
331+
if (needs_erase) {
332+
rc = flash_area_flatten(fa, off, fpi.size);
333+
334+
if (rc != 0) {
335+
LOG_ERR("Failed to erase flash area: %d", rc);
336+
return rc;
337+
}
338+
}
339+
340+
off += fpi.size;
341+
}
342+
343+
return 0;
344+
}
345+
346+
int img_mgmt_erase_pending_upload_slot(void)
347+
{
348+
const struct flash_area *fa;
349+
int rc;
350+
351+
rc = flash_area_open(g_img_mgmt_state.area_id, &fa);
352+
353+
if (rc) {
354+
goto done;
355+
}
356+
357+
rc = img_mgmt_erase_unerased_slot_data(fa);
358+
flash_area_close(fa);
359+
360+
done:
361+
return rc;
362+
}
363+
#endif
364+
277365
int img_mgmt_erase_slot(int slot)
278366
{
279367
const struct flash_area *fa;
@@ -291,6 +379,9 @@ int img_mgmt_erase_slot(int slot)
291379
return IMG_MGMT_ERR_FLASH_OPEN_FAILED;
292380
}
293381

382+
#if defined(CONFIG_MCUMGR_GRP_IMG_IMAGE_SKIP_ERASED_SECTORS)
383+
rc = img_mgmt_erase_unerased_slot_data(fa);
384+
#else
294385
rc = img_mgmt_flash_check_empty_inner(fa);
295386

296387
if (rc == 0) {
@@ -306,6 +397,7 @@ int img_mgmt_erase_slot(int slot)
306397
*/
307398
rc = 0;
308399
}
400+
#endif
309401

310402
flash_area_close(fa);
311403

0 commit comments

Comments
 (0)