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 <alberto.escolar.piedras@nordicsemi.no>
This commit is contained in:
parent
4da4ee8ece
commit
3ee9b40a5a
6 changed files with 197 additions and 59 deletions
|
|
@ -702,7 +702,7 @@ host libC (:kconfig:option:`CONFIG_EXTERNAL_LIBC`):
|
|||
Console backend, :ref:`POSIX arch console <nsim_back_console>`, :kconfig:option:`CONFIG_POSIX_ARCH_CONSOLE`, All
|
||||
Display, :ref:`Display SDL <nsim_per_disp_sdl>`, :kconfig:option:`CONFIG_SDL_DISPLAY`, All
|
||||
Entropy, :ref:`Native posix entropy <nsim_per_entr>`, :kconfig:option:`CONFIG_FAKE_ENTROPY_NATIVE_POSIX`, All
|
||||
EEPROM, EEPROM simulator, :kconfig:option:`CONFIG_EEPROM_SIMULATOR`, Host libC
|
||||
EEPROM, EEPROM simulator, :kconfig:option:`CONFIG_EEPROM_SIMULATOR`, All
|
||||
EEPROM, EEPROM emulator, :kconfig:option:`CONFIG_EEPROM_EMULATOR`, All
|
||||
Ethernet, :ref:`Eth native_posix <nsim_per_ethe>`, :kconfig:option:`CONFIG_ETH_NATIVE_POSIX`, All
|
||||
Flash, :ref:`Flash simulator <nsim_per_flash_simu>`, :kconfig:option:`CONFIG_FLASH_SIMULATOR`, All
|
||||
|
|
|
|||
|
|
@ -10,7 +10,14 @@ zephyr_library_sources_ifdef(CONFIG_EEPROM_SHELL eeprom_shell.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_EEPROM_AT2X eeprom_at2x.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_EEPROM_LPC11U6X eeprom_lpc11u6x.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_EEPROM_STM32 eeprom_stm32.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_EEPROM_SIMULATOR eeprom_simulator.c)
|
||||
if(CONFIG_EEPROM_SIMULATOR)
|
||||
zephyr_library_sources(eeprom_simulator.c)
|
||||
if(CONFIG_NATIVE_LIBRARY)
|
||||
target_sources(native_simulator INTERFACE eeprom_simulator_native.c)
|
||||
elseif(CONFIG_ARCH_POSIX)
|
||||
zephyr_library_sources(eeprom_simulator_native.c)
|
||||
endif()
|
||||
endif()
|
||||
zephyr_library_sources_ifdef(CONFIG_EEPROM_EMULATOR eeprom_emulator.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_EEPROM_TMP116 eeprom_tmp116.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_EEPROM_XEC eeprom_mchp_xec.c)
|
||||
|
|
|
|||
|
|
@ -104,7 +104,6 @@ config EEPROM_SIMULATOR
|
|||
bool "Simulated EEPROM driver"
|
||||
default y
|
||||
depends on DT_HAS_ZEPHYR_SIM_EEPROM_ENABLED
|
||||
depends on !(ARCH_POSIX && !EXTERNAL_LIBC)
|
||||
select STATS
|
||||
select STATS_NAMES
|
||||
help
|
||||
|
|
|
|||
|
|
@ -8,18 +8,10 @@
|
|||
#define DT_DRV_COMPAT zephyr_sim_eeprom
|
||||
|
||||
#ifdef CONFIG_ARCH_POSIX
|
||||
#undef _POSIX_C_SOURCE
|
||||
/* Note: This is used only for interaction with the host C library, and is therefore exempt of
|
||||
* coding guidelines rule A.4&5 which applies to the embedded code using embedded libraries
|
||||
*/
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include "eeprom_simulator_native.h"
|
||||
#include "cmdline.h"
|
||||
#include "soc.h"
|
||||
#endif
|
||||
#endif /* CONFIG_ARCH_POSIX */
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/eeprom.h>
|
||||
|
|
@ -87,10 +79,13 @@ STATS_NAME(eeprom_sim_thresholds, max_len)
|
|||
STATS_NAME_END(eeprom_sim_thresholds);
|
||||
|
||||
#ifdef CONFIG_ARCH_POSIX
|
||||
static uint8_t *mock_eeprom;
|
||||
static char *mock_eeprom;
|
||||
static int eeprom_fd = -1;
|
||||
static const char *eeprom_file_path;
|
||||
static const char default_eeprom_file_path[] = "eeprom.bin";
|
||||
#define DEFAULT_EEPROM_FILE_PATH "eeprom.bin"
|
||||
static bool eeprom_erase_at_start;
|
||||
static bool eeprom_rm_at_exit;
|
||||
static bool eeprom_in_ram;
|
||||
#else
|
||||
static uint8_t mock_eeprom[DT_INST_PROP(0, size)];
|
||||
#endif /* CONFIG_ARCH_POSIX */
|
||||
|
|
@ -218,35 +213,22 @@ static const struct eeprom_sim_config eeprom_sim_config_0 = {
|
|||
|
||||
static int eeprom_mock_init(const struct device *dev)
|
||||
{
|
||||
if (eeprom_file_path == NULL) {
|
||||
eeprom_file_path = default_eeprom_file_path;
|
||||
int rc;
|
||||
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
if (eeprom_in_ram == false && eeprom_file_path == NULL) {
|
||||
eeprom_file_path = DEFAULT_EEPROM_FILE_PATH;
|
||||
}
|
||||
|
||||
eeprom_fd = open(eeprom_file_path, O_RDWR | O_CREAT, (mode_t)0600);
|
||||
if (eeprom_fd == -1) {
|
||||
posix_print_warning("Failed to open eeprom device file "
|
||||
"%s: %s\n",
|
||||
eeprom_file_path, strerror(errno));
|
||||
rc = eeprom_mock_init_native(eeprom_in_ram, &mock_eeprom, DT_INST_PROP(0, size), &eeprom_fd,
|
||||
eeprom_file_path, 0xFF, eeprom_erase_at_start);
|
||||
|
||||
if (rc < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (ftruncate(eeprom_fd, DT_INST_PROP(0, size)) == -1) {
|
||||
posix_print_warning("Failed to resize eeprom device file "
|
||||
"%s: %s\n",
|
||||
eeprom_file_path, strerror(errno));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mock_eeprom = mmap(NULL, DT_INST_PROP(0, size),
|
||||
PROT_WRITE | PROT_READ, MAP_SHARED, eeprom_fd, 0);
|
||||
if (mock_eeprom == MAP_FAILED) {
|
||||
posix_print_warning("Failed to mmap eeprom device file "
|
||||
"%s: %s\n",
|
||||
eeprom_file_path, strerror(errno));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
@ -269,35 +251,43 @@ static int eeprom_sim_init(const struct device *dev)
|
|||
return eeprom_mock_init(dev);
|
||||
}
|
||||
|
||||
DEVICE_DT_INST_DEFINE(0, &eeprom_sim_init, NULL,
|
||||
NULL, &eeprom_sim_config_0, POST_KERNEL,
|
||||
DEVICE_DT_INST_DEFINE(0, &eeprom_sim_init, NULL, NULL, &eeprom_sim_config_0, POST_KERNEL,
|
||||
CONFIG_EEPROM_INIT_PRIORITY, &eeprom_sim_api);
|
||||
|
||||
#ifdef CONFIG_ARCH_POSIX
|
||||
|
||||
static void eeprom_native_cleanup(void)
|
||||
{
|
||||
if ((mock_eeprom != MAP_FAILED) && (mock_eeprom != NULL)) {
|
||||
munmap(mock_eeprom, DT_INST_PROP(0, size));
|
||||
}
|
||||
|
||||
if (eeprom_fd != -1) {
|
||||
close(eeprom_fd);
|
||||
}
|
||||
eeprom_mock_cleanup_native(eeprom_in_ram, eeprom_fd, mock_eeprom, DT_INST_PROP(0, size),
|
||||
eeprom_file_path, eeprom_rm_at_exit);
|
||||
}
|
||||
|
||||
static void eeprom_native_options(void)
|
||||
{
|
||||
static struct args_struct_t eeprom_options[] = {
|
||||
{ .manual = false,
|
||||
.is_mandatory = false,
|
||||
.is_switch = false,
|
||||
.option = "eeprom",
|
||||
{.option = "eeprom",
|
||||
.name = "path",
|
||||
.type = 's',
|
||||
.dest = (void *)&eeprom_file_path,
|
||||
.call_when_found = NULL,
|
||||
.descript = "Path to binary file to be used as eeprom" },
|
||||
.descript = "Path to binary file to be used as EEPROM, by default "
|
||||
"\"" DEFAULT_EEPROM_FILE_PATH "\""},
|
||||
{.is_switch = true,
|
||||
.option = "eeprom_erase",
|
||||
.type = 'b',
|
||||
.dest = (void *)&eeprom_erase_at_start,
|
||||
.descript = "Erase the EEPROM content at startup"},
|
||||
{.is_switch = true,
|
||||
.option = "eeprom_rm",
|
||||
.type = 'b',
|
||||
.dest = (void *)&eeprom_rm_at_exit,
|
||||
.descript = "Remove the EEPROM file when terminating the execution"},
|
||||
{.is_switch = true,
|
||||
.option = "eeprom_in_ram",
|
||||
.type = 'b',
|
||||
.dest = (void *)&eeprom_in_ram,
|
||||
.descript = "Instead of a file, keep the file content just in RAM. If this is "
|
||||
"set, eeprom, eeprom_erase & eeprom_rm are ignored, and the EEPROM "
|
||||
"content is always erased at startup"},
|
||||
ARG_TABLE_ENDMARKER
|
||||
};
|
||||
|
||||
|
|
|
|||
114
drivers/eeprom/eeprom_simulator_native.c
Normal file
114
drivers/eeprom/eeprom_simulator_native.c
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Part of EEPROM simulator which interacts with the host OS / Linux
|
||||
*
|
||||
* When building for the native simulator, this file is built in the
|
||||
* native simulator runner/host context, and not in Zephyr/embedded context.
|
||||
*/
|
||||
|
||||
#undef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <nsi_tracing.h>
|
||||
|
||||
/*
|
||||
* Initialize the EEPROM buffer.
|
||||
* And, if the content is to be kept on disk map it to the buffer to the file.
|
||||
*
|
||||
* Returns -1 on failure
|
||||
* 0 on success
|
||||
*/
|
||||
int eeprom_mock_init_native(bool eeprom_in_ram, char **mock_eeprom, unsigned int size,
|
||||
int *eeprom_fd, const char *eeprom_file_path, unsigned int erase_value,
|
||||
bool eeprom_erase_at_start)
|
||||
{
|
||||
struct stat f_stat;
|
||||
int rc;
|
||||
|
||||
if (eeprom_in_ram == true) {
|
||||
*mock_eeprom = (char *)malloc(size);
|
||||
if (*mock_eeprom == NULL) {
|
||||
nsi_print_warning("Could not allocate EEPROM in the process heap %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
*eeprom_fd = open(eeprom_file_path, O_RDWR | O_CREAT, (mode_t)0600);
|
||||
if (*eeprom_fd == -1) {
|
||||
nsi_print_warning("Failed to open EEPROM device file %s: %s\n",
|
||||
eeprom_file_path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = fstat(*eeprom_fd, &f_stat);
|
||||
if (rc) {
|
||||
nsi_print_warning("Failed to get status of EEPROM device file %s: %s\n",
|
||||
eeprom_file_path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ftruncate(*eeprom_fd, size) == -1) {
|
||||
nsi_print_warning("Failed to resize EEPROM device file %s: %s\n",
|
||||
eeprom_file_path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
*mock_eeprom = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, *eeprom_fd, 0);
|
||||
if (*mock_eeprom == MAP_FAILED) {
|
||||
nsi_print_warning("Failed to mmap EEPROM device file %s: %s\n",
|
||||
eeprom_file_path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((eeprom_erase_at_start == true) || (eeprom_in_ram == true) || (f_stat.st_size == 0)) {
|
||||
/* Erase the EEPROM by setting all bits to the configured erase value */
|
||||
(void)memset(*mock_eeprom, erase_value, size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If in RAM: Free the mock buffer
|
||||
* If in disk: unmap the eeprom file from RAM, close the file, and if configured to do so,
|
||||
* delete the file.
|
||||
*/
|
||||
void eeprom_mock_cleanup_native(bool eeprom_in_ram, int eeprom_fd, char *mock_eeprom,
|
||||
unsigned int size, const char *eeprom_file_path,
|
||||
bool eeprom_rm_at_exit)
|
||||
{
|
||||
|
||||
if (eeprom_in_ram == true) {
|
||||
if (mock_eeprom != NULL) {
|
||||
free(mock_eeprom);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ((mock_eeprom != MAP_FAILED) && (mock_eeprom != NULL)) {
|
||||
munmap(mock_eeprom, size);
|
||||
}
|
||||
|
||||
if (eeprom_fd != -1) {
|
||||
close(eeprom_fd);
|
||||
}
|
||||
|
||||
if ((eeprom_rm_at_exit == true) && (eeprom_file_path != NULL)) {
|
||||
/* We try to remove the file but do not error out if we can't */
|
||||
(void)remove(eeprom_file_path);
|
||||
}
|
||||
}
|
||||
28
drivers/eeprom/eeprom_simulator_native.h
Normal file
28
drivers/eeprom/eeprom_simulator_native.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef DRIVERS_EEPROM_EEPROM_SIMULATOR_NATIVE_H
|
||||
#define DRIVERS_EEPROM_EEPROM_SIMULATOR_NATIVE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int eeprom_mock_init_native(bool eeprom_in_ram, char **mock_eeprom, unsigned int size,
|
||||
int *eeprom_fd, const char *eeprom_file_path, unsigned int erase_value,
|
||||
bool eeprom_erase_at_start);
|
||||
|
||||
void eeprom_mock_cleanup_native(bool eeprom_in_ram, int eeprom_fd, char *mock_eeprom,
|
||||
unsigned int size, const char *eeprom_file_path,
|
||||
bool eeprom_rm_at_exit);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DRIVERS_EEPROM_EEPROM_SIMULATOR_NATIVE_H */
|
||||
Loading…
Reference in a new issue