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 */