Skip to content

Commit 3ee9b40

Browse files
committed
eeprom sim: Enhance & refactor native part so it works w emb libCs
For the parts of the simulator which are dedicated for the native platforms (POSIX arch based): * Refactor the parts that interacts with the host, so it is possible to use it also with embedded libCs * Enhance it with more options to allow: * Keeping the content just in RAM * Erasing the EEPROM file at exit * Clearing the file at boot * Also show in the command line help the default file name. As part of this: * Update the kconfig dependencies, so we allow building it with other C libraries in the native targets * Update the table in the native_sim docs to indicate all C libraries are supproted now Signed-off-by: Alberto Escolar Piedras <[email protected]>
1 parent 4da4ee8 commit 3ee9b40

File tree

6 files changed

+195
-57
lines changed

6 files changed

+195
-57
lines changed

boards/native/native_sim/doc/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ host libC (:kconfig:option:`CONFIG_EXTERNAL_LIBC`):
702702
Console backend, :ref:`POSIX arch console <nsim_back_console>`, :kconfig:option:`CONFIG_POSIX_ARCH_CONSOLE`, All
703703
Display, :ref:`Display SDL <nsim_per_disp_sdl>`, :kconfig:option:`CONFIG_SDL_DISPLAY`, All
704704
Entropy, :ref:`Native posix entropy <nsim_per_entr>`, :kconfig:option:`CONFIG_FAKE_ENTROPY_NATIVE_POSIX`, All
705-
EEPROM, EEPROM simulator, :kconfig:option:`CONFIG_EEPROM_SIMULATOR`, Host libC
705+
EEPROM, EEPROM simulator, :kconfig:option:`CONFIG_EEPROM_SIMULATOR`, All
706706
EEPROM, EEPROM emulator, :kconfig:option:`CONFIG_EEPROM_EMULATOR`, All
707707
Ethernet, :ref:`Eth native_posix <nsim_per_ethe>`, :kconfig:option:`CONFIG_ETH_NATIVE_POSIX`, All
708708
Flash, :ref:`Flash simulator <nsim_per_flash_simu>`, :kconfig:option:`CONFIG_FLASH_SIMULATOR`, All

drivers/eeprom/CMakeLists.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,14 @@ zephyr_library_sources_ifdef(CONFIG_EEPROM_SHELL eeprom_shell.c)
1010
zephyr_library_sources_ifdef(CONFIG_EEPROM_AT2X eeprom_at2x.c)
1111
zephyr_library_sources_ifdef(CONFIG_EEPROM_LPC11U6X eeprom_lpc11u6x.c)
1212
zephyr_library_sources_ifdef(CONFIG_EEPROM_STM32 eeprom_stm32.c)
13-
zephyr_library_sources_ifdef(CONFIG_EEPROM_SIMULATOR eeprom_simulator.c)
13+
if(CONFIG_EEPROM_SIMULATOR)
14+
zephyr_library_sources(eeprom_simulator.c)
15+
if(CONFIG_NATIVE_LIBRARY)
16+
target_sources(native_simulator INTERFACE eeprom_simulator_native.c)
17+
elseif(CONFIG_ARCH_POSIX)
18+
zephyr_library_sources(eeprom_simulator_native.c)
19+
endif()
20+
endif()
1421
zephyr_library_sources_ifdef(CONFIG_EEPROM_EMULATOR eeprom_emulator.c)
1522
zephyr_library_sources_ifdef(CONFIG_EEPROM_TMP116 eeprom_tmp116.c)
1623
zephyr_library_sources_ifdef(CONFIG_EEPROM_XEC eeprom_mchp_xec.c)

drivers/eeprom/Kconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ config EEPROM_SIMULATOR
104104
bool "Simulated EEPROM driver"
105105
default y
106106
depends on DT_HAS_ZEPHYR_SIM_EEPROM_ENABLED
107-
depends on !(ARCH_POSIX && !EXTERNAL_LIBC)
108107
select STATS
109108
select STATS_NAMES
110109
help

drivers/eeprom/eeprom_simulator.c

