dfu/flash_img: use flash_map instead of flash API
Patch introduces flash_map subsystem to operate on flash image instead of direct operation using flash_driver API. Changes allows to support operation on the image in any flash device. flash_map was not available when this subsystem was introduced. Signed-off-by: Findlay Feng <i@fengch.me>
This commit is contained in:
parent
04bf2e1bd1
commit
2d2e1614b5
3 changed files with 73 additions and 62 deletions
|
@ -12,9 +12,11 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <flash_map.h>
|
||||||
|
|
||||||
struct flash_img_context {
|
struct flash_img_context {
|
||||||
u8_t buf[CONFIG_IMG_BLOCK_BUF_SIZE];
|
u8_t buf[CONFIG_IMG_BLOCK_BUF_SIZE];
|
||||||
struct device *dev;
|
const struct flash_area *flash_area;
|
||||||
size_t bytes_written;
|
size_t bytes_written;
|
||||||
u16_t buf_bytes;
|
u16_t buf_bytes;
|
||||||
};
|
};
|
||||||
|
@ -23,9 +25,10 @@ struct flash_img_context {
|
||||||
* @brief Initialize context needed for writing the image to the flash.
|
* @brief Initialize context needed for writing the image to the flash.
|
||||||
*
|
*
|
||||||
* @param ctx context to be initialized
|
* @param ctx context to be initialized
|
||||||
* @param dev flash driver to used while writing the image
|
*
|
||||||
|
* @return 0 on success, negative errno code on fail
|
||||||
*/
|
*/
|
||||||
void flash_img_init(struct flash_img_context *ctx, struct device *dev);
|
int flash_img_init(struct flash_img_context *ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read number of bytes of the image written to the flash.
|
* @brief Read number of bytes of the image written to the flash.
|
||||||
|
|
|
@ -15,7 +15,6 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <flash.h>
|
|
||||||
#include <dfu/flash_img.h>
|
#include <dfu/flash_img.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
@ -23,7 +22,7 @@ BUILD_ASSERT_MSG((CONFIG_IMG_BLOCK_BUF_SIZE % FLASH_WRITE_BLOCK_SIZE == 0),
|
||||||
"CONFIG_IMG_BLOCK_BUF_SIZE is not a multiple of "
|
"CONFIG_IMG_BLOCK_BUF_SIZE is not a multiple of "
|
||||||
"FLASH_WRITE_BLOCK_SIZE");
|
"FLASH_WRITE_BLOCK_SIZE");
|
||||||
|
|
||||||
static bool flash_verify(struct device *dev, off_t offset,
|
static bool flash_verify(const struct flash_area *fa, off_t offset,
|
||||||
u8_t *data, size_t len)
|
u8_t *data, size_t len)
|
||||||
{
|
{
|
||||||
size_t size;
|
size_t size;
|
||||||
|
@ -32,7 +31,7 @@ static bool flash_verify(struct device *dev, off_t offset,
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
size = (len >= sizeof(temp)) ? sizeof(temp) : len;
|
size = (len >= sizeof(temp)) ? sizeof(temp) : len;
|
||||||
rc = flash_read(dev, offset, &temp, size);
|
rc = flash_area_read(fa, offset, &temp, size);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
LOG_ERR("flash_read error %d offset=0x%08"PRIx32,
|
LOG_ERR("flash_read error %d offset=0x%08"PRIx32,
|
||||||
rc, (u32_t)offset);
|
rc, (u32_t)offset);
|
||||||
|
@ -53,36 +52,54 @@ static bool flash_verify(struct device *dev, off_t offset,
|
||||||
return (len == 0) ? true : false;
|
return (len == 0) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* buffer data into block writes */
|
static int flash_sync(struct flash_img_context *ctx)
|
||||||
static int flash_block_write(struct flash_img_context *ctx, off_t offset,
|
{
|
||||||
u8_t *data, size_t len, bool finished)
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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%08" PRIx32, rc,
|
||||||
|
(u32_t)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 = 0;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int flash_img_buffered_write(struct flash_img_context *ctx, u8_t *data,
|
||||||
|
size_t len, bool flush)
|
||||||
{
|
{
|
||||||
int processed = 0;
|
int processed = 0;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
int buf_empty_bytes;
|
||||||
|
|
||||||
while ((len - processed) >
|
while ((len - processed) >
|
||||||
(CONFIG_IMG_BLOCK_BUF_SIZE - ctx->buf_bytes)) {
|
(buf_empty_bytes = CONFIG_IMG_BLOCK_BUF_SIZE - ctx->buf_bytes)) {
|
||||||
memcpy(ctx->buf + ctx->buf_bytes, data + processed,
|
memcpy(ctx->buf + ctx->buf_bytes, data + processed,
|
||||||
(CONFIG_IMG_BLOCK_BUF_SIZE - ctx->buf_bytes));
|
buf_empty_bytes);
|
||||||
|
|
||||||
|
ctx->buf_bytes = CONFIG_IMG_BLOCK_BUF_SIZE;
|
||||||
|
rc = flash_sync(ctx);
|
||||||
|
|
||||||
flash_write_protection_set(ctx->dev, false);
|
|
||||||
rc = flash_write(ctx->dev, offset + ctx->bytes_written,
|
|
||||||
ctx->buf, CONFIG_IMG_BLOCK_BUF_SIZE);
|
|
||||||
flash_write_protection_set(ctx->dev, true);
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
LOG_ERR("flash_write error %d offset=0x%08"PRIx32,
|
|
||||||
rc, (u32_t)(offset + ctx->bytes_written));
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!flash_verify(ctx->dev, offset + ctx->bytes_written,
|
processed += buf_empty_bytes;
|
||||||
ctx->buf, CONFIG_IMG_BLOCK_BUF_SIZE)) {
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->bytes_written += CONFIG_IMG_BLOCK_BUF_SIZE;
|
|
||||||
processed += (CONFIG_IMG_BLOCK_BUF_SIZE - ctx->buf_bytes);
|
|
||||||
ctx->buf_bytes = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* place rest of the data into ctx->buf */
|
/* place rest of the data into ctx->buf */
|
||||||
|
@ -92,30 +109,22 @@ static int flash_block_write(struct flash_img_context *ctx, off_t offset,
|
||||||
ctx->buf_bytes += len - processed;
|
ctx->buf_bytes += len - processed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (finished && ctx->buf_bytes > 0) {
|
if (!flush) {
|
||||||
/* pad the rest of ctx->buf and write it out */
|
return rc;
|
||||||
(void)memset(ctx->buf + ctx->buf_bytes, 0xFF,
|
}
|
||||||
CONFIG_IMG_BLOCK_BUF_SIZE - ctx->buf_bytes);
|
|
||||||
|
if (ctx->buf_bytes > 0) {
|
||||||
|
/* pad the rest of ctx->buf and write it out */
|
||||||
|
rc = flash_sync(ctx);
|
||||||
|
|
||||||
flash_write_protection_set(ctx->dev, false);
|
|
||||||
rc = flash_write(ctx->dev, offset + ctx->bytes_written,
|
|
||||||
ctx->buf, CONFIG_IMG_BLOCK_BUF_SIZE);
|
|
||||||
flash_write_protection_set(ctx->dev, true);
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
LOG_ERR("flash_write error %d offset=0x%08"PRIx32,
|
|
||||||
rc, (u32_t)(offset + ctx->bytes_written));
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!flash_verify(ctx->dev, offset + ctx->bytes_written,
|
|
||||||
ctx->buf, CONFIG_IMG_BLOCK_BUF_SIZE)) {
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->bytes_written = ctx->bytes_written + ctx->buf_bytes;
|
|
||||||
ctx->buf_bytes = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flash_area_close(ctx->flash_area);
|
||||||
|
ctx->flash_area = NULL;
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,16 +133,10 @@ size_t flash_img_bytes_written(struct flash_img_context *ctx)
|
||||||
return ctx->bytes_written;
|
return ctx->bytes_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
void flash_img_init(struct flash_img_context *ctx, struct device *dev)
|
int flash_img_init(struct flash_img_context *ctx)
|
||||||
{
|
{
|
||||||
ctx->dev = dev;
|
|
||||||
ctx->bytes_written = 0;
|
ctx->bytes_written = 0;
|
||||||
ctx->buf_bytes = 0;
|
ctx->buf_bytes = 0;
|
||||||
}
|
return flash_area_open(DT_FLASH_AREA_IMAGE_1_ID,
|
||||||
|
(const struct flash_area **)&(ctx->flash_area));
|
||||||
int flash_img_buffered_write(struct flash_img_context *ctx, u8_t *data,
|
|
||||||
size_t len, bool flush)
|
|
||||||
{
|
|
||||||
return flash_block_write(ctx, FLASH_AREA_IMAGE_1_OFFSET, data, len,
|
|
||||||
flush);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,24 +5,23 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ztest.h>
|
#include <ztest.h>
|
||||||
#include <flash.h>
|
#include <flash_map.h>
|
||||||
#include <dfu/flash_img.h>
|
#include <dfu/flash_img.h>
|
||||||
|
|
||||||
void test_collecting(void)
|
void test_collecting(void)
|
||||||
{
|
{
|
||||||
struct device *flash_dev;
|
const struct flash_area *fa;
|
||||||
struct flash_img_context ctx;
|
struct flash_img_context ctx;
|
||||||
u32_t i, j;
|
u32_t i, j;
|
||||||
u8_t data[5], temp, k;
|
u8_t data[5], temp, k;
|
||||||
|
int ret;
|
||||||
|
|
||||||
flash_dev = device_get_binding(DT_FLASH_DEV_NAME);
|
ret = flash_img_init(&ctx);
|
||||||
|
zassert_true(ret == 0, "Flash img init");
|
||||||
|
|
||||||
flash_write_protection_set(flash_dev, false);
|
ret = flash_area_erase(ctx.flash_area, 0, ctx.flash_area->fa_size);
|
||||||
flash_erase(flash_dev, FLASH_AREA_IMAGE_1_OFFSET,
|
zassert_true(ret == 0, "Flash erase");
|
||||||
FLASH_AREA_IMAGE_1_SIZE);
|
|
||||||
flash_write_protection_set(flash_dev, true);
|
|
||||||
|
|
||||||
flash_img_init(&ctx, flash_dev);
|
|
||||||
zassert(flash_img_bytes_written(&ctx) == 0, "pass", "fail");
|
zassert(flash_img_bytes_written(&ctx) == 0, "pass", "fail");
|
||||||
|
|
||||||
k = 0U;
|
k = 0U;
|
||||||
|
@ -37,10 +36,16 @@ void test_collecting(void)
|
||||||
zassert(flash_img_buffered_write(&ctx, data, 0, true) == 0, "pass",
|
zassert(flash_img_buffered_write(&ctx, data, 0, true) == 0, "pass",
|
||||||
"fail");
|
"fail");
|
||||||
|
|
||||||
|
|
||||||
|
ret = flash_area_open(DT_FLASH_AREA_IMAGE_1_ID, &fa);
|
||||||
|
if (ret) {
|
||||||
|
printf("Flash driver was not found!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
k = 0U;
|
k = 0U;
|
||||||
for (i = 0U; i < 300 * sizeof(data); i++) {
|
for (i = 0U; i < 300 * sizeof(data); i++) {
|
||||||
zassert(flash_read(flash_dev, FLASH_AREA_IMAGE_1_OFFSET + i,
|
zassert(flash_area_read(fa, i, &temp, 1) == 0, "pass", "fail");
|
||||||
&temp, 1) == 0, "pass", "fail");
|
|
||||||
zassert(temp == k, "pass", "fail");
|
zassert(temp == k, "pass", "fail");
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue