1 /*
2 * Copyright (c) 2023-2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT zephyr_sim_flash
8
9 #include <zephyr/device.h>
10 #include <zephyr/devicetree.h>
11 #include <zephyr/linker/devicetree_regions.h>
12 #include <zephyr/drivers/flash.h>
13 #include <zephyr/init.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/sys/util.h>
16 #include <zephyr/random/random.h>
17 #include <zephyr/stats/stats.h>
18 #include <string.h>
19
20 #include <zephyr/drivers/flash/flash_simulator.h>
21
22 #ifdef CONFIG_ARCH_POSIX
23
24 #include "flash_simulator_native.h"
25 #include "cmdline.h"
26 #include "soc.h"
27 #define DEFAULT_FLASH_FILE_PATH "flash.bin"
28
29 #endif /* CONFIG_ARCH_POSIX */
30
31 /* configuration derived from DT */
32 #ifdef CONFIG_ARCH_POSIX
33 #define SOC_NV_FLASH_NODE DT_INST_CHILD(0, flash_0)
34 #else
35 #define SOC_NV_FLASH_NODE DT_INST_CHILD(0, flash_sim_0)
36 #endif /* CONFIG_ARCH_POSIX */
37
38 #define FLASH_SIMULATOR_BASE_OFFSET DT_REG_ADDR(SOC_NV_FLASH_NODE)
39 #define FLASH_SIMULATOR_ERASE_UNIT DT_PROP(SOC_NV_FLASH_NODE, erase_block_size)
40 #define FLASH_SIMULATOR_PROG_UNIT DT_PROP(SOC_NV_FLASH_NODE, write_block_size)
41 #define FLASH_SIMULATOR_FLASH_SIZE DT_REG_SIZE(SOC_NV_FLASH_NODE)
42
43 #define FLASH_SIMULATOR_ERASE_VALUE \
44 DT_PROP(DT_PARENT(SOC_NV_FLASH_NODE), erase_value)
45
46 #define FLASH_SIMULATOR_PAGE_COUNT (FLASH_SIMULATOR_FLASH_SIZE / \
47 FLASH_SIMULATOR_ERASE_UNIT)
48
49 #if (FLASH_SIMULATOR_ERASE_UNIT % FLASH_SIMULATOR_PROG_UNIT)
50 #error "Erase unit must be a multiple of program unit"
51 #endif
52
53 #define MOCK_FLASH(offset) (mock_flash + (offset))
54
55 /* maximum number of pages that can be tracked by the stats module */
56 #define STATS_PAGE_COUNT_THRESHOLD 256
57
58 #define STATS_SECT_EC(N, _) STATS_SECT_ENTRY32(erase_cycles_unit##N)
59 #define STATS_NAME_EC(N, _) STATS_NAME(flash_sim_stats, erase_cycles_unit##N)
60
61 #define STATS_SECT_DIRTYR(N, _) STATS_SECT_ENTRY32(dirty_read_unit##N)
62 #define STATS_NAME_DIRTYR(N, _) STATS_NAME(flash_sim_stats, dirty_read_unit##N)
63
64 #ifdef CONFIG_FLASH_SIMULATOR_STATS
65 /* increment a unit erase cycles counter */
66 #define ERASE_CYCLES_INC(U) \
67 do { \
68 if (U < STATS_PAGE_COUNT_THRESHOLD) { \
69 (*(&flash_sim_stats.erase_cycles_unit0 + (U)) += 1); \
70 } \
71 } while (false)
72
73 #if (CONFIG_FLASH_SIMULATOR_STAT_PAGE_COUNT > STATS_PAGE_COUNT_THRESHOLD)
74 /* Limitation above is caused by used LISTIFY */
75 /* Using FLASH_SIMULATOR_FLASH_PAGE_COUNT allows to avoid terrible */
76 /* error logg at the output and work with the stats module partially */
77 #define FLASH_SIMULATOR_FLASH_PAGE_COUNT STATS_PAGE_COUNT_THRESHOLD
78 #else
79 #define FLASH_SIMULATOR_FLASH_PAGE_COUNT CONFIG_FLASH_SIMULATOR_STAT_PAGE_COUNT
80 #endif
81
82 /* simulator statistics */
83 STATS_SECT_START(flash_sim_stats)
84 STATS_SECT_ENTRY32(bytes_read) /* total bytes read */
85 STATS_SECT_ENTRY32(bytes_written) /* total bytes written */
86 STATS_SECT_ENTRY32(double_writes) /* num. of writes to non-erased units */
87 STATS_SECT_ENTRY32(flash_read_calls) /* calls to flash_read() */
88 STATS_SECT_ENTRY32(flash_read_time_us) /* time spent in flash_read() */
89 STATS_SECT_ENTRY32(flash_write_calls) /* calls to flash_write() */
90 STATS_SECT_ENTRY32(flash_write_time_us) /* time spent in flash_write() */
91 STATS_SECT_ENTRY32(flash_erase_calls) /* calls to flash_erase() */
92 STATS_SECT_ENTRY32(flash_erase_time_us) /* time spent in flash_erase() */
93 /* -- per-unit statistics -- */
94 /* erase cycle count for unit */
95 LISTIFY(FLASH_SIMULATOR_FLASH_PAGE_COUNT, STATS_SECT_EC, ())
96 /* number of read operations on worn out erase units */
97 LISTIFY(FLASH_SIMULATOR_FLASH_PAGE_COUNT, STATS_SECT_DIRTYR, ())
98 STATS_SECT_END;
99
100 STATS_SECT_DECL(flash_sim_stats) flash_sim_stats;
101 STATS_NAME_START(flash_sim_stats)
102 STATS_NAME(flash_sim_stats, bytes_read)
103 STATS_NAME(flash_sim_stats, bytes_written)
104 STATS_NAME(flash_sim_stats, double_writes)
105 STATS_NAME(flash_sim_stats, flash_read_calls)
106 STATS_NAME(flash_sim_stats, flash_read_time_us)
107 STATS_NAME(flash_sim_stats, flash_write_calls)
108 STATS_NAME(flash_sim_stats, flash_write_time_us)
109 STATS_NAME(flash_sim_stats, flash_erase_calls)
110 STATS_NAME(flash_sim_stats, flash_erase_time_us)
111 LISTIFY(FLASH_SIMULATOR_FLASH_PAGE_COUNT, STATS_NAME_EC, ())
112 LISTIFY(FLASH_SIMULATOR_FLASH_PAGE_COUNT, STATS_NAME_DIRTYR, ())
113 STATS_NAME_END(flash_sim_stats);
114
115 /* simulator dynamic thresholds */
116 STATS_SECT_START(flash_sim_thresholds)
117 STATS_SECT_ENTRY32(max_write_calls)
118 STATS_SECT_ENTRY32(max_erase_calls)
119 STATS_SECT_ENTRY32(max_len)
120 STATS_SECT_END;
121
122 STATS_SECT_DECL(flash_sim_thresholds) flash_sim_thresholds;
123 STATS_NAME_START(flash_sim_thresholds)
124 STATS_NAME(flash_sim_thresholds, max_write_calls)
125 STATS_NAME(flash_sim_thresholds, max_erase_calls)
126 STATS_NAME(flash_sim_thresholds, max_len)
127 STATS_NAME_END(flash_sim_thresholds);
128
129 #define FLASH_SIM_STATS_INC(group__, var__) STATS_INC(group__, var__)
130 #define FLASH_SIM_STATS_INCN(group__, var__, n__) STATS_INCN(group__, var__, n__)
131 #define FLASH_SIM_STATS_INIT_AND_REG(group__, size__, name__) \
132 STATS_INIT_AND_REG(group__, size__, name__)
133
134
135 #else
136
137 #define ERASE_CYCLES_INC(U) do {} while (false)
138 #define FLASH_SIM_STATS_INC(group__, var__)
139 #define FLASH_SIM_STATS_INCN(group__, var__, n__)
140 #define FLASH_SIM_STATS_INIT_AND_REG(group__, size__, name__)
141
142 #endif /* CONFIG_FLASH_SIMULATOR_STATS */
143
144
145 #ifdef CONFIG_ARCH_POSIX
146 static uint8_t *mock_flash;
147 static int flash_fd = -1;
148 static const char *flash_file_path;
149 static bool flash_erase_at_start;
150 static bool flash_rm_at_exit;
151 static bool flash_in_ram;
152 #else
153 #if DT_NODE_HAS_PROP(DT_PARENT(SOC_NV_FLASH_NODE), memory_region)
154 #define FLASH_SIMULATOR_MREGION \
155 LINKER_DT_NODE_REGION_NAME( \
156 DT_PHANDLE(DT_PARENT(SOC_NV_FLASH_NODE), memory_region))
157 static uint8_t mock_flash[FLASH_SIMULATOR_FLASH_SIZE] Z_GENERIC_SECTION(FLASH_SIMULATOR_MREGION);
158 #else
159 static uint8_t mock_flash[FLASH_SIMULATOR_FLASH_SIZE];
160 #endif
161 #endif /* CONFIG_ARCH_POSIX */
162
163 uint8_t prog_unit_buf[FLASH_SIMULATOR_PROG_UNIT];
164
165 static DEVICE_API(flash, flash_sim_api);
166
167 static const struct flash_parameters flash_sim_parameters = {
168 .write_block_size = FLASH_SIMULATOR_PROG_UNIT,
169 .erase_value = FLASH_SIMULATOR_ERASE_VALUE,
170 .caps = {
171 #if !defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE)
172 .no_explicit_erase = false,
173 #endif
174 },
175 };
176
177
178 #ifdef CONFIG_FLASH_SIMULATOR_CALLBACKS
179 static const struct flash_simulator_params flash_sim_params = {
180 .memory_size = FLASH_SIMULATOR_FLASH_SIZE,
181 .base_offset = FLASH_SIMULATOR_BASE_OFFSET,
182 .erase_unit = FLASH_SIMULATOR_ERASE_UNIT,
183 .prog_unit = FLASH_SIMULATOR_PROG_UNIT,
184 .explicit_erase = IS_ENABLED(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE),
185 .erase_value = FLASH_SIMULATOR_ERASE_VALUE,
186 };
187 static const struct flash_simulator_cb *flash_simulator_cbs;
188 #endif /* CONFIG_FLASH_SIMULATOR_CALLBACKS */
189
190
flash_range_is_valid(const struct device * dev,off_t offset,size_t len)191 static int flash_range_is_valid(const struct device *dev, off_t offset,
192 size_t len)
193 {
194 ARG_UNUSED(dev);
195
196 if ((offset < 0 || offset >= FLASH_SIMULATOR_FLASH_SIZE ||
197 (FLASH_SIMULATOR_FLASH_SIZE - offset) < len)) {
198 return 0;
199 }
200
201 return 1;
202 }
203
flash_sim_read(const struct device * dev,const off_t offset,void * data,const size_t len)204 static int flash_sim_read(const struct device *dev, const off_t offset,
205 void *data,
206 const size_t len)
207 {
208 ARG_UNUSED(dev);
209
210 if (!flash_range_is_valid(dev, offset, len)) {
211 return -EINVAL;
212 }
213
214 if (!IS_ENABLED(CONFIG_FLASH_SIMULATOR_UNALIGNED_READ)) {
215 if ((offset % FLASH_SIMULATOR_PROG_UNIT) ||
216 (len % FLASH_SIMULATOR_PROG_UNIT)) {
217 return -EINVAL;
218 }
219 }
220
221 FLASH_SIM_STATS_INC(flash_sim_stats, flash_read_calls);
222
223 memcpy(data, MOCK_FLASH(offset), len);
224 FLASH_SIM_STATS_INCN(flash_sim_stats, bytes_read, len);
225
226 #ifdef CONFIG_FLASH_SIMULATOR_SIMULATE_TIMING
227 k_busy_wait(CONFIG_FLASH_SIMULATOR_MIN_READ_TIME_US);
228 FLASH_SIM_STATS_INCN(flash_sim_stats, flash_read_time_us,
229 CONFIG_FLASH_SIMULATOR_MIN_READ_TIME_US);
230 #endif
231
232 return 0;
233 }
234
flash_sim_write(const struct device * dev,const off_t offset,const void * data,const size_t len)235 static int flash_sim_write(const struct device *dev, const off_t offset,
236 const void *data, const size_t len)
237 {
238 ARG_UNUSED(dev);
239
240 if (!flash_range_is_valid(dev, offset, len)) {
241 return -EINVAL;
242 }
243
244 if ((offset % FLASH_SIMULATOR_PROG_UNIT) ||
245 (len % FLASH_SIMULATOR_PROG_UNIT)) {
246 return -EINVAL;
247 }
248
249 FLASH_SIM_STATS_INC(flash_sim_stats, flash_write_calls);
250
251 #ifdef CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE
252 /* check if any unit has been already programmed */
253 memset(prog_unit_buf, FLASH_SIMULATOR_ERASE_VALUE, sizeof(prog_unit_buf));
254 #else
255 memcpy(prog_unit_buf, MOCK_FLASH(offset), sizeof(prog_unit_buf));
256 #endif
257 for (uint32_t i = 0; i < len; i += FLASH_SIMULATOR_PROG_UNIT) {
258 if (memcmp(prog_unit_buf, MOCK_FLASH(offset + i), sizeof(prog_unit_buf))) {
259 FLASH_SIM_STATS_INC(flash_sim_stats, double_writes);
260 #if !CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES
261 return -EIO;
262 #endif
263 }
264 }
265
266 #ifdef CONFIG_FLASH_SIMULATOR_STATS
267 bool data_part_ignored = false;
268
269 if (flash_sim_thresholds.max_write_calls != 0) {
270 if (flash_sim_stats.flash_write_calls >
271 flash_sim_thresholds.max_write_calls) {
272 return 0;
273 } else if (flash_sim_stats.flash_write_calls ==
274 flash_sim_thresholds.max_write_calls) {
275 if (flash_sim_thresholds.max_len == 0) {
276 return 0;
277 }
278
279 data_part_ignored = true;
280 }
281 }
282 #endif
283
284 #ifdef CONFIG_FLASH_SIMULATOR_CALLBACKS
285 flash_simulator_write_byte_cb_t write_cb = NULL;
286 const struct flash_simulator_cb *cb = flash_simulator_cbs;
287
288 if (cb != NULL) {
289 write_cb = cb->write_byte;
290 }
291 #endif /* CONFIG_FLASH_SIMULATOR_CALLBACKS */
292
293 for (uint32_t i = 0; i < len; i++) {
294 #ifdef CONFIG_FLASH_SIMULATOR_STATS
295 if (data_part_ignored) {
296 if (i >= flash_sim_thresholds.max_len) {
297 return 0;
298 }
299 }
300 #endif /* CONFIG_FLASH_SIMULATOR_STATS */
301
302 uint8_t data_val = *((const uint8_t *)data + i);
303
304 #ifdef CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE
305 #if FLASH_SIMULATOR_ERASE_VALUE == 0xFF
306 /* only pull bits to zero */
307 data_val &= *(MOCK_FLASH(offset + i));
308 #else
309 /* only pull bits to one */
310 data_val |= *(MOCK_FLASH(offset + i));
311 #endif
312 #endif
313 #ifdef CONFIG_FLASH_SIMULATOR_CALLBACKS
314 if (write_cb != NULL) {
315 int ret = write_cb(dev, offset + i, data_val);
316
317 if (ret < 0) {
318 return ret;
319 }
320 data_val = (uint8_t)ret;
321 }
322 #endif /* CONFIG_FLASH_SIMULATOR_CALLBACKS */
323 *(MOCK_FLASH(offset + i)) = data_val;
324 }
325
326 FLASH_SIM_STATS_INCN(flash_sim_stats, bytes_written, len);
327
328 #ifdef CONFIG_FLASH_SIMULATOR_SIMULATE_TIMING
329 /* wait before returning */
330 k_busy_wait(CONFIG_FLASH_SIMULATOR_MIN_WRITE_TIME_US);
331 FLASH_SIM_STATS_INCN(flash_sim_stats, flash_write_time_us,
332 CONFIG_FLASH_SIMULATOR_MIN_WRITE_TIME_US);
333 #endif
334
335 return 0;
336 }
337
unit_erase(const struct device * dev,const uint32_t unit)338 static int unit_erase(const struct device *dev, const uint32_t unit)
339 {
340 const off_t unit_addr = unit * FLASH_SIMULATOR_ERASE_UNIT;
341
342 #ifdef CONFIG_FLASH_SIMULATOR_CALLBACKS
343 flash_simulator_erase_unit_cb_t erase_cb = NULL;
344 const struct flash_simulator_cb *cb = flash_simulator_cbs;
345
346 if (cb != NULL) {
347 erase_cb = cb->erase_unit;
348 }
349 if (erase_cb != NULL) {
350 return erase_cb(dev, unit_addr);
351 }
352 #endif /* CONFIG_FLASH_SIMULATOR_CALLBACKS */
353
354 /* erase the memory unit by setting it to erase value */
355 memset(MOCK_FLASH(unit_addr), FLASH_SIMULATOR_ERASE_VALUE,
356 FLASH_SIMULATOR_ERASE_UNIT);
357 return 0;
358 }
359
flash_sim_erase(const struct device * dev,const off_t offset,const size_t len)360 static int flash_sim_erase(const struct device *dev, const off_t offset,
361 const size_t len)
362 {
363 if (!flash_range_is_valid(dev, offset, len)) {
364 return -EINVAL;
365 }
366
367 /* erase operation must be aligned to the erase unit boundary */
368 if ((offset % FLASH_SIMULATOR_ERASE_UNIT) ||
369 (len % FLASH_SIMULATOR_ERASE_UNIT)) {
370 return -EINVAL;
371 }
372
373 FLASH_SIM_STATS_INC(flash_sim_stats, flash_erase_calls);
374
375 #ifdef CONFIG_FLASH_SIMULATOR_STATS
376 if ((flash_sim_thresholds.max_erase_calls != 0) &&
377 (flash_sim_stats.flash_erase_calls >=
378 flash_sim_thresholds.max_erase_calls)){
379 return 0;
380 }
381 #endif
382 /* the first unit to be erased */
383 uint32_t unit_start = offset / FLASH_SIMULATOR_ERASE_UNIT;
384
385 /* erase as many units as necessary and increase their erase counter */
386 for (uint32_t i = 0; i < len / FLASH_SIMULATOR_ERASE_UNIT; i++) {
387 int ret;
388
389 ERASE_CYCLES_INC(unit_start + i);
390 ret = unit_erase(dev, unit_start + i);
391 if (ret < 0) {
392 return ret;
393 }
394 }
395
396 #ifdef CONFIG_FLASH_SIMULATOR_SIMULATE_TIMING
397 /* wait before returning */
398 k_busy_wait(CONFIG_FLASH_SIMULATOR_MIN_ERASE_TIME_US);
399 FLASH_SIM_STATS_INCN(flash_sim_stats, flash_erase_time_us,
400 CONFIG_FLASH_SIMULATOR_MIN_ERASE_TIME_US);
401 #endif
402
403 return 0;
404 }
405
406 #ifdef CONFIG_FLASH_PAGE_LAYOUT
407 static const struct flash_pages_layout flash_sim_pages_layout = {
408 .pages_count = FLASH_SIMULATOR_PAGE_COUNT,
409 .pages_size = FLASH_SIMULATOR_ERASE_UNIT,
410 };
411
flash_sim_page_layout(const struct device * dev,const struct flash_pages_layout ** layout,size_t * layout_size)412 static void flash_sim_page_layout(const struct device *dev,
413 const struct flash_pages_layout **layout,
414 size_t *layout_size)
415 {
416 *layout = &flash_sim_pages_layout;
417 *layout_size = 1;
418 }
419 #endif
420
flash_sim_get_size(const struct device * dev,uint64_t * size)421 static int flash_sim_get_size(const struct device *dev, uint64_t *size)
422 {
423 ARG_UNUSED(dev);
424
425 *size = FLASH_SIMULATOR_FLASH_SIZE;
426
427 return 0;
428 }
429 static const struct flash_parameters *
flash_sim_get_parameters(const struct device * dev)430 flash_sim_get_parameters(const struct device *dev)
431 {
432 ARG_UNUSED(dev);
433
434 return &flash_sim_parameters;
435 }
436
437 static DEVICE_API(flash, flash_sim_api) = {
438 .read = flash_sim_read,
439 .write = flash_sim_write,
440 .erase = flash_sim_erase,
441 .get_parameters = flash_sim_get_parameters,
442 .get_size = flash_sim_get_size,
443 #ifdef CONFIG_FLASH_PAGE_LAYOUT
444 .page_layout = flash_sim_page_layout,
445 #endif
446 };
447
448 #ifdef CONFIG_ARCH_POSIX
449
flash_mock_init(const struct device * dev)450 static int flash_mock_init(const struct device *dev)
451 {
452 int rc;
453 ARG_UNUSED(dev);
454
455 if (flash_in_ram == false && flash_file_path == NULL) {
456 flash_file_path = DEFAULT_FLASH_FILE_PATH;
457 }
458
459 rc = flash_mock_init_native(flash_in_ram, &mock_flash, FLASH_SIMULATOR_FLASH_SIZE,
460 &flash_fd, flash_file_path, FLASH_SIMULATOR_ERASE_VALUE,
461 flash_erase_at_start);
462
463 if (rc < 0) {
464 return -EIO;
465 } else {
466 return 0;
467 }
468 }
469
470 #else
471 #if DT_NODE_HAS_PROP(DT_PARENT(SOC_NV_FLASH_NODE), memory_region)
flash_mock_init(const struct device * dev)472 static int flash_mock_init(const struct device *dev)
473 {
474 ARG_UNUSED(dev);
475 return 0;
476 }
477 #else
flash_mock_init(const struct device * dev)478 static int flash_mock_init(const struct device *dev)
479 {
480 ARG_UNUSED(dev);
481 memset(mock_flash, FLASH_SIMULATOR_ERASE_VALUE, ARRAY_SIZE(mock_flash));
482 return 0;
483 }
484 #endif /* DT_NODE_HAS_PROP(DT_PARENT(SOC_NV_FLASH_NODE), memory_region) */
485 #endif /* CONFIG_ARCH_POSIX */
486
flash_init(const struct device * dev)487 static int flash_init(const struct device *dev)
488 {
489 FLASH_SIM_STATS_INIT_AND_REG(flash_sim_stats, STATS_SIZE_32, "flash_sim_stats");
490 FLASH_SIM_STATS_INIT_AND_REG(flash_sim_thresholds, STATS_SIZE_32,
491 "flash_sim_thresholds");
492 return flash_mock_init(dev);
493 }
494
495 DEVICE_DT_INST_DEFINE(0, flash_init, NULL,
496 NULL, NULL, POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY,
497 &flash_sim_api);
498
499 #ifdef CONFIG_ARCH_POSIX
500
flash_native_cleanup(void)501 static void flash_native_cleanup(void)
502 {
503 flash_mock_cleanup_native(flash_in_ram, flash_fd, mock_flash,
504 FLASH_SIMULATOR_FLASH_SIZE, flash_file_path,
505 flash_rm_at_exit);
506 }
507
flash_native_options(void)508 static void flash_native_options(void)
509 {
510 static struct args_struct_t flash_options[] = {
511 { .option = "flash",
512 .name = "path",
513 .type = 's',
514 .dest = (void *)&flash_file_path,
515 .descript = "Path to binary file to be used as flash, by default \""
516 DEFAULT_FLASH_FILE_PATH "\""},
517 { .is_switch = true,
518 .option = "flash_erase",
519 .type = 'b',
520 .dest = (void *)&flash_erase_at_start,
521 .descript = "Erase the flash content at startup" },
522 { .is_switch = true,
523 .option = "flash_rm",
524 .type = 'b',
525 .dest = (void *)&flash_rm_at_exit,
526 .descript = "Remove the flash file when terminating the execution" },
527 { .is_switch = true,
528 .option = "flash_in_ram",
529 .type = 'b',
530 .dest = (void *)&flash_in_ram,
531 .descript = "Instead of a file, keep the file content just in RAM. If this is "
532 "set, flash, flash_erase & flash_rm are ignored. The flash content"
533 " is always erased at startup" },
534 ARG_TABLE_ENDMARKER
535 };
536
537 native_add_command_line_opts(flash_options);
538 }
539
540 NATIVE_TASK(flash_native_options, PRE_BOOT_1, 1);
541 NATIVE_TASK(flash_native_cleanup, ON_EXIT, 1);
542
543 #endif /* CONFIG_ARCH_POSIX */
544
545 /* Extension to generic flash driver API */
z_impl_flash_simulator_get_memory(const struct device * dev,size_t * mock_size)546 void *z_impl_flash_simulator_get_memory(const struct device *dev,
547 size_t *mock_size)
548 {
549 ARG_UNUSED(dev);
550
551 *mock_size = FLASH_SIMULATOR_FLASH_SIZE;
552 return mock_flash;
553 }
554
z_impl_flash_simulator_get_params(const struct device * dev)555 const struct flash_simulator_params *z_impl_flash_simulator_get_params(const struct device *dev)
556 {
557 ARG_UNUSED(dev);
558
559 #ifdef CONFIG_FLASH_SIMULATOR_CALLBACKS
560 return &flash_sim_params;
561 #else
562 return NULL;
563 #endif
564 }
565
566 #ifdef CONFIG_FLASH_SIMULATOR_CALLBACKS
z_impl_flash_simulator_set_callbacks(const struct device * dev,const struct flash_simulator_cb * cb)567 void z_impl_flash_simulator_set_callbacks(const struct device *dev,
568 const struct flash_simulator_cb *cb)
569 {
570 ARG_UNUSED(dev);
571 flash_simulator_cbs = cb;
572 }
573 #endif /* CONFIG_FLASH_SIMULATOR_CALLBACKS */
574
575 #ifdef CONFIG_USERSPACE
576
577 #include <zephyr/internal/syscall_handler.h>
578
z_vrfy_flash_simulator_get_memory(const struct device * dev,size_t * mock_size)579 void *z_vrfy_flash_simulator_get_memory(const struct device *dev,
580 size_t *mock_size)
581 {
582 K_OOPS(K_SYSCALL_SPECIFIC_DRIVER(dev, K_OBJ_DRIVER_FLASH, &flash_sim_api));
583
584 return z_impl_flash_simulator_get_memory(dev, mock_size);
585 }
586
z_vrfy_flash_simulator_set_callbacks(const struct device * dev,const struct flash_simulator_cb * cb)587 void z_vrfy_flash_simulator_set_callbacks(const struct device *dev,
588 const struct flash_simulator_cb *cb)
589 {
590 K_OOPS(K_SYSCALL_SPECIFIC_DRIVER(dev, K_OBJ_DRIVER_FLASH, &flash_sim_api));
591
592 z_impl_flash_simulator_set_callbacks(dev, cb);
593 }
594
z_vrfy_flash_simulator_get_params(const struct device * dev)595 const struct flash_simulator_params *z_vrfy_flash_simulator_get_params(const struct device *dev)
596 {
597 K_OOPS(K_SYSCALL_SPECIFIC_DRIVER(dev, K_OBJ_DRIVER_FLASH, &flash_sim_api));
598
599 return z_impl_flash_simulator_get_params(dev);
600 }
601
602 #include <zephyr/syscalls/flash_simulator_get_memory_mrsh.c>
603
604 #endif /* CONFIG_USERSPACE */
605