Lines changed: 44 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,10 @@
88
#define DT_DRV_COMPAT zephyr_sim_eeprom
99

1010
#ifdef CONFIG_ARCH_POSIX
11-
#undef _POSIX_C_SOURCE
12-
/* Note: This is used only for interaction with the host C library, and is therefore exempt of
13-
* coding guidelines rule A.4&5 which applies to the embedded code using embedded libraries
14-
*/
15-
#define _POSIX_C_SOURCE 200809L
16-
#include <unistd.h>
17-
#include <sys/types.h>
18-
#include <sys/mman.h>
19-
#include <fcntl.h>
11+
#include "eeprom_simulator_native.h"
2012
#include "cmdline.h"
2113
#include "soc.h"
22-
#endif
14+
#endif /* CONFIG_ARCH_POSIX */
2315

2416
#include <zephyr/device.h>
2517
#include <zephyr/drivers/eeprom.h>
@@ -87,10 +79,13 @@ STATS_NAME(eeprom_sim_thresholds, max_len)
8779
STATS_NAME_END(eeprom_sim_thresholds);
8880

8981
#ifdef CONFIG_ARCH_POSIX
90-
static uint8_t *mock_eeprom;
82+
static char *mock_eeprom;
9183
static int eeprom_fd = -1;
9284
static const char *eeprom_file_path;
93-
static const char default_eeprom_file_path[] = "eeprom.bin";
85+
#define DEFAULT_EEPROM_FILE_PATH "eeprom.bin"
86+
static bool eeprom_erase_at_start;
87+
static bool eeprom_rm_at_exit;
88+
static bool eeprom_in_ram;
9489
#else
9590
static uint8_t mock_eeprom[DT_INST_PROP(0, size)];
9691
#endif /* CONFIG_ARCH_POSIX */
@@ -218,35 +213,22 @@ static const struct eeprom_sim_config eeprom_sim_config_0 = {
218213

219214
static int eeprom_mock_init(const struct device *dev)
220215
{
221-
if (eeprom_file_path == NULL) {
222-
eeprom_file_path = default_eeprom_file_path;
223-
}
216+
int rc;
224217

225-
eeprom_fd = open(eeprom_file_path, O_RDWR | O_CREAT, (mode_t)0600);
226-
if (eeprom_fd == -1) {
227-
posix_print_warning("Failed to open eeprom device file "
228-
"%s: %s\n",
229-
eeprom_file_path, strerror(errno));
230-
return -EIO;
231-
}
218+
ARG_UNUSED(dev);
232219

233-
if (ftruncate(eeprom_fd, DT_INST_PROP(0, size)) == -1) {
234-
posix_print_warning("Failed to resize eeprom device file "
235-
"%s: %s\n",
236-
eeprom_file_path, strerror(errno));
237-
return -EIO;
220+
if (eeprom_in_ram == false && eeprom_file_path == NULL) {
221+
eeprom_file_path = DEFAULT_EEPROM_FILE_PATH;
238222
}
239223

240-
mock_eeprom = mmap(NULL, DT_INST_PROP(0, size),
241-
PROT_WRITE | PROT_READ, MAP_SHARED, eeprom_fd, 0);
242-
if (mock_eeprom == MAP_FAILED) {
243-
posix_print_warning("Failed to mmap eeprom device file "
244-
"%s: %s\n",
245-
eeprom_file_path, strerror(errno));
224+
rc = eeprom_mock_init_native(eeprom_in_ram, &mock_eeprom, DT_INST_PROP(0, size), &eeprom_fd,
225+
eeprom_file_path, 0xFF, eeprom_erase_at_start);
226+
227+
if (rc < 0) {
246228
return -EIO;
229+
} else {
230+
return 0;
247231
}
248-
249-
return 0;
250232
}
251233

252234
#else
@@ -269,35 +251,43 @@ static int eeprom_sim_init(const struct device *dev)
269251
return eeprom_mock_init(dev);
270252
}
271253

272-
DEVICE_DT_INST_DEFINE(0, &eeprom_sim_init, NULL,
273-
NULL, &eeprom_sim_config_0, POST_KERNEL,
274-
CONFIG_EEPROM_INIT_PRIORITY, &eeprom_sim_api);
254+
DEVICE_DT_INST_DEFINE(0, &eeprom_sim_init, NULL, NULL, &eeprom_sim_config_0, POST_KERNEL,
255+
CONFIG_EEPROM_INIT_PRIORITY, &eeprom_sim_api);
275256

276257
#ifdef CONFIG_ARCH_POSIX
277258

278259
static void eeprom_native_cleanup(void)
279260
{
280-
if ((mock_eeprom != MAP_FAILED) && (mock_eeprom != NULL)) {
281-
munmap(mock_eeprom, DT_INST_PROP(0, size));
282-
}
283-
284-
if (eeprom_fd != -1) {
285-
close(eeprom_fd);
286-
}
261+
eeprom_mock_cleanup_native(eeprom_in_ram, eeprom_fd, mock_eeprom, DT_INST_PROP(0, size),
262+
eeprom_file_path, eeprom_rm_at_exit);
287263
}
288264

289265
static void eeprom_native_options(void)
290266
{
291267
static struct args_struct_t eeprom_options[] = {
292-
{ .manual = false,
293-
.is_mandatory = false,
294-
.is_switch = false,
295-
.option = "eeprom",
296-
.name = "path",
297-
.type = 's',
298-
.dest = (void *)&eeprom_file_path,
299-
.call_when_found = NULL,
300-
.descript = "Path to binary file to be used as eeprom" },
268+
{.option = "eeprom",
269+
.name = "path",
270+
.type = 's',
271+
.dest = (void *)&eeprom_file_path,
272+
.descript = "Path to binary file to be used as EEPROM, by default "
273+
"\"" DEFAULT_EEPROM_FILE_PATH "\""},
274+
{.is_switch = true,
275+
.option = "eeprom_erase",
276+
.type = 'b',
277+
.dest = (void *)&eeprom_erase_at_start,
278+
.descript = "Erase the EEPROM content at startup"},
279+
{.is_switch = true,
280+
.option = "eeprom_rm",
281+
.type = 'b',
282+
.dest = (void *)&eeprom_rm_at_exit,
283+
.descript = "Remove the EEPROM file when terminating the execution"},
284+
{.is_switch = true,
285+
.option = "eeprom_in_ram",
286+
.type = 'b',
287+
.dest = (void *)&eeprom_in_ram,
288+
.descript = "Instead of a file, keep the file content just in RAM. If this is "
289+
"set, eeprom, eeprom_erase & eeprom_rm are ignored, and the EEPROM "
290+
"content is always erased at startup"},
301291
ARG_TABLE_ENDMARKER
302292
};
303293

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Part of EEPROM simulator which interacts with the host OS / Linux
7+
*
8+
* When building for the native simulator, this file is built in the
9+
* native simulator runner/host context, and not in Zephyr/embedded context.
10+
*/
11+
12+
#undef _POSIX_C_SOURCE
13+
#define _POSIX_C_SOURCE 200809L
14+
15+
#include <unistd.h>
16+
#include <sys/types.h>
17+
#include <sys/stat.h>
18+
#include <sys/mman.h>
19+
#include <fcntl.h>
20+
#include <errno.h>
21+
#include <stdio.h>
22+
#include <stdlib.h>
23+
#include <stdbool.h>
24+
#include <string.h>
25+
#include <nsi_tracing.h>
26+
27+
/*
28+
* Initialize the EEPROM buffer.
29+
* And, if the content is to be kept on disk map it to the buffer to the file.
30+
*
31+
* Returns -1 on failure
32+
* 0 on success
33+
*/
34+
int eeprom_mock_init_native(bool eeprom_in_ram, char **mock_eeprom, unsigned int size,
35+
int *eeprom_fd, const char *eeprom_file_path, unsigned int erase_value,
36+
bool eeprom_erase_at_start)
37+
{
38+
struct stat f_stat;
39+
int rc;
40+
41+
if (eeprom_in_ram == true) {
42+
*mock_eeprom = (char *)malloc(size);
43+
if (*mock_eeprom == NULL) {
44+
nsi_print_warning("Could not allocate EEPROM in the process heap %s\n",
45+
strerror(errno));
46+
return -1;
47+
}
48+
} else {
49+
*eeprom_fd = open(eeprom_file_path, O_RDWR | O_CREAT, (mode_t)0600);
50+
if (*eeprom_fd == -1) {
51+
nsi_print_warning("Failed to open EEPROM device file %s: %s\n",
52+
eeprom_file_path, strerror(errno));
53+
return -1;
54+
}
55+
56+
rc = fstat(*eeprom_fd, &f_stat);
57+
if (rc) {
58+
nsi_print_warning("Failed to get status of EEPROM device file %s: %s\n",
59+
eeprom_file_path, strerror(errno));
60+
return -1;
61+
}
62+
63+
if (ftruncate(*eeprom_fd, size) == -1) {
64+
nsi_print_warning("Failed to resize EEPROM device file %s: %s\n",
65+
eeprom_file_path, strerror(errno));
66+
return -1;
67+
}
68+
69+
*mock_eeprom = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, *eeprom_fd, 0);
70+
if (*mock_eeprom == MAP_FAILED) {
71+
nsi_print_warning("Failed to mmap EEPROM device file %s: %s\n",
72+
eeprom_file_path, strerror(errno));
73+
return -1;
74+
}
75+
}
76+
77+
if ((eeprom_erase_at_start == true) || (eeprom_in_ram == true) || (f_stat.st_size == 0)) {
78+
/* Erase the EEPROM by setting all bits to the configured erase value */
79+
(void)memset(*mock_eeprom, erase_value, size);
80+
}
81+
82+
return 0;
83+
}
84+
85+
/*
86+
* If in RAM: Free the mock buffer
87+
* If in disk: unmap the eeprom file from RAM, close the file, and if configured to do so,
88+
* delete the file.
89+
*/
90+
void eeprom_mock_cleanup_native(bool eeprom_in_ram, int eeprom_fd, char *mock_eeprom,
91+
unsigned int size, const char *eeprom_file_path,
92+
bool eeprom_rm_at_exit)
93+
{
94+
95+
if (eeprom_in_ram == true) {
96+
if (mock_eeprom != NULL) {
97+
free(mock_eeprom);
98+
}
99+
return;
100+
}
101+
102+
if ((mock_eeprom != MAP_FAILED) && (mock_eeprom != NULL)) {
103+
munmap(mock_eeprom, size);
104+
}
105+
106+
if (eeprom_fd != -1) {
107+
close(eeprom_fd);
108+
}
109+
110+
if ((eeprom_rm_at_exit == true) && (eeprom_file_path != NULL)) {
111+
/* We try to remove the file but do not error out if we can't */
112+
(void)remove(eeprom_file_path);
113+
}
114+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef DRIVERS_EEPROM_EEPROM_SIMULATOR_NATIVE_H
8+
#define DRIVERS_EEPROM_EEPROM_SIMULATOR_NATIVE_H
9+
10+
#include <stdbool.h>
11+
12+
#ifdef __cplusplus
13+
extern "C" {
14+
#endif
15+
16+
int eeprom_mock_init_native(bool eeprom_in_ram, char **mock_eeprom, unsigned int size,
17+
int *eeprom_fd, const char *eeprom_file_path, unsigned int erase_value,
18+
bool eeprom_erase_at_start);
19+
20+
void eeprom_mock_cleanup_native(bool eeprom_in_ram, int eeprom_fd, char *mock_eeprom,
21+
unsigned int size, const char *eeprom_file_path,
22+
bool eeprom_rm_at_exit);
23+
24+
#ifdef __cplusplus
25+
}
26+
#endif
27+
28+
#endif /* DRIVERS_EEPROM_EEPROM_SIMULATOR_NATIVE_H */

0 commit comments

Comments
 (0)