Skip to content

Commit db207b0

Browse files
ludvigsjkartben
authored andcommitted
Bluetooth: Mesh: decouple blob_io_flash from internal flash
This fully decouples blob_io_flash from specific flash device details, by not reading the write block size from a hard-coded device tree node, instead pulling this from the actual flash device used. The block write routine has been updated to be more generic and fix a few bugs: * The write buffer is now sized based on a KConfig option instead of basing it off the device tree - this makes the module usable with any flash device, not just the internal memory. The configured value is checked during initialization, to ensure that the configured size will fit the write block size required by the device passed to the init function. * The erase value used to fill the buffer when using a device with explicit erase is now pulled from the flash parameters instead of being hard-coded to `0xff`. * An additional write block sized piece of buffer is allocated - the previous buffer sizing with rounding up only worked if `BLOB_RX_CHUNK_SIZE % WRITE_BLOCK_SIZE` was 0 or 1 (which coincidentally worked in all testing because the chunk size defaults to 161, and for internal flash w/write block size of 4, `161 % 4 == 1`). * The choice of whether to just write the chunk as-is or to write-block align it is now based on the erase cap pulled from the flash parameters, instead of checking the type of memory in the SOC. This means the module dos _not_ currently support the case where memory has to be written write-block aligned, but the memory does _not_ use explicit erase. It uses a trick of filling the write buffer with the erase value to avoid overwriting existing chunks, which will not work in this case. This trick is required to support random ordered chunks while still writing write-block aligned. * The code has been cleaned up a bit in general. Signed-off-by: Ludvig Jordet <[email protected]>
1 parent 99190cb commit db207b0

File tree

2 files changed

+59
-15
lines changed

2 files changed

+59
-15
lines changed

subsys/bluetooth/mesh/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,6 +1065,17 @@ config BT_MESH_BLOB_IO_FLASH_WITH_ERASE
10651065
and may be disabled to reduce code size in case when no operations
10661066
are intended on such type of devices.
10671067

1068+
if BT_MESH_BLOB_IO_FLASH_WITH_ERASE
1069+
1070+
config BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX
1071+
int "Maximum supported write block size"
1072+
default 4
1073+
help
1074+
The BLOB IO Flash module will support flash devices with explicit erase
1075+
using a write block size of at most this value.
1076+
1077+
endif # BT_MESH_BLOB_IO_FLASH_WITH_ERASE
1078+
10681079
endif # BT_MESH_BLOB_IO_FLASH
10691080

10701081
config BT_MESH_DFU_SRV

subsys/bluetooth/mesh/blob_io_flash.c

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,17 @@
1212
#include "net.h"
1313
#include "transport.h"
1414

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

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

1921
static int test_flash_area(uint8_t area_id)
2022
{
23+
const struct flash_parameters *fparam;
2124
const struct flash_area *area;
25+
const struct device *fdev;
2226
uint8_t align;
2327
int err;
2428

@@ -28,9 +32,19 @@ static int test_flash_area(uint8_t area_id)
2832
}
2933

3034
align = flash_area_align(area);
35+
fdev = flash_area_get_device(area);
36+
fparam = flash_get_parameters(fdev);
37+
3138
flash_area_close(area);
3239

33-
if (align > WRITE_BLOCK_SIZE) {
40+
if (!fdev) {
41+
return -ENODEV;
42+
}
43+
44+
if ((flash_params_get_erase_cap(fparam) & FLASH_ERASE_C_EXPLICIT) &&
45+
CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX % align) {
46+
LOG_ERR("CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX must be set to a\n"
47+
"multiple of the write block size for the flash deviced used.");
3448
return -EINVAL;
3549
}
3650

@@ -126,30 +140,49 @@ static int wr_chunk(const struct bt_mesh_blob_io *io,
126140
const struct bt_mesh_blob_chunk *chunk)
127141
{
128142
struct bt_mesh_blob_io_flash *flash = FLASH_IO(io);
143+
const struct device *fdev = flash_area_get_device(flash->area);
129144

130-
if (IS_ENABLED(CONFIG_SOC_FLASH_NRF_RRAM)) {
145+
if (!fdev) {
146+
return -ENODEV;
147+
}
148+
149+
const struct flash_parameters *fparam = flash_get_parameters(fdev);
150+
151+
/*
152+
* If device has no erase requirement then write directly.
153+
* This is required since trick with padding using the erase value will
154+
* not work in this case.
155+
*/
156+
if (!(flash_params_get_erase_cap(fparam) & FLASH_ERASE_C_EXPLICIT)) {
131157
return flash_area_write(flash->area,
132158
flash->offset + block->offset + chunk->offset,
133159
chunk->data, chunk->size);
134160
}
135161

136-
uint8_t buf[ROUND_UP(BLOB_RX_CHUNK_SIZE, WRITE_BLOCK_SIZE)];
162+
/*
163+
* Allocate one additional write block for the case where a chunk will need
164+
* an extra write block on both sides to fit.
165+
*/
166+
uint8_t buf[ROUND_UP(BLOB_RX_CHUNK_SIZE, CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX)
167+
+ CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX];
168+
uint32_t write_block_size = flash_area_align(flash->area);
137169
off_t area_offset = flash->offset + block->offset + chunk->offset;
138-
int i = 0;
139-
140-
/* Write block align the chunk data */
141-
memset(&buf[i], 0xff, area_offset % WRITE_BLOCK_SIZE);
142-
i += area_offset % WRITE_BLOCK_SIZE;
170+
int start_pad = area_offset % write_block_size;
143171

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

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

150182
return flash_area_write(flash->area,
151-
ROUND_DOWN(area_offset, WRITE_BLOCK_SIZE),
152-
buf, i);
183+
ROUND_DOWN(area_offset, write_block_size),
184+
buf,
185+
ROUND_UP(start_pad + chunk->size, write_block_size));
153186
}
154187

155188
int bt_mesh_blob_io_flash_init(struct bt_mesh_blob_io_flash *flash,

0 commit comments

Comments
 (0)