storage/flash_map: Add flash_area_flatten
Add equivalent of flash_erase, from Flash API, to Flash Map API; idea is the same: function tries to erase area if driver provides erase function, otherwise writes erase_value across the defined area. Signed-off-by: Dominik Ermel <dominik.ermel@nordicsemi.no>
This commit is contained in:
parent
b8d073c572
commit
a5f7ceff81
3 changed files with 93 additions and 0 deletions
|
@ -187,6 +187,29 @@ int flash_area_write(const struct flash_area *fa, off_t off, const void *src,
|
||||||
*/
|
*/
|
||||||
int flash_area_erase(const struct flash_area *fa, off_t off, size_t len);
|
int flash_area_erase(const struct flash_area *fa, off_t off, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Erase flash area or fill with erase-value
|
||||||
|
*
|
||||||
|
* On program-erase devices this function behaves exactly like flash_area_erase.
|
||||||
|
* On RAM non-volatile device it will call erase, if driver provides such
|
||||||
|
* callback, or will fill given range with erase-value defined by driver.
|
||||||
|
* This function should be only used by code that has not been written
|
||||||
|
* to directly support devices that do not require erase and rely on
|
||||||
|
* device being erased prior to some operations.
|
||||||
|
* Note that emulated erase, on devices that do not require, is done
|
||||||
|
* via write, which affects endurance of device.
|
||||||
|
*
|
||||||
|
* @see flash_area_erase()
|
||||||
|
* @see flash_flatten()
|
||||||
|
*
|
||||||
|
* @param[in] fa Flash area
|
||||||
|
* @param[in] off Offset relative from beginning of flash area.
|
||||||
|
* @param[in] len Number of bytes to be erase
|
||||||
|
*
|
||||||
|
* @return 0 on success, negative errno code on fail.
|
||||||
|
*/
|
||||||
|
int flash_area_flatten(const struct flash_area *fa, off_t off, size_t len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get write block size of the flash area
|
* @brief Get write block size of the flash area
|
||||||
*
|
*
|
||||||
|
|
|
@ -82,6 +82,15 @@ int flash_area_erase(const struct flash_area *fa, off_t off, size_t len)
|
||||||
return flash_erase(fa->fa_dev, fa->fa_off + off, len);
|
return flash_erase(fa->fa_dev, fa->fa_off + off, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int flash_area_flatten(const struct flash_area *fa, off_t off, size_t len)
|
||||||
|
{
|
||||||
|
if (!is_in_flash_area_bounds(fa, off, len)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return flash_flatten(fa->fa_dev, fa->fa_off + off, len);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t flash_area_align(const struct flash_area *fa)
|
uint32_t flash_area_align(const struct flash_area *fa)
|
||||||
{
|
{
|
||||||
return flash_get_write_block_size(fa->fa_dev);
|
return flash_get_write_block_size(fa->fa_dev);
|
||||||
|
|
|
@ -202,4 +202,65 @@ ZTEST(flash_map, test_fixed_partition_node_macros)
|
||||||
DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(SLOT1_PARTITION_NODE)));
|
DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(SLOT1_PARTITION_NODE)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZTEST(flash_map, test_flash_area_erase_and_flatten)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
bool erased = true;
|
||||||
|
int rc;
|
||||||
|
const struct flash_area *fa;
|
||||||
|
const struct device *flash_dev;
|
||||||
|
|
||||||
|
rc = flash_area_open(SLOT1_PARTITION_ID, &fa);
|
||||||
|
zassert_true(rc == 0, "flash_area_open() fail");
|
||||||
|
|
||||||
|
/* First erase the area so it's ready for use. */
|
||||||
|
flash_dev = flash_area_get_device(fa);
|
||||||
|
|
||||||
|
rc = flash_erase(flash_dev, fa->fa_off, fa->fa_size);
|
||||||
|
zassert_true(rc == 0, "flash area erase fail");
|
||||||
|
|
||||||
|
rc = flash_fill(flash_dev, 0xaa, fa->fa_off, fa->fa_size);
|
||||||
|
zassert_true(rc == 0, "flash device fill fail");
|
||||||
|
|
||||||
|
rc = flash_area_erase(fa, 0, fa->fa_size);
|
||||||
|
zassert_true(rc == 0, "flash area erase fail");
|
||||||
|
|
||||||
|
/* we work under assumption that flash_fill is working and tested */
|
||||||
|
for (i = 0; erased && i < fa->fa_size; ++i) {
|
||||||
|
uint8_t buf[32];
|
||||||
|
int chunk = MIN(sizeof(buf), fa->fa_size - i);
|
||||||
|
|
||||||
|
rc = flash_read(flash_dev, i, buf, chunk);
|
||||||
|
zassert_equal(rc, 0, "Unexpected read fail");
|
||||||
|
for (int ii = 0; ii < chunk; ++ii, ++i) {
|
||||||
|
if (buf[ii] != flash_area_erased_val(fa)) {
|
||||||
|
erased = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zassert_true(erased, "Erase failed at index %d", i);
|
||||||
|
|
||||||
|
rc = flash_fill(flash_dev, 0xaa, fa->fa_off, fa->fa_size);
|
||||||
|
zassert_true(rc == 0, "flash device fill fail");
|
||||||
|
|
||||||
|
rc = flash_area_flatten(fa, 0, fa->fa_size);
|
||||||
|
|
||||||
|
erased = true;
|
||||||
|
for (i = 0; erased && i < fa->fa_size; ++i) {
|
||||||
|
uint8_t buf[32];
|
||||||
|
int chunk = MIN(sizeof(buf), fa->fa_size - i);
|
||||||
|
|
||||||
|
rc = flash_read(flash_dev, i, buf, chunk);
|
||||||
|
zassert_equal(rc, 0, "Unexpected read fail");
|
||||||
|
for (int ii = 0; ii < chunk; ++ii, ++i) {
|
||||||
|
if (buf[ii] != flash_area_erased_val(fa)) {
|
||||||
|
erased = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zassert_true(erased, "Flatten/Erase failed at index %d", i);
|
||||||
|
}
|
||||||
|
|
||||||
ZTEST_SUITE(flash_map, NULL, NULL, NULL, NULL, NULL);
|
ZTEST_SUITE(flash_map, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue