Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions subsys/bluetooth/mesh/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1053,31 +1053,36 @@ config BT_MESH_BLOB_IO_FLASH
default y
depends on BT_MESH_BLOB_SRV || BT_MESH_BLOB_CLI
depends on FLASH_MAP
depends on FLASH_PAGE_LAYOUT
help
Enable the BLOB flash stream for reading and writing BLOBs directly to
and from flash.

if BT_MESH_BLOB_IO_FLASH

config BT_MESH_BLOB_IO_FLASH_WITHOUT_ERASE
bool "BLOB flash support for devices without erase"
default y if FLASH_HAS_NO_EXPLICIT_ERASE
bool "BLOB flash support for devices without erase [DEPRECATED]"
default n
depends on FLASH_HAS_NO_EXPLICIT_ERASE
select DEPRECATED
help
Enable path supporting devices without erase. This option appears only
if there are devices without explicit erase requirements in the system
and may be disabled to reduce code size in case when no operations
are intended on such type of devices.
This option is deprecated and is no longer used by the BLOB IO Flash module.

config BT_MESH_BLOB_IO_FLASH_WITH_ERASE
bool "BLOB flash support for devices with erase"
default y if FLASH_HAS_EXPLICIT_ERASE
bool "BLOB flash support for devices with erase [DEPRECATED]"
default n
depends on FLASH_HAS_EXPLICIT_ERASE
depends on FLASH_PAGE_LAYOUT
select DEPRECATED
help
Enable path supporting devices with erase. This option appears only
if there are devices requiring erase, before write, in the system
and may be disabled to reduce code size in case when no operations
are intended on such type of devices.
This option is deprecated and is no longer used by the BLOB IO Flash module.

config BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX
int "Maximum supported write block size"
default 4
help
The BLOB IO Flash module will support flash devices with explicit erase
when this value is set to a multiple of the device write block size.

endif # BT_MESH_BLOB_IO_FLASH

Expand Down
122 changes: 75 additions & 47 deletions subsys/bluetooth/mesh/blob_io_flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@
#include "net.h"
#include "transport.h"

#define WRITE_BLOCK_SIZE DT_PROP(DT_INST(0, soc_nv_flash), write_block_size)
#define LOG_LEVEL CONFIG_BT_MESH_MODEL_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(bt_mesh_blob_io_flash);

#define FLASH_IO(_io) CONTAINER_OF(_io, struct bt_mesh_blob_io_flash, io)

static int test_flash_area(uint8_t area_id)
{
const struct flash_parameters *fparam;
const struct flash_area *area;
const struct device *fdev;
uint8_t align;
int err;

Expand All @@ -28,9 +32,19 @@
}

align = flash_area_align(area);
fdev = flash_area_get_device(area);
fparam = flash_get_parameters(fdev);

flash_area_close(area);

