diff --git a/openrtx/include/interfaces/nvmem.h b/openrtx/include/interfaces/nvmem.h
index bfcaf5d7..e37ea4ea 100644
--- a/openrtx/include/interfaces/nvmem.h
+++ b/openrtx/include/interfaces/nvmem.h
@@ -36,7 +36,8 @@ extern "C" {
enum nvmType
{
NVM_FLASH = 0, ///< FLASH type non volatile memory
- NVM_EEPROM ///< EEPROM type non volatile memory
+ NVM_EEPROM, ///< EEPROM type non volatile memory
+ NVM_FILE ///< File type non volatile memory
};
/**
diff --git a/platform/drivers/NVM/posix_file.c b/platform/drivers/NVM/posix_file.c
new file mode 100644
index 00000000..6a64c9f4
--- /dev/null
+++ b/platform/drivers/NVM/posix_file.c
@@ -0,0 +1,127 @@
+/***************************************************************************
+ * Copyright (C) 2023 by Federico Amedeo Izzo IU2NUO, *
+ * Niccolò Izzo IU2KIN *
+ * Frederik Saraci IU2NRO *
+ * Silvano Seva IU2KWO *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, see *
+ ***************************************************************************/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "posix_file.h"
+
+static const struct nvmParams posix_file_params =
+{
+ .write_size = 1,
+ .erase_size = 1,
+ .erase_cycles = INT_MAX,
+ .type = NVM_FILE
+};
+
+
+int posixFile_init(const struct nvmDevice *dev, const char *fileName)
+{
+ const struct posixFileCfg *cfg = (const struct posixFileCfg *)(dev->config);
+ const char *name = cfg->fileName;
+
+ // Override filename from config, if a new one is provided.
+ if(fileName != NULL)
+ name = fileName;
+
+ // Test if file exists, if it doesn't create it.
+ int flags = O_RDWR;
+ int ret = access(name, F_OK);
+ if(ret != 0)
+ flags |= O_CREAT | O_EXCL;
+
+ // Open file
+ int fd = open(name, flags, S_IRUSR | S_IWUSR);
+ if(fd < 0)
+ return fd;
+
+ // Truncate to size, pad with zeroes if extending.
+ ftruncate(fd, cfg->fileSize);
+
+ *(int *)(dev->priv) = fd;
+
+ return 0;
+}
+
+int posixFile_terminate(const struct nvmDevice *dev)
+{
+ int fd = *(int *)(dev->priv);
+ if(fd < 0)
+ return -EBADF;
+
+ fsync(fd);
+ close(fd);
+
+ *(int *)(dev->priv) = -1;
+
+ return 0;
+}
+
+
+static int nvm_api_read(const struct nvmDevice *dev, uint32_t offset,
+ void *data, size_t len)
+{
+ const struct posixFileCfg *cfg = (const struct posixFileCfg *)(dev->config);
+ const int fd = *(int *)(dev->priv);
+
+ if(fd < 0)
+ return -EBADF;
+
+ if((offset + len) >= cfg->fileSize)
+ return -EINVAL;
+
+ lseek(fd, offset, SEEK_SET);
+ return read(fd, data, len);
+}
+
+static int nvm_api_write(const struct nvmDevice *dev, uint32_t offset,
+ const void *data, size_t len)
+{
+ const struct posixFileCfg *cfg = (const struct posixFileCfg *)(dev->config);
+ const int fd = *(int *)(dev->priv);
+
+ if(fd < 0)
+ return -EBADF;
+
+ if((offset + len) >= cfg->fileSize)
+ return -EINVAL;
+
+ lseek(fd, offset, SEEK_SET);
+ return write(fd, data, len);
+}
+
+static const struct nvmParams *nvm_api_params(const struct nvmDevice *dev)
+{
+ (void) dev;
+
+ return &posix_file_params;
+}
+
+const struct nvmApi posix_file_api =
+{
+ .read = nvm_api_read,
+ .write = nvm_api_write,
+ .erase = NULL,
+ .sync = NULL,
+ .params = nvm_api_params
+};
diff --git a/platform/drivers/NVM/posix_file.h b/platform/drivers/NVM/posix_file.h
new file mode 100644
index 00000000..f58d6b3c
--- /dev/null
+++ b/platform/drivers/NVM/posix_file.h
@@ -0,0 +1,88 @@
+/***************************************************************************
+ * Copyright (C) 2023 by Federico Amedeo Izzo IU2NUO, *
+ * Niccolò Izzo IU2KIN *
+ * Frederik Saraci IU2NRO *
+ * Silvano Seva IU2KWO *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, see *
+ ***************************************************************************/
+
+#ifndef POSIX_FILE_H
+#define POSIX_FILE_H
+
+#include
+
+/**
+ * Device driver for file-based nonvolatile memory storage. The driver
+ * implementation is based on the POSIX syscalls for file management.
+ */
+
+
+/**
+ * Driver configuration data structure.
+ */
+struct posixFileCfg
+{
+ const char *fileName; ///< Full path of the file used for data storage
+ const size_t fileSize; ///< File size, in bytes
+};
+
+/**
+ * Driver API functions.
+ */
+extern const struct nvmApi posix_file_api;
+
+
+/**
+ * Instantiate a POSIX file storage NVM device.
+ *
+ * @param name: device name.
+ * @param path: full path of the file used for data storage.
+ * @param size: size of the storage file, in bytes.
+ */
+#define POSIX_FILE_DEVICE_DEFINE(name, path, size) \
+static int fd_##name; \
+static const struct posixFileCfg cfg_##name = \
+{ \
+ .fileName = path, \
+ .fileSize = size \
+}; \
+static const struct nvmDevice name = \
+{ \
+ .config = &cfg_##name, \
+ .priv = &fd_##name, \
+ .api = &posix_file_api \
+};
+
+/**
+ * Initialize a POSIX file driver instance.
+ * This function allows also to override the path of the file used for data
+ * storage, where necessary.
+ *
+ * @param dev: pointer to device descriptor.
+ * @param fileName: alternative path of the file used for data storage or NULL.
+ * @return zero on success, a negative error code otherwise.
+ */
+int posixFile_init(const struct nvmDevice *dev, const char *fileName);
+
+/**
+ * Shut down a POSIX file driver instance.
+ *
+ * @param dev: pointer to device descriptor.
+ * @param maxSize: maximum size for the storage file, in bytes.
+ * @return zero on success, a negative error code otherwise.
+ */
+int posixFile_terminate(const struct nvmDevice *dev);
+
+#endif /* POSIX_FILE_H */