diff --git a/CMakeLists.txt b/CMakeLists.txt index ab901ee4..304223bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,6 +111,7 @@ target_sources(app openrtx/src/core/voicePrompts.c openrtx/src/core/voicePromptUtils.c openrtx/src/core/voicePromptData.S + openrtx/src/core/nvmem_access.c openrtx/src/rtx/rtx.cpp openrtx/src/rtx/OpMode_FM.cpp openrtx/src/rtx/OpMode_M17.cpp diff --git a/meson.build b/meson.build index 9ce86b02..a5b3b406 100644 --- a/meson.build +++ b/meson.build @@ -55,6 +55,7 @@ openrtx_src = ['openrtx/src/core/state.c', 'openrtx/src/core/voicePrompts.c', 'openrtx/src/core/voicePromptUtils.c', 'openrtx/src/core/voicePromptData.S', + 'openrtx/src/core/nvmem_access.c', 'openrtx/src/rtx/rtx.cpp', 'openrtx/src/rtx/OpMode_FM.cpp', 'openrtx/src/rtx/OpMode_M17.cpp', diff --git a/openrtx/include/core/nvmem_access.h b/openrtx/include/core/nvmem_access.h new file mode 100644 index 00000000..006cf5a2 --- /dev/null +++ b/openrtx/include/core/nvmem_access.h @@ -0,0 +1,139 @@ +/*************************************************************************** + * 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 NVMEM_ACCESS_H +#define NVMEM_ACCESS_H + +#include +#include +#include + +/** + * Perform a byte-aligned read operation on an NVM area. + * + * @param area: pointer to the NVM are descriptor. + * @param address: start address for the read operation. + * @param data: pointer to a buffer where to store the data read. + * @param len: number of bytes to read. + * @return zero on success, a negative error code otherwise. + */ +int nvmArea_read(const struct nvmArea *area, uint32_t address, void *data, size_t len); + +/** + * Perform a byte-aligned write operation on an NVM area. If the underlying + * device requires state syncing, a sync operation is performed at the end of + * the write. + * + * @param area: pointer to the NVM are descriptor. + * @param address: start address for the write operation. + * @param data: pointer to a buffer containing the data to write. + * @param len: number of bytes to write. + * @return zero on success, a negative error code otherwise. + */ +int nvmArea_write(const struct nvmArea *area, uint32_t address, const void *data, + size_t len); + +/** + * Perform an erase operation on an NVM area. Acceptable start address and size + * depend on the NVM device the area belongs to. + * + * @param area: pointer to the NVM are descriptor. + * @param address: start address for the erase operation. + * @param size: size of the area to be erased. + * @return zero on success, a negative error code otherwise. + */ +int nvmArea_erase(const struct nvmArea *area, uint32_t address, size_t size); + +/** + * Get the parameters of the NVM device associated to a memory area. + * + * @param area: pointer to the NVM are descriptor. + * @return pointer to the device parameters' data structure. + */ +static inline const struct nvmParams *nvmArea_params(const struct nvmArea *area) +{ + const struct nvmDevice *dev = area->dev; + + return dev->api->params(dev); +} + +/** + * Perform a byte-aligned read operation on an NVM area partition. + * + * @param area: pointer to the NVM are descriptor. + * @param pNum: partition number. + * @param address: start address for the read operation. + * @param data: pointer to a buffer where to store the data read. + * @param len: number of bytes to read. + * @return zero on success, a negative error code otherwise. + */ +static inline int nvmArea_readPartition(const struct nvmArea *area, + const uint32_t pNum, uint32_t offset, + void *data, size_t len) +{ + const struct nvmPartition *partition = &(area->partitions[pNum]); + const size_t startAddr = area->startAddr + partition->offset + offset; + + return nvmArea_read(area, startAddr, data, len); +} + +/** + * Perform a byte-aligned write operation on an NVM area partition. If the + * underlying device requires state syncing, a sync operation is performed at + * the end of the write. + * + * @param area: pointer to the NVM are descriptor. + * @param pNum: partition number. + * @param address: start address for the write operation. + * @param data: pointer to a buffer containing the data to write. + * @param len: number of bytes to write. + * @return zero on success, a negative error code otherwise. + */ +static inline int nvmArea_writePartition(const struct nvmArea *area, + const uint32_t pNum, uint32_t offset, + const void *data, size_t len) +{ + const struct nvmPartition *partition = &(area->partitions[pNum]); + const size_t startAddr = area->startAddr + partition->offset + offset; + + return nvmArea_write(area, startAddr, data, len); +} + +/** + * Perform an erase operation on an NVM area partition. Acceptable start address + * and size depend on the NVM device the area belongs to. + * + * @param area: pointer to the NVM are descriptor. + * @param pNum: partition number. + * @param address: start address for the erase operation. + * @param size: size of the area to be erased. + * @return zero on success, a negative error code otherwise. + */ +static inline int nvmArea_erasePartition(const struct nvmArea *area, + const uint32_t pNum, uint32_t offset, + size_t size) +{ + const struct nvmPartition *partition = &(area->partitions[pNum]); + const size_t startAddr = area->startAddr + partition->offset + offset; + + return nvmArea_erase(area, startAddr, size); +} + +#endif diff --git a/openrtx/src/core/nvmem_access.c b/openrtx/src/core/nvmem_access.c new file mode 100644 index 00000000..9ede2435 --- /dev/null +++ b/openrtx/src/core/nvmem_access.c @@ -0,0 +1,85 @@ +/*************************************************************************** + * 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 + + +/** + * \internal + * Check if a read/write/erase operation is within the bounds of a given NVM + * area. + * + * @param area: pointer to the NVM area descriptor + * @param addr: start address of the read/write/erase operation + * @param len: size of the read/write/erase operation + * @return true if the operation is within the NVM area bounds + */ +static inline bool checkBounds(const struct nvmArea *area, uint32_t addr, size_t len) +{ + return (addr >= area->startAddr) + && ((addr + len) < (area->startAddr + area->size)); +} + + +int nvmArea_read(const struct nvmArea *area, uint32_t address, void *data, size_t len) +{ + const struct nvmDevice *dev = area->dev; + + if(checkBounds(area, address, len) == false) + return -EINVAL; + + return dev->api->read(dev, address, data, len); +} + +int nvmArea_write(const struct nvmArea *area, uint32_t address, void *data, size_t len) +{ + const struct nvmDevice *dev = area->dev; + + if(checkBounds(area, address, len) == false) + return -EINVAL; + + if(dev->api->write == NULL) + return -ENOTSUP; + + int ret = dev->api->write(dev, address, data, len); + if(ret < 0) + return ret; + + if(dev->api->sync != NULL) + dev->api->sync(dev); + + return 0; +} + +int nvmArea_erase(const struct nvmArea *area, uint32_t address, size_t size) +{ + const struct nvmDevice *dev = area->dev; + + if(checkBounds(area, address, size) == false) + return -EINVAL; + + if(dev->api->erase == NULL) + return -ENOTSUP; + + return dev->api->erase(dev, address, size); +}