Skip to content

Commit 11e7772

Browse files
committed
drivers/flash/flash_simulator: Add write and erase callbacks
Add the functionality that allows to register write and erase callbacks. The callbacks can modify the behaviour of this operations. It are meant to be used during testing of the situation when the memory starts to generate errors or the data cannot be trusted anymore. It expands the testing possibility, for a situation when the module is tested that checks the data integrity and and we cannot just jump in between its internal write and read operations to inject an error. Signed-off-by: Radosław Koppel <[email protected]>
1 parent 64a1477 commit 11e7772

File tree

2 files changed

+167
-9
lines changed

2 files changed

+167
-9
lines changed

drivers/flash/flash_simulator.c

Lines changed: 70 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include <zephyr/stats/stats.h>
1818
#include <string.h>
1919

20+
#include <zephyr/drivers/flash/flash_simulator.h>
21+
2022
#ifdef CONFIG_ARCH_POSIX
2123

2224
#include "flash_simulator_native.h"
@@ -170,6 +172,20 @@ static const struct flash_parameters flash_sim_parameters = {
170172
},
171173
};
172174

175+
static uint8_t *const mock_flash_pointer = mock_flash;
176+
static const struct flash_simulator_params flash_sim_params = {
177+
.memory = &mock_flash_pointer,
178+
.memory_size = FLASH_SIMULATOR_FLASH_SIZE,
179+
.base_offset = FLASH_SIMULATOR_BASE_OFFSET,
180+
.erase_unit = FLASH_SIMULATOR_ERASE_UNIT,
181+
.prog_unit = FLASH_SIMULATOR_PROG_UNIT,
182+
.explicit_erase = IS_ENABLED(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE),
183+
.erase_value = FLASH_SIMULATOR_ERASE_VALUE,
184+
};
185+
186+
static const struct flash_simulator_cb *flash_simulator_cbs;
187+
188+
173189
static int flash_range_is_valid(const struct device *dev, off_t offset,
174190
size_t len)
175191
{
@@ -264,6 +280,13 @@ static int flash_sim_write(const struct device *dev, const off_t offset,
264280
}
265281
#endif
266282

283+
flash_simulator_write_byte_cb_t write_cb = NULL;
284+
const struct flash_simulator_cb *cb = flash_simulator_cbs;
285+
286+
if (cb != NULL) {
287+
write_cb = cb->write_byte;
288+
}
289+
267290
for (uint32_t i = 0; i < len; i++) {
268291
#ifdef CONFIG_FLASH_SIMULATOR_STATS
269292
if (data_part_ignored) {
@@ -273,16 +296,26 @@ static int flash_sim_write(const struct device *dev, const off_t offset,
273296
}
274297
#endif /* CONFIG_FLASH_SIMULATOR_STATS */
275298

276-
/* only pull bits to zero */
299+
uint8_t data_val = *((const uint8_t *)data + i);
300+
277301
#if defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE)
278302
#if FLASH_SIMULATOR_ERASE_VALUE == 0xFF
279-
*(MOCK_FLASH(offset + i)) &= *((uint8_t *)data + i);
303+
/* only pull bits to zero */
304+
data_val &= *(MOCK_FLASH(offset + i));
280305
#else
281-
*(MOCK_FLASH(offset + i)) |= *((uint8_t *)data + i);
306+
/* only pull bits to one */
307+
data_val |= *(MOCK_FLASH(offset + i));
282308
#endif
283-
#else
284-
*(MOCK_FLASH(offset + i)) = *((uint8_t *)data + i);
285309
#endif
310+
if (write_cb != NULL) {
311+
int ret = write_cb(dev, &flash_sim_params,
312+
offset + i, data_val);
313+
if (ret < 0) {
314+
return ret;
315+
}
316+
data_val = (uint8_t)ret;
317+
}
318+
*(MOCK_FLASH(offset + i)) = data_val;
286319
}
287320

288321
FLASH_SIM_STATS_INCN(flash_sim_stats, bytes_written, len);
@@ -297,20 +330,28 @@ static int flash_sim_write(const struct device *dev, const off_t offset,
297330
return 0;
298331
}
299332

300-
static void unit_erase(const uint32_t unit)
333+
static int unit_erase(const struct device *dev, const uint32_t unit)
301334
{
302335
const off_t unit_addr = unit * FLASH_SIMULATOR_ERASE_UNIT;
336+
flash_simulator_erase_unit_cb_t erase_cb = NULL;
337+
const struct flash_simulator_cb *cb = flash_simulator_cbs;
338+
339+
if (cb != NULL) {
340+
erase_cb = cb->erase_unit;
341+
}
342+
if (erase_cb != NULL) {
343+
return erase_cb(dev, &flash_sim_params, unit_addr);
344+
}
303345

304346
/* erase the memory unit by setting it to erase value */
305347
memset(MOCK_FLASH(unit_addr), FLASH_SIMULATOR_ERASE_VALUE,
306348
FLASH_SIMULATOR_ERASE_UNIT);
349+
return 0;
307350
}
308351

309352
static int flash_sim_erase(const struct device *dev, const off_t offset,
310353
const size_t len)
311354
{
312-
ARG_UNUSED(dev);
313-
314355
if (!flash_range_is_valid(dev, offset, len)) {
315356
return -EINVAL;
316357
}
@@ -335,8 +376,13 @@ static int flash_sim_erase(const struct device *dev, const off_t offset,
335376

336377
/* erase as many units as necessary and increase their erase counter */
337378
for (uint32_t i = 0; i < len / FLASH_SIMULATOR_ERASE_UNIT; i++) {
379+
int ret;
380+
338381
ERASE_CYCLES_INC(unit_start + i);
339-
unit_erase(unit_start + i);
382+
ret = unit_erase(dev, unit_start + i);
383+
if (ret < 0) {
384+
return ret;
385+
}
340386
}
341387

342388
#ifdef CONFIG_FLASH_SIMULATOR_SIMULATE_TIMING
@@ -498,6 +544,13 @@ void *z_impl_flash_simulator_get_memory(const struct device *dev,
498544
return mock_flash;
499545
}
500546

547+
void z_impl_flash_simulator_set_callbacks(const struct device *dev,
548+
const struct flash_simulator_cb *cb)
549+
{
550+
ARG_UNUSED(dev);
551+
flash_simulator_cbs = cb;
552+
}
553+
501554
#ifdef CONFIG_USERSPACE
502555

503556
#include <zephyr/internal/syscall_handler.h>
@@ -510,6 +563,14 @@ void *z_vrfy_flash_simulator_get_memory(const struct device *dev,
510563
return z_impl_flash_simulator_get_memory(dev, mock_size);
511564
}
512565

566+
void z_vrfy_flash_simulator_set_callbacks(const struct device *dev,
567+
const struct flash_simulator_cb *cb)
568+
{
569+
K_OOPS(K_SYSCALL_SPECIFIC_DRIVER(dev, K_OBJ_DRIVER_FLASH, &flash_sim_api));
570+
571+
z_impl_flash_simulator_set_callbacks(dev, cb);
572+
}
573+
513574
#include <zephyr/syscalls/flash_simulator_get_memory_mrsh.c>
514575

515576
#endif /* CONFIG_USERSPACE */

include/zephyr/drivers/flash/flash_simulator.h

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,110 @@
1010
extern "C" {
1111
#endif
1212

13+
#include <zephyr/device.h>
14+
#include <zephyr/types.h>
15+
#include <sys/types.h>
16+
1317
/**
1418
* @file
1519
* @brief Flash simulator specific API.
1620
*
1721
* Extension for flash simulator.
1822
*/
1923

24+
/**
25+
* @brief Flash simulator parameters structure
26+
*
27+
* Auxiliary structure containing flash simulator parameters to be used by callbacks
28+
* that can modify the behavior of the flash simulator driver.
29+
*/
30+
struct flash_simulator_params {
31+
uint8_t *const *memory; /**< @brief The memory pointer */
32+
size_t memory_size; /**< @brief The total size of the memory */
33+
size_t base_offset; /**< @brief The base offset of the flash simulator */
34+
size_t erase_unit; /**< @brief The erase unit size */
35+
size_t prog_unit; /**< @brief The program unit size */
36+
bool explicit_erase; /**< @brief Whether explicit erase is required */
37+
uint8_t erase_value; /**< @brief The value used to represent erased memory */
38+
};
39+
40+
/**
41+
* @brief Flash simulator write byte callback type
42+
*
43+
* Callback used to overwrite single byte write. The callback gets the requested data
44+
* and offset as the parameter. The offset is the same offset passed to the flash write.
45+
* The callback must return a value to be written at the specified offset or negative value
46+
* in case of error.
47+
*
48+
* @param dev Flash simulator device pointer.
49+
* @param params Flash simulator parameters.
50+
* @param offset Offset within the flash simulator memory.
51+
* @param data Data byte to be written.
52+
* @return Value to be written at the specified offset or negative value in case of error.
53+
*/
54+
typedef int (*flash_simulator_write_byte_cb_t)(const struct device *dev,
55+
const struct flash_simulator_params *params,
56+
off_t offset,
57+
const uint8_t data);
58+
59+
/**
60+
* @brief Flash simulator erase unit callback type
61+
*
62+
* Callback used to overwrite unit erase operation. The callback gets the unit offset
63+
* as the parameter. The offset is the same offset passed to the flash erase. The callback
64+
* must return 0 in case of success or negative value in case of error.
65+
*
66+
* @note If this callback is set, the flash simulator driver will not perform any erase operation
67+
* by itself.
68+
*
69+
* @param dev Flash simulator device pointer.
70+
* @param params Flash simulator parameters.
71+
* @param unit_offset Offset within the flash simulator memory.
72+
* @return 0 in case of success or negative value in case of error.
73+
*/
74+
typedef int (*flash_simulator_erase_unit_cb_t)(const struct device *dev,
75+
const struct flash_simulator_params *params,
76+
off_t unit_offset);
77+
78+
/**
79+
* @brief Flash simulator callbacks structure
80+
*
81+
* Structure containing flash simulator operation callbacks.
82+
*/
83+
struct flash_simulator_cb {
84+
flash_simulator_write_byte_cb_t write_byte; /**< @brief Byte write callback */
85+
flash_simulator_erase_unit_cb_t erase_unit; /**< @brief Unit erase callback */
86+
};
87+
88+
/**
89+
* @brief Get pointer to the flash simulator mock flash memory
90+
*
91+
* This function allows the caller to get the address of the RAM buffer
92+
* in which the flash simulator emulates its flash memory content.
93+
*
94+
* @param[in] params flash simulator parameters.
95+
* @param[in] offset offset within the flash simulator memory.
96+
*
97+
* @retval pointer to the ram buffer at specified offset
98+
*/
99+
static inline uint8_t *flash_simulator_mock_flash(const struct flash_simulator_params *params,
100+
off_t offset)
101+
{
102+
return (*params->memory) + offset;
103+
}
104+
105+
/**
106+
* @brief Set flash simulator callbacks
107+
*
108+
* This function allows the caller to set custom callbacks for byte write and
109+
* unit erase operations performed by the flash simulator.
110+
*
111+
* @param[in] dev flash simulator device pointer.
112+
* @param[in] cb pointer to the structure containing the callbacks.
113+
*/
114+
__syscall void flash_simulator_set_callbacks(const struct device *dev,
115+
const struct flash_simulator_cb *cb);
116+
20117
/**
21118
* @brief Obtain a pointer to the RAM buffer used but by the simulator
22119
*

0 commit comments

Comments
 (0)