if (align > WRITE_BLOCK_SIZE) {
if (!fdev) {
return -ENODEV;
}

if ((flash_params_get_erase_cap(fparam) & FLASH_ERASE_C_EXPLICIT) &&
CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX % align) {
LOG_ERR("CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX must be set to a\n"
"multiple of the write block size for the flash deviced used.");
return -EINVAL;
}

Expand Down Expand Up @@ -58,40 +72,35 @@

static inline int erase_device_block(const struct flash_area *fa, off_t start, size_t size)
{
/* If there are no devices requiring erase, then there is nothing to do */
if (IS_ENABLED(CONFIG_BT_MESH_BLOB_IO_FLASH_WITH_ERASE)) {
const struct device *fdev = flash_area_get_device(fa);

if (!fdev) {
return -ENODEV;
}

/* We have a mix of devices in system */
if (IS_ENABLED(CONFIG_BT_MESH_BLOB_IO_FLASH_WITHOUT_ERASE)) {
const struct flash_parameters *fparam = flash_get_parameters(fdev);

/* If device has no erase requirement then do nothing */
if (!(flash_params_get_erase_cap(fparam) & FLASH_ERASE_C_EXPLICIT)) {
return 0;
}
}

if (IS_ENABLED(CONFIG_FLASH_PAGE_LAYOUT)) {
struct flash_pages_info page;
int err;

err = flash_get_page_info_by_offs(fdev, start, &page);
if (err) {
return err;
}

size = page.size * DIV_ROUND_UP(size, page.size);
start = page.start_offset;
}
return flash_area_erase(fa, start, size);
const struct device *fdev = flash_area_get_device(fa);
struct flash_pages_info page;
int err;

if (!fdev) {
return -ENODEV;
}

return 0;
const struct flash_parameters *fparam = flash_get_parameters(fdev);

/* If device has no erase requirement then do nothing */
if (!(flash_params_get_erase_cap(fparam) & FLASH_ERASE_C_EXPLICIT)) {
return 0;
}

err = flash_get_page_info_by_offs(fdev, start, &page);
if (err) {
return err;
}

if (start != page.start_offset) {
/* Only need to erase when starting the first block on the page. */
return 0;
}

/* Align to page boundary. */
size = page.size * DIV_ROUND_UP(size, page.size);

return flash_area_erase(fa, start, size);
}

static int block_start(const struct bt_mesh_blob_io *io,
Expand Down Expand Up @@ -125,30 +134,49 @@
const struct bt_mesh_blob_chunk *chunk)
{
struct bt_mesh_blob_io_flash *flash = FLASH_IO(io);
const struct device *fdev = flash_area_get_device(flash->area);

if (!fdev) {
return -ENODEV;
}

if (IS_ENABLED(CONFIG_SOC_FLASH_NRF_RRAM)) {
const struct flash_parameters *fparam = flash_get_parameters(fdev);

/*
* If device has no erase requirement then write directly.
* This is required since trick with padding using the erase value will
* not work in this case.
*/
if (!(flash_params_get_erase_cap(fparam) & FLASH_ERASE_C_EXPLICIT)) {
return flash_area_write(flash->area,
flash->offset + block->offset + chunk->offset,
chunk->data, chunk->size);
}

uint8_t buf[ROUND_UP(BLOB_RX_CHUNK_SIZE, WRITE_BLOCK_SIZE)];
/*
* Allocate one additional write block for the case where a chunk will need
* an extra write block on both sides to fit.
*/
uint8_t buf[ROUND_UP(BLOB_RX_CHUNK_SIZE, CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX)
+ CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX];
uint32_t write_block_size = flash_area_align(flash->area);

Check notice on line 162 in subsys/bluetooth/mesh/blob_io_flash.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/bluetooth/mesh/blob_io_flash.c:162 - uint8_t buf[ROUND_UP(BLOB_RX_CHUNK_SIZE, CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX) - + CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX]; + uint8_t buf[ROUND_UP(BLOB_RX_CHUNK_SIZE, + CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX) + + CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX];

Check notice on line 162 in subsys/bluetooth/mesh/blob_io_flash.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/bluetooth/mesh/blob_io_flash.c:162 - uint8_t buf[ROUND_UP(BLOB_RX_CHUNK_SIZE, CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX) - + CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX]; + uint8_t buf[ROUND_UP(BLOB_RX_CHUNK_SIZE, + CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX) + + CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX];
off_t area_offset = flash->offset + block->offset + chunk->offset;
int i = 0;

/* Write block align the chunk data */
memset(&buf[i], 0xff, area_offset % WRITE_BLOCK_SIZE);
i += area_offset % WRITE_BLOCK_SIZE;
int start_pad = area_offset % write_block_size;

memcpy(&buf[i], chunk->data, chunk->size);
i += chunk->size;
/*
* Fill buffer with erase value, to make sure only the part of the
* buffer with chunk data will overwrite flash.
* (Because chunks can arrive in random order, this is required unless
* the entire block is cached in RAM).
*/
memset(buf, fparam->erase_value, sizeof(buf));

memset(&buf[i], 0xff, ROUND_UP(i, WRITE_BLOCK_SIZE) - i);
i = ROUND_UP(i, WRITE_BLOCK_SIZE);
memcpy(&buf[start_pad], chunk->data, chunk->size);

return flash_area_write(flash->area,
ROUND_DOWN(area_offset, WRITE_BLOCK_SIZE),
buf, i);
ROUND_DOWN(area_offset, write_block_size),
buf,
ROUND_UP(start_pad + chunk->size, write_block_size));

Check notice on line 179 in subsys/bluetooth/mesh/blob_io_flash.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/bluetooth/mesh/blob_io_flash.c:179 - return flash_area_write(flash->area, - ROUND_DOWN(area_offset, write_block_size), - buf, + return flash_area_write(flash->area, ROUND_DOWN(area_offset, write_block_size), buf,

Check notice on line 179 in subsys/bluetooth/mesh/blob_io_flash.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/bluetooth/mesh/blob_io_flash.c:179 - return flash_area_write(flash->area, - ROUND_DOWN(area_offset, write_block_size), - buf, + return flash_area_write(flash->area, ROUND_DOWN(area_offset, write_block_size), buf,
}

int bt_mesh_blob_io_flash_init(struct bt_mesh_blob_io_flash *flash,
Expand Down
Loading