dfu: use stream_flash in flash_img
Leverage strem_flash in flash_img.c to reduce code size. Signed-off-by: Håkon Øye Amundsen <haakon.amundsen@nordicsemi.no>
This commit is contained in:
parent
a9676831cb
commit
0aa21a632a
3 changed files with 26 additions and 200 deletions
|
@ -8,7 +8,7 @@
|
|||
#ifndef ZEPHYR_INCLUDE_DFU_FLASH_IMG_H_
|
||||
#define ZEPHYR_INCLUDE_DFU_FLASH_IMG_H_
|
||||
|
||||
#include <storage/flash_map.h>
|
||||
#include <storage/stream_flash.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -17,11 +17,7 @@ extern "C" {
|
|||
struct flash_img_context {
|
||||
u8_t buf[CONFIG_IMG_BLOCK_BUF_SIZE];
|
||||
const struct flash_area *flash_area;
|
||||
size_t bytes_written;
|
||||
u16_t buf_bytes;
|
||||
#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
|
||||
off_t off_last;
|
||||
#endif
|
||||
struct stream_flash_ctx stream;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
menuconfig IMG_MANAGER
|
||||
bool "DFU image manager"
|
||||
select STREAM_FLASH
|
||||
help
|
||||
Enable support for managing DFU image.
|
||||
|
||||
|
@ -48,10 +49,10 @@ 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
|
||||
config IMG_ERASE_PROGRESSIVELY
|
||||
bool "Erase flash progressively when receiving new firmware"
|
||||
depends on MCUBOOT_IMG_MANAGER
|
||||
select FLASH_PAGE_LAYOUT
|
||||
select STREAM_FLASH_ERASE
|
||||
help
|
||||
If enabled, flash is erased as necessary when receiving new firmware,
|
||||
instead of erasing the whole image slot at once. This is necessary
|
||||
|
|
|
@ -1,26 +1,19 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2017, 2020 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2017 Linaro Limited
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define LOG_MODULE_NAME fota_flash_block
|
||||
#define LOG_LEVEL CONFIG_IMG_MANAGER_LOG_LEVEL
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <dfu/flash_img.h>
|
||||
#include <inttypes.h>
|
||||
#include <storage/flash_map.h>
|
||||
#include <storage/stream_flash.h>
|
||||
|
||||
#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
|
||||
#include <dfu/mcuboot.h>
|
||||
#include <drivers/flash.h>
|
||||
#endif
|
||||
|
||||
#include <devicetree.h>
|
||||
|
@ -38,181 +31,19 @@ BUILD_ASSERT((CONFIG_IMG_BLOCK_BUF_SIZE % FLASH_WRITE_BLOCK_SIZE == 0),
|
|||
"CONFIG_IMG_BLOCK_BUF_SIZE is not a multiple of "
|
||||
"FLASH_WRITE_BLOCK_SIZE");
|
||||
|
||||
static bool flash_verify(const struct flash_area *fa, off_t offset,
|
||||
u8_t *data, size_t len)
|
||||
{
|
||||
size_t size;
|
||||
u32_t temp;
|
||||
int rc;
|
||||
|
||||
while (len) {
|
||||
size = (len >= sizeof(temp)) ? sizeof(temp) : len;
|
||||
rc = flash_area_read(fa, offset, &temp, size);
|
||||
if (rc) {
|
||||
LOG_ERR("flash_read error %d offset=0x%08lx",
|
||||
rc, (long)offset);
|
||||
break;
|
||||
}
|
||||
|
||||
if (memcmp(data, &temp, size)) {
|
||||
LOG_ERR("offset=0x%08lx VERIFY FAIL. "
|
||||
"expected: 0x%08x, actual: 0x%08x",
|
||||
(long)offset, temp, UNALIGNED_GET(data));
|
||||
break;
|
||||
}
|
||||
len -= size;
|
||||
offset += size;
|
||||
data += size;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
off += fap->fa_off; /* flash driver uses offset from memory beginning */
|
||||
|
||||
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, §or);
|
||||
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%08lx",
|
||||
(long)sector.fs_off);
|
||||
rc = flash_area_erase(ctx->flash_area,
|
||||
sector.fs_off -
|
||||
ctx->flash_area->fa_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;
|
||||
|
||||
if (ctx->buf_bytes < CONFIG_IMG_BLOCK_BUF_SIZE) {
|
||||
(void)memset(ctx->buf + ctx->buf_bytes, 0xFF,
|
||||
CONFIG_IMG_BLOCK_BUF_SIZE - ctx->buf_bytes);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
|
||||
rc = flash_progressive_erase(ctx, ctx->bytes_written +
|
||||
CONFIG_IMG_BLOCK_BUF_SIZE);
|
||||
if (rc) {
|
||||
LOG_ERR("flash_progressive_erase error %d offset=0x%08zx", rc,
|
||||
ctx->bytes_written);
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = flash_area_write(ctx->flash_area, ctx->bytes_written, ctx->buf,
|
||||
CONFIG_IMG_BLOCK_BUF_SIZE);
|
||||
if (rc) {
|
||||
LOG_ERR("flash_write error %d offset=0x%08zx", rc,
|
||||
ctx->bytes_written);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (!flash_verify(ctx->flash_area, ctx->bytes_written, ctx->buf,
|
||||
CONFIG_IMG_BLOCK_BUF_SIZE)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ctx->bytes_written += ctx->buf_bytes;
|
||||
ctx->buf_bytes = 0U;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int flash_img_buffered_write(struct flash_img_context *ctx, u8_t *data,
|
||||
size_t len, bool flush)
|
||||
{
|
||||
int processed = 0;
|
||||
int rc = 0;
|
||||
int buf_empty_bytes;
|
||||
|
||||
while ((len - processed) >=
|
||||
(buf_empty_bytes = CONFIG_IMG_BLOCK_BUF_SIZE - ctx->buf_bytes)) {
|
||||
memcpy(ctx->buf + ctx->buf_bytes, data + processed,
|
||||
buf_empty_bytes);
|
||||
|
||||
ctx->buf_bytes = CONFIG_IMG_BLOCK_BUF_SIZE;
|
||||
rc = flash_sync(ctx);
|
||||
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
processed += buf_empty_bytes;
|
||||
}
|
||||
|
||||
/* place rest of the data into ctx->buf */
|
||||
if (processed < len) {
|
||||
memcpy(ctx->buf + ctx->buf_bytes,
|
||||
data + processed, len - processed);
|
||||
ctx->buf_bytes += len - processed;
|
||||
}
|
||||
int rc;
|
||||
|
||||
rc = stream_flash_buffered_write(&ctx->stream, data, len, flush);
|
||||
if (!flush) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (ctx->buf_bytes > 0) {
|
||||
/* pad the rest of ctx->buf and write it out */
|
||||
rc = flash_sync(ctx);
|
||||
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
|
||||
/* erase the image trailer area if it was not erased */
|
||||
rc = flash_progressive_erase(ctx,
|
||||
rc = stream_flash_erase_page(&ctx->stream,
|
||||
ctx->flash_area->fa_off +
|
||||
BOOT_TRAILER_IMG_STATUS_OFFS(ctx->flash_area));
|
||||
if (rc) {
|
||||
return rc;
|
||||
|
@ -227,30 +58,28 @@ int flash_img_buffered_write(struct flash_img_context *ctx, u8_t *data,
|
|||
|
||||
size_t flash_img_bytes_written(struct flash_img_context *ctx)
|
||||
{
|
||||
return ctx->bytes_written;
|
||||
}
|
||||
|
||||
static void init_ctx(struct flash_img_context *ctx)
|
||||
{
|
||||
ctx->bytes_written = 0;
|
||||
ctx->buf_bytes = 0U;
|
||||
#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
|
||||
ctx->off_last = -1;
|
||||
#endif
|
||||
return stream_flash_bytes_written(&ctx->stream);
|
||||
}
|
||||
|
||||
int flash_img_init_id(struct flash_img_context *ctx, u8_t area_id)
|
||||
{
|
||||
init_ctx(ctx);
|
||||
int rc;
|
||||
struct device *flash_dev;
|
||||
|
||||
return flash_area_open(area_id,
|
||||
rc = flash_area_open(area_id,
|
||||
(const struct flash_area **)&(ctx->flash_area));
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
flash_dev = flash_area_get_device(ctx->flash_area);
|
||||
|
||||
return stream_flash_init(&ctx->stream, flash_dev, ctx->buf,
|
||||
CONFIG_IMG_BLOCK_BUF_SIZE, ctx->flash_area->fa_off,
|
||||
ctx->flash_area->fa_size, NULL);
|
||||
}
|
||||
|
||||
int flash_img_init(struct flash_img_context *ctx)
|
||||
{
|
||||
init_ctx(ctx);
|
||||
|
||||
return flash_area_open(FLASH_AREA_IMAGE_SECONDARY,
|
||||
(const struct flash_area **)&(ctx->flash_area));
|
||||
return flash_img_init_id(ctx, FLASH_AREA_IMAGE_SECONDARY);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue