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,26 @@ static const struct flash_parameters flash_sim_parameters = {
170172 },
171173};
172174
175+
176+ #ifdef CONFIG_FLASH_SIMULATOR_CALLBACKS
177+ #ifdef CONFIG_ARCH_POSIX
178+ static struct flash_simulator_params flash_sim_params = {
179+ #else
180+ static const struct flash_simulator_params flash_sim_params = {
181+ .memory = mock_flash ,
182+ #endif
183+ .memory_size = FLASH_SIMULATOR_FLASH_SIZE ,
184+ .base_offset = FLASH_SIMULATOR_BASE_OFFSET ,
185+ .erase_unit = FLASH_SIMULATOR_ERASE_UNIT ,
186+ .prog_unit = FLASH_SIMULATOR_PROG_UNIT ,
187+ .explicit_erase = IS_ENABLED (CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE ),
188+ .erase_value = FLASH_SIMULATOR_ERASE_VALUE ,
189+ };
190+
191+ static const struct flash_simulator_cb * flash_simulator_cbs ;
192+ #endif /* CONFIG_FLASH_SIMULATOR_CALLBACKS */
193+
194+
173195static int flash_range_is_valid (const struct device * dev , off_t offset ,
174196 size_t len )
175197{
@@ -231,7 +253,7 @@ static int flash_sim_write(const struct device *dev, const off_t offset,
231253
232254 FLASH_SIM_STATS_INC (flash_sim_stats , flash_write_calls );
233255
234- #if defined( CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE )
256+ #ifdef CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE
235257 /* check if any unit has been already programmed */
236258 memset (buf , FLASH_SIMULATOR_ERASE_VALUE , sizeof (buf ));
237259#else
@@ -264,6 +286,15 @@ static int flash_sim_write(const struct device *dev, const off_t offset,
264286 }
265287#endif
266288
289+ #ifdef CONFIG_FLASH_SIMULATOR_CALLBACKS
290+ flash_simulator_write_byte_cb_t write_cb = NULL ;
291+ const struct flash_simulator_cb * cb = flash_simulator_cbs ;
292+
293+ if (cb != NULL ) {
294+ write_cb = cb -> write_byte ;
295+ }
296+ #endif /* CONFIG_FLASH_SIMULATOR_CALLBACKS */
297+
267298 for (uint32_t i = 0 ; i < len ; i ++ ) {
268299#ifdef CONFIG_FLASH_SIMULATOR_STATS
269300 if (data_part_ignored ) {
@@ -273,16 +304,28 @@ static int flash_sim_write(const struct device *dev, const off_t offset,
273304 }
274305#endif /* CONFIG_FLASH_SIMULATOR_STATS */
275306
276- /* only pull bits to zero */
277- #if defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE )
307+ uint8_t data_val = * ((const uint8_t * )data + i );
308+
309+ #ifdef CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE
278310#if FLASH_SIMULATOR_ERASE_VALUE == 0xFF
279- * (MOCK_FLASH (offset + i )) &= * ((uint8_t * )data + i );
311+ /* only pull bits to zero */
312+ data_val &= * (MOCK_FLASH (offset + i ));
280313#else
281- * (MOCK_FLASH (offset + i )) |= * ((uint8_t * )data + i );
314+ /* only pull bits to one */
315+ data_val |= * (MOCK_FLASH (offset + i ));
282316#endif
283- #else
284- * (MOCK_FLASH (offset + i )) = * ((uint8_t * )data + i );
285317#endif
318+ #ifdef CONFIG_FLASH_SIMULATOR_CALLBACKS
319+ if (write_cb != NULL ) {
320+ int ret = write_cb (dev , & flash_sim_params ,
321+ offset + i , data_val );
322+ if (ret < 0 ) {
323+ return ret ;
324+ }
325+ data_val = (uint8_t )ret ;
326+ }
327+ #endif /* CONFIG_FLASH_SIMULATOR_CALLBACKS */
328+ * (MOCK_FLASH (offset + i )) = data_val ;
286329 }
287330
288331 FLASH_SIM_STATS_INCN (flash_sim_stats , bytes_written , len );
@@ -297,20 +340,31 @@ static int flash_sim_write(const struct device *dev, const off_t offset,
297340 return 0 ;
298341}
299342
300- static void unit_erase (const uint32_t unit )
343+ static int unit_erase (const struct device * dev , const uint32_t unit )
301344{
302345 const off_t unit_addr = unit * FLASH_SIMULATOR_ERASE_UNIT ;
303346
347+ #ifdef CONFIG_FLASH_SIMULATOR_CALLBACKS
348+ flash_simulator_erase_unit_cb_t erase_cb = NULL ;
349+ const struct flash_simulator_cb * cb = flash_simulator_cbs ;
350+
351+ if (cb != NULL ) {
352+ erase_cb = cb -> erase_unit ;
353+ }
354+ if (erase_cb != NULL ) {
355+ return erase_cb (dev , & flash_sim_params , unit_addr );
356+ }
357+ #endif /* CONFIG_FLASH_SIMULATOR_CALLBACKS */
358+
304359 /* erase the memory unit by setting it to erase value */
305360 memset (MOCK_FLASH (unit_addr ), FLASH_SIMULATOR_ERASE_VALUE ,
306361 FLASH_SIMULATOR_ERASE_UNIT );
362+ return 0 ;
307363}
308364
309365static int flash_sim_erase (const struct device * dev , const off_t offset ,
310366 const size_t len )
311367{
312- ARG_UNUSED (dev );
313-
314368 if (!flash_range_is_valid (dev , offset , len )) {
315369 return - EINVAL ;
316370 }
@@ -335,8 +389,13 @@ static int flash_sim_erase(const struct device *dev, const off_t offset,
335389
336390 /* erase as many units as necessary and increase their erase counter */
337391 for (uint32_t i = 0 ; i < len / FLASH_SIMULATOR_ERASE_UNIT ; i ++ ) {
392+ int ret ;
393+
338394 ERASE_CYCLES_INC (unit_start + i );
339- unit_erase (unit_start + i );
395+ ret = unit_erase (dev , unit_start + i );
396+ if (ret < 0 ) {
397+ return ret ;
398+ }
340399 }
341400
342401#ifdef CONFIG_FLASH_SIMULATOR_SIMULATE_TIMING
@@ -405,6 +464,9 @@ static int flash_mock_init(const struct device *dev)
405464 rc = flash_mock_init_native (flash_in_ram , & mock_flash , FLASH_SIMULATOR_FLASH_SIZE ,
406465 & flash_fd , flash_file_path , FLASH_SIMULATOR_ERASE_VALUE ,
407466 flash_erase_at_start );
467+ #ifdef CONFIG_FLASH_SIMULATOR_CALLBACKS
468+ flash_sim_params .memory = mock_flash ;
469+ #endif
408470
409471 if (rc < 0 ) {
410472 return - EIO ;
@@ -498,6 +560,15 @@ void *z_impl_flash_simulator_get_memory(const struct device *dev,
498560 return mock_flash ;
499561}
500562
563+ #ifdef CONFIG_FLASH_SIMULATOR_CALLBACKS
564+ void z_impl_flash_simulator_set_callbacks (const struct device * dev ,
565+ const struct flash_simulator_cb * cb )
566+ {
567+ ARG_UNUSED (dev );
568+ flash_simulator_cbs = cb ;
569+ }
570+ #endif /* CONFIG_FLASH_SIMULATOR_CALLBACKS */
571+
501572#ifdef CONFIG_USERSPACE
502573
503574#include <zephyr/internal/syscall_handler.h>
@@ -510,6 +581,14 @@ void *z_vrfy_flash_simulator_get_memory(const struct device *dev,
510581 return z_impl_flash_simulator_get_memory (dev , mock_size );
511582}
512583
584+ void z_vrfy_flash_simulator_set_callbacks (const struct device * dev ,
585+ const struct flash_simulator_cb * cb )
586+ {
587+ K_OOPS (K_SYSCALL_SPECIFIC_DRIVER (dev , K_OBJ_DRIVER_FLASH , & flash_sim_api ));
588+
589+ z_impl_flash_simulator_set_callbacks (dev , cb );
590+ }
591+
513592#include <zephyr/syscalls/flash_simulator_get_memory_mrsh.c>
514593
515594#endif /* CONFIG_USERSPACE */
0 commit comments