mgmt/mcumgr/lib: Fix parasitic use of heap by image management
The commit fixes issue where image management would switch to using heap, whether developer wanted or not, when CONFIG_HEAP_MEM_POOL gets value greater than zero. Now when heap is enabled the user can select whether image management will keep on using static variable, taking static RAM, or will use heap to allocate the flash image context only when needed. For this purpose CONFIG_IMG_MGMT_USE_HEAP_FOR_FLASH_IMG_CONTEXT has been added, which is available when CONFIG_HEAP_MEM_POOL is enabled. Fixes #44214 Signed-off-by: Dominik Ermel <dominik.ermel@nordicsemi.no>
This commit is contained in:
parent
93e9b5c49d
commit
37dd4fb775
|
@ -12,6 +12,23 @@ menuconfig MCUMGR_CMD_IMG_MGMT
|
|||
Enables mcumgr handlers for image management
|
||||
|
||||
if MCUMGR_CMD_IMG_MGMT
|
||||
|
||||
if HEAP_MEM_POOL_SIZE > 0
|
||||
config IMG_MGMT_USE_HEAP_FOR_FLASH_IMG_CONTEXT
|
||||
bool "Use heap mem pool for flash image DFU context"
|
||||
help
|
||||
Use heap to allocate flash image upload context, otherwise a static variable will
|
||||
be used. The context object is used by IMG_MANAGER to buffer image writes
|
||||
and has significant size, mainly affected by image write buffer of
|
||||
the CONFIG_IMG_BLOCK_BUF_SIZE size and additional fields that hold the state information
|
||||
(struct flash_img_context).
|
||||
When the option is not enabled it increases static RAM use.
|
||||
Make sure with testing, when enabling the option, that the heap has enough size
|
||||
to allocate this context or it will not be possible to perform DFU; it may also not be
|
||||
possible to allocate such context when heap is under pressure, due to application
|
||||
operation, an issue that should also be addressed within application.
|
||||
endif
|
||||
|
||||
config IMG_MGMT_UL_CHUNK_SIZE
|
||||
int "Maximum chunk size for image uploads (DEPRECATED)"
|
||||
default 512
|
||||
|
|
|
@ -334,60 +334,37 @@ img_mgmt_impl_read(int slot, unsigned int offset, void *dst,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The alloc_ctx and free_ctx are specifically provided for
|
||||
* the img_mgmt_impl_write_image_data to allocate/free single flash_img_context
|
||||
* type buffer.
|
||||
* When heap is enabled these functions will operate on heap; when heap is not
|
||||
* allocated the alloc_ctx just returns pointer to static, global life-time
|
||||
* variable, and free_ctx does nothing.
|
||||
* CONFIG_HEAP_MEM_POOL_SIZE is C preprocessor literal.
|
||||
*/
|
||||
static inline struct flash_img_context *alloc_ctx(void)
|
||||
{
|
||||
struct flash_img_context *ctx = NULL;
|
||||
|
||||
if (CONFIG_HEAP_MEM_POOL_SIZE > 0) {
|
||||
ctx = k_malloc(sizeof(*ctx));
|
||||
} else {
|
||||
static struct flash_img_context stcx;
|
||||
|
||||
ctx = &stcx;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static inline void free_ctx(struct flash_img_context *ctx)
|
||||
{
|
||||
if (CONFIG_HEAP_MEM_POOL_SIZE > 0) {
|
||||
k_free(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_IMG_MGMT_USE_HEAP_FOR_FLASH_IMG_CONTEXT)
|
||||
int
|
||||
img_mgmt_impl_write_image_data(unsigned int offset, const void *data, unsigned int num_bytes,
|
||||
bool last)
|
||||
{
|
||||
int rc = 0;
|
||||
/* Even if CONFIG_HEAP_MEM_POOL_SIZE will be able to match size of the structure,
|
||||
* keep in mind that when application will put the heap under pressure, obtaining
|
||||
* of a flash image context may not be possible, so plan bigger heap size or
|
||||
* make sure to limit application pressure on heap when DFU is expected.
|
||||
*/
|
||||
BUILD_ASSERT(CONFIG_HEAP_MEM_POOL_SIZE >= (sizeof(struct flash_img_context)),
|
||||
"Not enough heap mem for flash_img_context.");
|
||||
|
||||
int rc = MGMT_ERR_EOK;
|
||||
static struct flash_img_context *ctx;
|
||||
|
||||
if (CONFIG_HEAP_MEM_POOL_SIZE > 0 && offset != 0 && ctx == NULL) {
|
||||
if (offset != 0 && ctx == NULL) {
|
||||
return MGMT_ERR_EUNKNOWN;
|
||||
}
|
||||
|
||||
if (offset == 0) {
|
||||
if (ctx == NULL) {
|
||||
ctx = alloc_ctx();
|
||||
if (ctx != NULL) {
|
||||
return MGMT_ERR_EUNKNOWN;
|
||||
}
|
||||
ctx = k_malloc(sizeof(struct flash_img_context));
|
||||
|
||||
if (ctx == NULL) {
|
||||
rc = MGMT_ERR_ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (ctx == NULL) {
|
||||
return MGMT_ERR_ENOMEM;
|
||||
}
|
||||
|
||||
rc = flash_img_init_id(ctx, g_img_mgmt_state.area_id);
|
||||
|
||||
if (rc != 0) {
|
||||
if (flash_img_init_id(ctx, g_img_mgmt_state.area_id) != 0) {
|
||||
rc = MGMT_ERR_EUNKNOWN;
|
||||
goto out;
|
||||
}
|
||||
|
@ -398,15 +375,13 @@ img_mgmt_impl_write_image_data(unsigned int offset, const void *data, unsigned i
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* Cast away const. */
|
||||
rc = flash_img_buffered_write(ctx, (void *)data, num_bytes, last);
|
||||
if (rc != 0) {
|
||||
if (flash_img_buffered_write(ctx, data, num_bytes, last) != 0) {
|
||||
rc = MGMT_ERR_EUNKNOWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (CONFIG_HEAP_MEM_POOL_SIZE > 0 && (last || rc != 0)) {
|
||||
if (last || rc != MGMT_ERR_EOK) {
|
||||
k_free(ctx);
|
||||
ctx = NULL;
|
||||
}
|
||||
|
@ -414,6 +389,31 @@ out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
#else
|
||||
int
|
||||
img_mgmt_impl_write_image_data(unsigned int offset, const void *data, unsigned int num_bytes,
|
||||
bool last)
|
||||
{
|
||||
static struct flash_img_context ctx;
|
||||
|
||||
if (offset == 0) {
|
||||
if (flash_img_init_id(&ctx, g_img_mgmt_state.area_id) != 0) {
|
||||
return MGMT_ERR_EUNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
if (offset != ctx.stream.bytes_written + ctx.stream.buf_bytes) {
|
||||
return MGMT_ERR_EUNKNOWN;
|
||||
}
|
||||
|
||||
if (flash_img_buffered_write(&ctx, data, num_bytes, last) != 0) {
|
||||
return MGMT_ERR_EUNKNOWN;
|
||||
}
|
||||
|
||||
return MGMT_ERR_EOK;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
img_mgmt_impl_erase_image_data(unsigned int off, unsigned int num_bytes)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue