Reorganized Linux nonvolatile memory devices

This commit is contained in:
Silvano Seva 2024-04-03 21:16:08 +02:00
parent 5b9cc789b9
commit 6aee71ec84
3 changed files with 68 additions and 86 deletions

View File

@ -29,7 +29,7 @@
#define NVM_MAX_PATHLEN 256 #define NVM_MAX_PATHLEN 256
POSIX_FILE_DEVICE_DEFINE(stateDevice, NULL, 1024) POSIX_FILE_DEVICE_DEFINE(stateDevice, 1024)
const struct nvmPartition statePartitions[] = const struct nvmPartition statePartitions[] =
{ {
@ -43,15 +43,12 @@ const struct nvmPartition statePartitions[] =
} }
}; };
const struct nvmArea areas[] = const struct nvmDescriptor stateNvm =
{ {
{ .name = "Device state NVM area",
.name = "Device state NVM area", .dev = (const struct nvmDevice *) &stateDevice,
.dev = &stateDevice, .partNum = sizeof(statePartitions) / sizeof(struct nvmPartition),
.startAddr = 0x0000, .partitions = statePartitions
.size = 1024,
.partitions = statePartitions
}
}; };
@ -153,11 +150,12 @@ void nvm_terminate()
posixFile_terminate(&stateDevice); posixFile_terminate(&stateDevice);
} }
size_t nvm_getMemoryAreas(const struct nvmArea **list) const struct nvmDescriptor *nvm_getDesc(const size_t index)
{ {
*list = &areas[0]; if(index > 0)
return NULL;
return (sizeof(areas) / sizeof(struct nvmArea)); return &stateNvm;
} }
void nvm_readHwInfo(hwInfo_t *info) void nvm_readHwInfo(hwInfo_t *info)
@ -168,7 +166,7 @@ void nvm_readHwInfo(hwInfo_t *info)
int nvm_readVfoChannelData(channel_t *channel) int nvm_readVfoChannelData(channel_t *channel)
{ {
int ret = nvmArea_readPartition(&areas[0], 0, 0, channel, sizeof(channel_t)); int ret = nvm_read(0, 0, 0, channel, sizeof(channel_t));
if(ret < 0) if(ret < 0)
return ret; return ret;
@ -185,7 +183,7 @@ int nvm_readVfoChannelData(channel_t *channel)
int nvm_readSettings(settings_t *settings) int nvm_readSettings(settings_t *settings)
{ {
int ret = nvmArea_readPartition(&areas[0], 1, 0, settings, sizeof(settings_t)); int ret = nvm_read(0, 1, 0, settings, sizeof(settings_t));
if(ret < 0) if(ret < 0)
return ret; return ret;
@ -202,14 +200,14 @@ int nvm_readSettings(settings_t *settings)
int nvm_writeSettings(const settings_t *settings) int nvm_writeSettings(const settings_t *settings)
{ {
return nvmArea_writePartition(&areas[0], 1, 0, settings, sizeof(settings_t)); return nvm_write(0, 1, 0, settings, sizeof(settings_t));
} }
int nvm_writeSettingsAndVfo(const settings_t *settings, const channel_t *vfo) int nvm_writeSettingsAndVfo(const settings_t *settings, const channel_t *vfo)
{ {
int ret = nvmArea_writePartition(&areas[0], 1, 0, settings, sizeof(settings_t)); int ret = nvm_write(0, 1, 0, settings, sizeof(settings_t));
if(ret < 0) if(ret < 0)
return ret; return ret;
return nvmArea_writePartition(&areas[0], 0, 0, vfo, sizeof(channel_t)); return nvm_write(0, 0, 0, vfo, sizeof(channel_t));
} }

View File

@ -24,55 +24,43 @@
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <string.h>
#include "posix_file.h" #include "posix_file.h"
static const struct nvmParams posix_file_params = int posixFile_init(struct nvmFileDevice *dev, const char *fileName)
{ {
.write_size = 1, // struct nvmFileDevice *pDev = (struct nvmFileDevice *)(dev);
.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. // Test if file exists, if it doesn't create it.
int flags = O_RDWR; int flags = O_RDWR;
int ret = access(name, F_OK); int ret = access(fileName, F_OK);
if(ret != 0) if(ret != 0)
flags |= O_CREAT | O_EXCL; flags |= O_CREAT | O_EXCL;
// Open file // Open file
int fd = open(name, flags, S_IRUSR | S_IWUSR); int fd = open(fileName, flags, S_IRUSR | S_IWUSR);
if(fd < 0) if(fd < 0)
return fd; return fd;
// Truncate to size, pad with zeroes if extending. // Truncate to size, pad with zeroes if extending.
ftruncate(fd, cfg->fileSize); ftruncate(fd, dev->size);
*(int *)(dev->priv) = fd; dev->fd = fd;
return 0; return 0;
} }
int posixFile_terminate(const struct nvmDevice *dev) int posixFile_terminate(struct nvmFileDevice *dev)
{ {
int fd = *(int *)(dev->priv); // struct nvmFileDevice *pDev = (struct nvmFileDevice *)(dev);
if(fd < 0)
if(dev->fd < 0)
return -EBADF; return -EBADF;
fsync(fd); fsync(dev->fd);
close(fd); close(dev->fd);
*(int *)(dev->priv) = -1; dev->fd = -1;
return 0; return 0;
} }
@ -81,47 +69,45 @@ int posixFile_terminate(const struct nvmDevice *dev)
static int nvm_api_read(const struct nvmDevice *dev, uint32_t offset, static int nvm_api_read(const struct nvmDevice *dev, uint32_t offset,
void *data, size_t len) void *data, size_t len)
{ {
const struct posixFileCfg *cfg = (const struct posixFileCfg *)(dev->config); struct nvmFileDevice *pDev = (struct nvmFileDevice *)(dev);
const int fd = *(int *)(dev->priv);
if(fd < 0) if(pDev->fd < 0)
return -EBADF; return -EBADF;
if((offset + len) >= cfg->fileSize) if((offset + len) >= pDev->size)
return -EINVAL; return -EINVAL;
lseek(fd, offset, SEEK_SET); lseek(pDev->fd, offset, SEEK_SET);
return read(fd, data, len); return read(pDev->fd, data, len);
} }
static int nvm_api_write(const struct nvmDevice *dev, uint32_t offset, static int nvm_api_write(const struct nvmDevice *dev, uint32_t offset,
const void *data, size_t len) const void *data, size_t len)
{ {
const struct posixFileCfg *cfg = (const struct posixFileCfg *)(dev->config); struct nvmFileDevice *pDev = (struct nvmFileDevice *)(dev);
const int fd = *(int *)(dev->priv);
if(fd < 0) if(pDev->fd < 0)
return -EBADF; return -EBADF;
if((offset + len) >= cfg->fileSize) if((offset + len) > pDev->size)
return -EINVAL; return -EINVAL;
lseek(fd, offset, SEEK_SET); lseek(pDev->fd, offset, SEEK_SET);
return write(fd, data, len); return write(pDev->fd, data, len);
} }
static const struct nvmParams *nvm_api_params(const struct nvmDevice *dev) const struct nvmOps posix_file_ops =
{
(void) dev;
return &posix_file_params;
}
const struct nvmApi posix_file_api =
{ {
.read = nvm_api_read, .read = nvm_api_read,
.write = nvm_api_write, .write = nvm_api_write,
.erase = NULL, .erase = NULL,
.sync = NULL, .sync = NULL,
.params = nvm_api_params };
const struct nvmInfo posix_file_info =
{
.write_size = 1,
.erase_size = 1,
.erase_cycles = INT_MAX,
.device_info = NVM_FILE | NVM_WRITE | NVM_BITWRITE
}; };

View File

@ -32,37 +32,35 @@
/** /**
* Driver configuration data structure. * Driver configuration data structure.
*/ */
struct posixFileCfg struct nvmFileDevice
{ {
const char *fileName; ///< Full path of the file used for data storage const void *priv; ///< Device driver private data
const size_t fileSize; ///< File size, in bytes const struct nvmOps *ops; ///< Device operations
const struct nvmInfo *info; ///< Device info
const size_t size; ///< Device size
int fd; ///< File descriptor
}; };
/** /**
* Driver API functions. * Driver API functions and info.
*/ */
extern const struct nvmApi posix_file_api; extern const struct nvmOps posix_file_ops;
extern const struct nvmInfo posix_file_info;
/** /**
* Instantiate a POSIX file storage NVM device. * Instantiate a POSIX file storage NVM device.
* *
* @param name: device name. * @param name: device name.
* @param path: full path of the file used for data storage. * @param path: full path of the file used for data storage.
* @param size: size of the storage file, in bytes. * @param dim: size of the storage file, in bytes.
*/ */
#define POSIX_FILE_DEVICE_DEFINE(name, path, size) \ #define POSIX_FILE_DEVICE_DEFINE(name, dim) \
static int fd_##name; \ static struct nvmFileDevice name = \
static const struct posixFileCfg cfg_##name = \ { \
{ \ .ops = &posix_file_ops, \
.fileName = path, \ .info = &posix_file_info, \
.fileSize = size \ .size = dim, \
}; \ .fd = -1 \
static const struct nvmDevice name = \
{ \
.config = &cfg_##name, \
.priv = &fd_##name, \
.api = &posix_file_api \
}; };
/** /**
@ -71,10 +69,10 @@ static const struct nvmDevice name = \
* storage, where necessary. * storage, where necessary.
* *
* @param dev: pointer to device descriptor. * @param dev: pointer to device descriptor.
* @param fileName: alternative path of the file used for data storage or NULL. * @param fileName: full path of the file used for data storage.
* @return zero on success, a negative error code otherwise. * @return zero on success, a negative error code otherwise.
*/ */
int posixFile_init(const struct nvmDevice *dev, const char *fileName); int posixFile_init(struct nvmFileDevice *dev, const char *fileName);
/** /**
* Shut down a POSIX file driver instance. * Shut down a POSIX file driver instance.
@ -83,6 +81,6 @@ int posixFile_init(const struct nvmDevice *dev, const char *fileName);
* @param maxSize: maximum size for the storage file, in bytes. * @param maxSize: maximum size for the storage file, in bytes.
* @return zero on success, a negative error code otherwise. * @return zero on success, a negative error code otherwise.
*/ */
int posixFile_terminate(const struct nvmDevice *dev); int posixFile_terminate(struct nvmFileDevice *dev);
#endif /* POSIX_FILE_H */ #endif /* POSIX_FILE_H */