From fa0241974d5dfbc35942757dccdff6df72cbaf97 Mon Sep 17 00:00:00 2001 From: eduazocar Date: Wed, 12 Oct 2022 00:47:15 -0400 Subject: [PATCH] firmware/sys/storage: Added supports to del registers an rwp bit set --- firmware/sys/storage/Makefile | 3 + firmware/sys/storage/include/storage.h | 64 ----- .../sys/storage/include/storage_internal.h | 73 ++++++ .../sys/storage/include/storage_register.h | 106 ++++++++ firmware/sys/storage/storage.c | 230 +----------------- firmware/sys/storage/storage_internal.c | 149 ++++++++++++ firmware/sys/storage/storage_register.c | 212 ++++++++++++++++ tests/system_storage/main.c | 13 +- 8 files changed, 554 insertions(+), 296 deletions(-) create mode 100644 firmware/sys/storage/include/storage_internal.h create mode 100644 firmware/sys/storage/include/storage_register.h create mode 100644 firmware/sys/storage/storage_internal.c create mode 100644 firmware/sys/storage/storage_register.c diff --git a/firmware/sys/storage/Makefile b/firmware/sys/storage/Makefile index 4d5ee21c4..15e50590e 100644 --- a/firmware/sys/storage/Makefile +++ b/firmware/sys/storage/Makefile @@ -1,3 +1,6 @@ SRC = storage.c +SRC += storage_register.c +SRC += storage_internal.c + include $(RIOTBASE)/Makefile.base diff --git a/firmware/sys/storage/include/storage.h b/firmware/sys/storage/include/storage.h index 0ad22c528..86ed03f47 100644 --- a/firmware/sys/storage/include/storage.h +++ b/firmware/sys/storage/include/storage.h @@ -35,30 +35,6 @@ extern "C" { #endif -#define LAST_AVAILABLE_PAGE (FLASHPAGE_NUMOF - 1) /*!< Last position in the block EEPROM*/ -#define MAX_SIZE_STORAGE (4096) /*!< max size of mtd_storage, only writeable 4K */ -#define MAX_NUMOF_FLASHPAGES \ - (MAX_SIZE_STORAGE / FLASHPAGE_SIZE) /*!< max num of pages that can be manipulated */ - -#define MTD_START_ADDR \ - ((uint32_t)(flashpage_addr(LAST_AVAILABLE_PAGE)) - \ - MAX_SIZE_STORAGE) /*!< Reference to the first address writeable*/ -#define MTD_LAST_ADDR \ - (uint32_t)(flashpage_addr(LAST_AVAILABLE_PAGE)) /*!< Reference to the last address writeable*/ -#define MTD_REGISTER_INDEX_LIMIT (512) /*!< Reference to max number of bytes to add an register*/ - -typedef struct { - uint16_t size; - uint8_t key[25]; - uint8_t rwp; - uint32_t ptr_content; -} mtd_register_t; - -#define MTD_REG_IDX_NUMOF (MTD_REGISTER_INDEX_LIMIT / sizeof(mtd_register_t)) /*!< */ - -/** @note The storage EEPROM section page could be resize with the bootloader block size - * @warning Always the block EEPROM and BOOTLOADER are affected between them. - */ /** * @brief This function initializes all components needed to start and to save the data * @@ -87,48 +63,8 @@ int mtd_save(const void *value, uint32_t len, uint32_t offset); */ int mtd_load(void *value, uint16_t len, uint32_t offset); -/** - * @brief Saves data using a key as identifier to localize a group of bytes. - * - * @param [in] value Any type of value. - * @param [in] key Identifier to set/get a specified value. - * @param [in] len size of @p value that will be saved. - * @return int8_t - */ -int mtd_save_reg(const void *value, const uint8_t *key, uint16_t len); - -/** - * @brief Load data from mtd_storage localizating with its knew key and saves in @p value the data. - * - * @param [out] value Any type of value. - * @param [in] key Identifier to set/get a specified value. - * @param [in] len size of data that will be saved in @p value . - * - * @note @p size is used to check with the data saved in mtd_storage and won't be overflowed the @p - * value parameter. - * @return int8_t - */ -int mtd_load_reg(void *value, const uint8_t *key, uint16_t len); - -/** - * @brief Removes all saved data in mtd_storage. This will erase all until the - * last page since to available flash page to write eeprom. - * - * @warning The mtd storage needs to define a flashpage limit after base program - * memory allocation - * - * @retval 0 Erased data success - * @retval -1 Erased Fail. - */ int8_t mtd_erase_all(void); -/** - * @brief Check the available registers, to write/save data. - * - * @return int8_t - */ -int8_t mtd_available_idx(void); - /** * @brief Dump all data inside mtd storage * diff --git a/firmware/sys/storage/include/storage_internal.h b/firmware/sys/storage/include/storage_internal.h new file mode 100644 index 000000000..c3031a826 --- /dev/null +++ b/firmware/sys/storage/include/storage_internal.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2022 Mesh4all + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @ingroup storage_module + * @{ + * @file + * @brief This is the storage module where you can save data in the flash memory. + * This data should not be greater than 64 bytes. Data formats allowed are string + * and uint8. + * + * @author xkevin190 + * @author eduazocar + * + */ +#ifndef STORAGE_INTERNAL_H +#define STORAGE_INTERNAL_H + +#include "mtd_flashpage.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define LAST_AVAILABLE_PAGE (FLASHPAGE_NUMOF - 1) /*!< Last position in the block EEPROM*/ +#define MAX_SIZE_STORAGE (4096) /*!< max size of mtd_storage, only writeable 4K */ +#define MAX_NUMOF_FLASHPAGES \ + (MAX_SIZE_STORAGE / FLASHPAGE_SIZE) /*!< max num of pages that can be manipulated */ + +#define MTD_START_ADDR \ + ((uint32_t)(flashpage_addr(LAST_AVAILABLE_PAGE)) - \ + MAX_SIZE_STORAGE) /*!< Reference to the first address writeable*/ +#define MTD_LAST_ADDR \ + (uint32_t)(flashpage_addr(LAST_AVAILABLE_PAGE)) /*!< Reference to the last address writeable*/ + +/** + * @brief Saves any value in any position of mtd_storage. + * + * @param [in] value Any type of value. + * @param [in] len size of @p value that will be saved. + * @param [in] offset reference to an position in mtd_storage. + * @return int8_t + */ +int mtd_save(const void *value, uint32_t len, uint32_t offset); + +/** + * @brief Loads any value in any position of mtd_storage. + * + * @param [out] value Any type of value. + * @param [in] len size of @p value that will be loaded. + * @param [in] offset reference to an position in mtd_storage. + * @return int8_t + */ +int mtd_load(void *value, uint16_t len, uint32_t offset); + +#ifdef __cplusplus +} +#endif +#endif /* STORAGE_INTERNAL_H */ +/** @} */ diff --git a/firmware/sys/storage/include/storage_register.h b/firmware/sys/storage/include/storage_register.h new file mode 100644 index 000000000..243993a4e --- /dev/null +++ b/firmware/sys/storage/include/storage_register.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2022 Mesh4all + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @ingroup storage_module + * @{ + * @file + * @brief This is the storage module where you can save data in the flash memory by registers + * you can add an identifier o key to locate a specify data. + * + * @author eduazocar + * + */ +#ifndef STORAGE_REGISTER_H +#define STORAGE_REGISTER_H + +#include "mtd_flashpage.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MTD_REGISTER_INDEX_LIMIT (512) /*!< Reference to max number of bytes to add an register*/ +#define RWP_WRITE_BITMASK (0x80) /*!< Read/Write protection bit mask to set Writeable register*/ +#define RWP_READ_BITMASK (0x00) /*!< Read/Write protection bit mask to set only-read register*/ +typedef struct { + uint16_t size; + uint8_t key[25]; + uint8_t rwp; + uint32_t ptr_content; +} mtd_register_t; + +#define MTD_REG_IDX_NUMOF \ + (MTD_REGISTER_INDEX_LIMIT / \ + sizeof(mtd_register_t)) /*!< Max number of indexes that can be saved in the mtd storage */ + +/** + * @brief Saves data using a key as identifier to localize a group of bytes. + * + * @param [in] value Any type of value. + * @param [in] key Identifier to set/get a specified value. + * @param [in] len size of @p value that will be saved. + * @return int8_t + */ +int mtd_save_reg(const void *value, const uint8_t *key, uint16_t len); + +/** + * @brief Load data from mtd_storage localizating with its knew key and saves in @p value the data. + * + * @param [out] value Any type of value. + * @param [in] key Identifier to set/get a specified value. + * @param [in] len size of data that will be saved in @p value . + * + * @note @p size is used to check with the data saved in mtd_storage and won't be overflowed the @p + * value parameter. + * @return int8_t + */ +int mtd_load_reg(void *value, const uint8_t *key, uint16_t len); + +/** + * @brief Removes all saved data in mtd_storage. This will erase all until the + * last page since to available flash page to write eeprom. + * + * @warning The mtd storage needs to define a flashpage limit after base program + * memory allocation + * + * @retval 0 Erased data success + * @retval -1 Erased Fail. + */ +int8_t mtd_reg_del(uint8_t *key, uint16_t size); + +/** + * @brief + * + * @param[inout] idx First available index to write a register. + * @param[inout] count Number of available registers to write. + * @return int8_t + */ +int8_t mtd_available_idx(uint8_t *idx, uint8_t *count); + +/** + * @brief Removes all registers and set all their read/write protection bit, making that registers + * writeable + * + * @return int + */ +int mtd_clear_all_regs(void); + +#ifdef __cplusplus +} +#endif +#endif /* STORAGE_REGISTER_H */ +/** @} */ diff --git a/firmware/sys/storage/storage.c b/firmware/sys/storage/storage.c index c3a413897..cb752ef51 100644 --- a/firmware/sys/storage/storage.c +++ b/firmware/sys/storage/storage.c @@ -27,6 +27,8 @@ #include "mtd.h" #include "storage.h" +#include "storage_register.h" +#include "storage_internal.h" #if (CONFIG_DEBUG_STORAGE) || (DOXYGEN) /** @@ -42,10 +44,6 @@ static mtd_flashpage_t _dev = MTD_FLASHPAGE_INIT_VAL(8); static mtd_dev_t *dev = &_dev.base; -#define MTD_WR_BLOCK_POS(offset) ((offset - MTD_START_ADDR) / dev->write_size) -#define MTD_WR_NUMOF_BLOCK(size, offset) ((size) + (offset)) / (dev->write_size) -#define MTD_LAST_BLOCK_RES(size, offset) (offset) + (size) % (dev->write_size) - int8_t mtd_start(void) { int ret = mtd_init(dev); if (ret < 0) { @@ -54,188 +52,6 @@ int8_t mtd_start(void) { return ret; } -int mtd_write_block(const void *val, uint32_t addr, uint8_t size, uint8_t offset) { - uint8_t buf[dev->write_size]; - int8_t ret = 0; - ret = mtd_read(dev, buf, addr, sizeof(buf)); - if (ret < 0) { - DEBUG("Err: Reading a Block before overwrite it\n"); - return ret; - } - memcpy(buf + offset, val, size - offset); - ret = mtd_write(dev, buf, addr, dev->write_size); - if (ret < 0) { - DEBUG("Err: Writing in a block\n"); - return ret; - } - return 0; -} - -int mtd_read_block(void *value, uint32_t addr, uint8_t size, uint8_t offset) { - uint8_t buf[dev->write_size]; - int8_t ret = 0; - memset(buf, 0xFF, sizeof(buf)); - ret = mtd_read(dev, buf, addr, dev->write_size); - if (ret < 0) { - DEBUG("Err: Reading a Block\n"); - return ret; - } - memcpy(value, buf + offset, size - offset); - return 0; -} - -int mtd_save(const void *value, uint32_t len, uint32_t addr) { - uint8_t block_offset = addr % dev->write_size; - uint8_t last_size = MTD_LAST_BLOCK_RES(len, block_offset); - uint32_t storage_addr = MTD_START_ADDR + MTD_WR_BLOCK_POS(addr) * dev->write_size; - if (len + storage_addr >= MTD_LAST_ADDR) { - DEBUG("error: Overload Memory size, file: %s, line %d, function: %s\n", __FILE__, __LINE__, - __func__); - return -EOVERFLOW; - } - for (uint16_t i = 0; i <= MTD_WR_NUMOF_BLOCK(len, block_offset); i++) { - if (mtd_write_block(value, storage_addr, - i == MTD_WR_NUMOF_BLOCK(len, block_offset) ? last_size - : dev->write_size, - block_offset) < 0) { - DEBUG("error: Writing block, file: %s, line %d, function: %s\n", __FILE__, __LINE__, - __func__); - return -EOVERFLOW; - } - value = (uint8_t *)value + dev->write_size - block_offset; - block_offset = 0; - storage_addr += dev->write_size; - } - return 0; -} - -int mtd_load(void *value, uint16_t len, uint32_t addr) { - uint8_t block_offset = addr % dev->write_size; - uint8_t last_size = MTD_LAST_BLOCK_RES(len, block_offset); - uint32_t storage_addr = MTD_START_ADDR + MTD_WR_BLOCK_POS(addr) * dev->write_size; - - if (len + addr >= MTD_LAST_ADDR) { - DEBUG("error: Overload Memory size, file: %s, line %d, function: %s\n", __FILE__, __LINE__, - __func__); - return -EOVERFLOW; - } - for (uint16_t i = 0; i <= MTD_WR_NUMOF_BLOCK(len, block_offset); i++) { - if (mtd_read_block(value, storage_addr, - i == MTD_WR_NUMOF_BLOCK(len, block_offset) ? last_size : dev->write_size, - block_offset) < 0) { - DEBUG("Error: Reading in block, file: %s, line %d, function: %s\n", __FILE__, __LINE__, - __func__); - return -EOVERFLOW; - } - value = (uint8_t *)value + dev->write_size - block_offset; - block_offset = 0; - storage_addr += dev->write_size; - } - return 0; -} - -int8_t idx_reg_is_empty(mtd_register_t reg) { - uint8_t empty_reg[sizeof(mtd_register_t)]; - memset(empty_reg, FLASHPAGE_ERASE_STATE, sizeof(empty_reg)); - if (memcmp(®, empty_reg, sizeof(reg.size) + sizeof(reg.key)) == 0) { - return 0; - } - return -1; -} - -int8_t check_idx_reg(mtd_register_t reg, mtd_register_t buffer) { - if (memcmp(®, &buffer, sizeof(reg.size) + sizeof(reg.key)) == 0) { - return 0; - } - if (idx_reg_is_empty(reg) == 0) { - return 1; - } - return -1; -} - -int mtd_save_reg(const void *value, const uint8_t *key, uint16_t len) { - mtd_register_t buff, mtd_reg = {.size = len}; - memcpy(mtd_reg.key, key, sizeof(mtd_reg.key)); - uint8_t reg_count = 0; - mtd_reg.ptr_content = MTD_START_ADDR + MTD_REGISTER_INDEX_LIMIT; - while (reg_count < MTD_REG_IDX_NUMOF) { - int8_t ret = 0; - - int8_t reg_state = 0; - ret = mtd_load(&buff, sizeof(mtd_register_t), - MTD_START_ADDR + (reg_count * sizeof(mtd_register_t))); - if (ret < 0) { - DEBUG("Failed to pre-load indexes, file: %s, line %d, function: %s\n", __FILE__, - __LINE__, __func__); - return ret; - } - if (buff.size != 0xffff) { - mtd_reg.ptr_content += buff.size; - } - reg_state = check_idx_reg(buff, mtd_reg); - if (reg_state == 0) { - DEBUG("The index already exist, can´t be updated, file: %s, line %d, function: %s\n", - __FILE__, __LINE__, __func__); - return 1; - } - if (reg_state == 1) { - DEBUG("Empty_register\n"); - ret = mtd_save(&mtd_reg, sizeof(mtd_register_t), - MTD_START_ADDR + (reg_count * sizeof(mtd_register_t))); - if (ret < 0) { - DEBUG("Failed Saving mtd register index, file: %s, line %d, function: %s\n", - __FILE__, __LINE__, __func__); - return ret; - } - ret = mtd_save(value, len, mtd_reg.ptr_content); - if (ret < 0) { - DEBUG("Failed Saving mtd register content, file: %s, line %d, function: %s\n", - __FILE__, __LINE__, __func__); - return ret; - } - return 0; - } - reg_count++; - } - return -1; -} - -int mtd_load_reg(void *value, const uint8_t *key, uint16_t len) { - mtd_register_t buff, mtd_reg = {.size = len}; - memcpy(mtd_reg.key, key, sizeof(mtd_reg.key)); - uint8_t reg_count = 0; - while (reg_count < MTD_REG_IDX_NUMOF) { - int8_t ret = 0; - int8_t reg_state = 0; - ret = mtd_load(&buff, sizeof(mtd_register_t), - reg_count * sizeof(mtd_register_t) + MTD_START_ADDR); - if (ret < 0) { - DEBUG("Err: Failed Reading Registers, file: %s, line %d, function: %s\n", __FILE__, - __LINE__, __func__); - return ret; - } - - reg_state = check_idx_reg(buff, mtd_reg); - if (reg_state == 0) { - DEBUG("Reading content of an register\n"); - ret = mtd_load(&mtd_reg, sizeof(mtd_register_t), - reg_count * sizeof(mtd_register_t) + MTD_START_ADDR); - if (ret < 0) { - return ret; - } - - uint8_t out[mtd_reg.size]; - if (mtd_load(out, mtd_reg.size, mtd_reg.ptr_content) < 0) { - return -1; - } - memcpy(value, out, len); - return 0; - } - reg_count++; - } - return -1; -} - int mtd_put_u8(const uint8_t value, const uint8_t *key) { return mtd_save_reg(&value, key, sizeof(uint8_t)); } @@ -292,27 +108,6 @@ int mtd_get_str(char *value, const uint8_t *key, uint8_t len) { return mtd_load_reg(value, key, len); } -int8_t mtd_available_idx(void) { - mtd_register_t buff; - uint8_t available_reg = 0; - - for (size_t i = 0; i < MTD_REG_IDX_NUMOF; i++) { - uint32_t idx_storage = MTD_START_ADDR + i * sizeof(mtd_register_t); - mtd_load(&buff, sizeof(buff), idx_storage); - if (idx_reg_is_empty(buff) == 0) { - DEBUG("Available index: 0x%" PRIX32 "\n", idx_storage); - available_reg++; - } - } - if (available_reg == 0) { - DEBUG("It's not available register for write\n"); - return -1; - } - - DEBUG("Number of available registers: %u\n\n", available_reg); - return 0; -} - int8_t mtd_erase_all(void) { uint32_t addr = MTD_START_ADDR; if (mtd_erase(dev, addr, MAX_SIZE_STORAGE) < 0) { @@ -320,24 +115,3 @@ int8_t mtd_erase_all(void) { } return 0; } - -int8_t mtd_dump(void) { - uint8_t value[dev->write_size]; - uint32_t addr = MTD_START_ADDR; - uint32_t erased_data = 0; - for (uint32_t i = 0; i < MAX_SIZE_STORAGE / dev->write_size; i++) { - mtd_read_block(value, addr, dev->write_size, 0); - for (uint8_t j = 0; j < dev->write_size; j++) { - DEBUG("%02X ", value[j]); - if ((value[j] == 255) || (value[j] == 0)) { - erased_data++; - } - } - DEBUG("\n"); - addr += dev->write_size; - } - if (erased_data == MAX_SIZE_STORAGE) { - return -1; - } - return 0; -} diff --git a/firmware/sys/storage/storage_internal.c b/firmware/sys/storage/storage_internal.c new file mode 100644 index 000000000..47e2f41cc --- /dev/null +++ b/firmware/sys/storage/storage_internal.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2022 Mesh4all + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @brief storage file + * + * @author xkevin190 + * @author eduazocar + */ +#include +#include +#include "errno.h" + +#include "mtd.h" +#include "storage_internal.h" + + +#if (CONFIG_DEBUG_STORAGE) || (DOXYGEN) +/** + * @brief KCONFIG_PARAMETER TO SET DEBUG MODE + * + */ +#define ENABLE_DEBUG CONFIG_DEBUG_STORAGE +#else +#define ENABLE_DEBUG 0 +#endif +#include "debug.h" + +static mtd_flashpage_t _dev = MTD_FLASHPAGE_INIT_VAL(8); +static mtd_dev_t *dev = &_dev.base; + +#define MTD_WR_BLOCK_POS(offset) ((offset - MTD_START_ADDR) / dev->write_size) +#define MTD_WR_NUMOF_BLOCK(size, offset) ((size) + (offset)) / (dev->write_size) +#define MTD_LAST_BLOCK_RES(size, offset) (offset) + (size) % (dev->write_size) + +int mtd_write_block(const void *val, uint32_t addr, uint8_t size, uint8_t offset) { + uint8_t buf[dev->write_size]; + int8_t ret = 0; + ret = mtd_read(dev, buf, addr, dev->write_size); + if (ret < 0) { + DEBUG("Err: Reading a Block before overwrite it\n"); + return ret; + } + memcpy(buf + offset, val, size - offset); + ret = mtd_write(dev, buf, addr, dev->write_size); + if (ret < 0) { + DEBUG("Err: Writing in a block\n"); + return ret; + } + return 0; +} + +int mtd_read_block(void *value, uint32_t addr, uint8_t size, uint8_t offset) { + uint8_t buf[dev->write_size]; + int8_t ret = 0; + memset(buf, 0xFF, sizeof(buf)); + ret = mtd_read(dev, buf, addr, dev->write_size); + if (ret < 0) { + DEBUG("Err: Reading a Block\n"); + return ret; + } + memcpy(value, buf + offset, size - offset); + return 0; +} + +int mtd_save(const void *value, uint32_t len, uint32_t addr) { + uint8_t block_offset = addr % dev->write_size; + uint8_t last_size = MTD_LAST_BLOCK_RES(len, block_offset); + uint32_t storage_addr = MTD_START_ADDR + MTD_WR_BLOCK_POS(addr) * dev->write_size; + if (len + storage_addr >= MTD_LAST_ADDR) { + DEBUG("error: Overload Memory size, file: %s, line %d, function: %s\n", __FILE__, __LINE__, + __func__); + return -EOVERFLOW; + } + for (uint16_t i = 0; i <= MTD_WR_NUMOF_BLOCK(len, block_offset); i++) { + if (mtd_write_block(value, storage_addr, + i == MTD_WR_NUMOF_BLOCK(len, block_offset) ? last_size + : dev->write_size, + block_offset) < 0) { + DEBUG("error: Writing block, file: %s, line %d, function: %s\n", __FILE__, __LINE__, + __func__); + return -EOVERFLOW; + } + value = (uint8_t *)value + dev->write_size - block_offset; + block_offset = 0; + storage_addr += dev->write_size; + } + return 0; +} + +int mtd_load(void *value, uint16_t len, uint32_t addr) { + uint8_t block_offset = addr % dev->write_size; + uint8_t last_size = MTD_LAST_BLOCK_RES(len, block_offset); + uint32_t storage_addr = MTD_START_ADDR + MTD_WR_BLOCK_POS(addr) * dev->write_size; + + if (len + addr >= MTD_LAST_ADDR) { + DEBUG("error: Overload Memory size, file: %s, line %d, function: %s\n", __FILE__, __LINE__, + __func__); + return -EOVERFLOW; + } + for (uint16_t i = 0; i <= MTD_WR_NUMOF_BLOCK(len, block_offset); i++) { + if (mtd_read_block(value, storage_addr, + i == MTD_WR_NUMOF_BLOCK(len, block_offset) ? last_size : dev->write_size, + block_offset) < 0) { + DEBUG("Error: Reading in block, file: %s, line %d, function: %s\n", __FILE__, __LINE__, + __func__); + return -EOVERFLOW; + } + value = (uint8_t *)value + dev->write_size - block_offset; + block_offset = 0; + storage_addr += dev->write_size; + } + return 0; +} + +int8_t mtd_dump(void) { + uint8_t value[dev->write_size]; + uint32_t addr = MTD_START_ADDR; + uint32_t erased_data = 0; + for (uint32_t i = 0; i < MAX_SIZE_STORAGE / dev->write_size; i++) { + printf("0x%" PRIX32 " : ", addr); + mtd_read_block(value, addr, dev->write_size, 0); + for (uint8_t j = 0; j < dev->write_size; j++) { + DEBUG("%02X ", value[j]); + if ((value[j] == 255) || (value[j] == 0)) { + erased_data++; + } + } + DEBUG("\n"); + addr += dev->write_size; + } + if (erased_data == MAX_SIZE_STORAGE) { + return -1; + } + return 0; +} \ No newline at end of file diff --git a/firmware/sys/storage/storage_register.c b/firmware/sys/storage/storage_register.c new file mode 100644 index 000000000..9452dbbf4 --- /dev/null +++ b/firmware/sys/storage/storage_register.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2022 Mesh4all + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @brief Storage registers file + * + * @author eduazocar + */ +#include +#include +#include +#include "errno.h" + +#include "storage.h" +#include "storage_register.h" +#include "storage_internal.h" + +#if (CONFIG_DEBUG_STORAGE) || (DOXYGEN) +/** + * @brief KCONFIG_PARAMETER TO SET DEBUG MODE + * + */ +#define ENABLE_DEBUG CONFIG_DEBUG_STORAGE +#else +#define ENABLE_DEBUG 0 +#endif +#include "debug.h" + +int8_t idx_reg_is_empty(mtd_register_t reg) { + uint8_t empty_reg[sizeof(mtd_register_t)]; + memset(empty_reg, FLASHPAGE_ERASE_STATE, sizeof(empty_reg)); + if (memcmp(®, empty_reg, sizeof(reg.size) + sizeof(reg.key)) == 0) { + return 0; + } + return -1; +} + +int8_t check_idx_reg(mtd_register_t reg, mtd_register_t buffer) { + if (memcmp(®, &buffer, sizeof(reg.size) + sizeof(reg.key)) == 0) { + return 0; + } + if (idx_reg_is_empty(reg) == 0) { + return 1; + } + return -1; +} + +int mtd_clear_all_regs(void) { + mtd_register_t reg; + memset(®, 0xFF, sizeof(reg)); + reg.rwp &= RWP_WRITE_BITMASK; + mtd_erase_all(); + uint32_t addr = MTD_START_ADDR + sizeof(reg.size) + sizeof(reg.key); + for (size_t i = 0; i < MTD_REG_IDX_NUMOF; i++) { + if (mtd_save(®.rwp, sizeof(reg.rwp), addr) < 0) { + DEBUG("Error dEL REGS\n"); + return -1; + } + addr += sizeof(mtd_register_t); + } + return 0; +} + +int mtd_save_reg(const void *value, const uint8_t *key, uint16_t len) { + mtd_register_t buff, mtd_reg = {.size = len}; + memcpy(mtd_reg.key, key, sizeof(mtd_reg.key)); + mtd_reg.rwp = 0xFF & RWP_READ_BITMASK; + uint8_t reg_count = 0; + mtd_reg.ptr_content = MTD_START_ADDR + MTD_REGISTER_INDEX_LIMIT; + while (reg_count < MTD_REG_IDX_NUMOF) { + int8_t ret = 0; + + int8_t reg_state = 0; + ret = mtd_load(&buff, sizeof(mtd_register_t), + MTD_START_ADDR + (reg_count * sizeof(mtd_register_t))); + if (ret < 0) { + DEBUG("Failed to pre-load indexes, file: %s, line %d, function: %s\n", __FILE__, + __LINE__, __func__); + return ret; + } + if (buff.size != 0xffff) { + mtd_reg.ptr_content += buff.size; + } + reg_state = check_idx_reg(buff, mtd_reg); + if (reg_state == 0) { + DEBUG("The index already exist, can´t be updated, file: %s, line %d, function: %s\n", + __FILE__, __LINE__, __func__); + return 1; + } + if (reg_state == 1) { + DEBUG("Empty_register\n"); + ret = mtd_save(&mtd_reg, sizeof(mtd_register_t), + MTD_START_ADDR + (reg_count * sizeof(mtd_register_t))); + if (ret < 0) { + DEBUG("Failed Saving mtd register index, file: %s, line %d, function: %s\n", + __FILE__, __LINE__, __func__); + return ret; + } + ret = mtd_save(value, len, mtd_reg.ptr_content); + if (ret < 0) { + DEBUG("Failed Saving mtd register content, file: %s, line %d, function: %s\n", + __FILE__, __LINE__, __func__); + return ret; + } + return 0; + } + reg_count++; + } + return -1; +} + +int mtd_load_reg(void *value, const uint8_t *key, uint16_t len) { + mtd_register_t buff, mtd_reg = {.size = len}; + memcpy(mtd_reg.key, key, sizeof(mtd_reg.key)); + uint8_t reg_count = 0; + while (reg_count < MTD_REG_IDX_NUMOF) { + int8_t ret = 0; + int8_t reg_state = 0; + ret = mtd_load(&buff, sizeof(mtd_register_t), + reg_count * sizeof(mtd_register_t) + MTD_START_ADDR); + if (ret < 0) { + DEBUG("Err: Failed Reading Registers, file: %s, line %d, function: %s\n", __FILE__, + __LINE__, __func__); + return ret; + } + + reg_state = check_idx_reg(buff, mtd_reg); + if (reg_state == 0) { + DEBUG("Reading content of an register\n"); + ret = mtd_load(&mtd_reg, sizeof(mtd_register_t), + reg_count * sizeof(mtd_register_t) + MTD_START_ADDR); + if (ret < 0) { + return ret; + } + + uint8_t out[mtd_reg.size]; + if (mtd_load(out, mtd_reg.size, mtd_reg.ptr_content) < 0) { + return -1; + } + memcpy(value, out, len); + return 0; + } + reg_count++; + } + return -1; +} + +int8_t mtd_available_idx(uint8_t *idx, uint8_t *count) { + (void)idx; + mtd_register_t buff; + *count = 0; + + for (size_t i = 0; i < MTD_REG_IDX_NUMOF; i++) { + uint32_t idx_storage = MTD_START_ADDR + i * sizeof(mtd_register_t); + mtd_load(&buff, sizeof(buff), idx_storage); + if (idx_reg_is_empty(buff) == 0) { + DEBUG("Available index: 0x%" PRIX32 "\n", idx_storage); + if (*count != 0) { + *idx = idx_storage; + } + *count += 1; + } + } + if (*count == 0) { + DEBUG("It's not available register for write\n"); + return -1; + } + return 0; +} + +int8_t mtd_reg_del(uint8_t *key, uint16_t size) { + mtd_register_t regs[MTD_REG_IDX_NUMOF], reg = {.size = size}; + memcpy(reg.key, key, sizeof(reg.key)); + uint8_t *content[MTD_REG_IDX_NUMOF]; + uint8_t j = 0; + for (size_t i = 0; i < MTD_REG_IDX_NUMOF; i++) { + int8_t reg_st = 0; + uint32_t idx_storage = MTD_START_ADDR + i * sizeof(mtd_register_t); + mtd_load(®s[i - j], sizeof(mtd_register_t), idx_storage); + reg_st = check_idx_reg(regs[i - j], reg); + if (reg_st == 0) { + j++; + } else if (reg_st == -1) { + content[i - j] = malloc(regs[i - j].size); + mtd_load(content[i - j], regs[i - j].size, regs[i - j].ptr_content); + printf("\n"); + } + } + mtd_clear_all_regs(); + for (size_t i = 0; i < MTD_REG_IDX_NUMOF; i++) { + if (idx_reg_is_empty(regs[i]) < 0) { + mtd_save_reg(content[i], regs[i].key, regs[i].size); + free(content[i]); + } else { + break; + } + } + return 0; +} diff --git a/tests/system_storage/main.c b/tests/system_storage/main.c index eb1ee7959..ac75addbb 100644 --- a/tests/system_storage/main.c +++ b/tests/system_storage/main.c @@ -27,6 +27,9 @@ #include "embUnit.h" #include "storage.h" +#include "storage_register.h" +#include "storage_internal.h" + #include "mtd.h" #if (CONFIG_DEBUG_TEST_STORAGE) || (DOXYGEN) @@ -63,6 +66,7 @@ void test_save_data(void) { .var3 = {1550, 5544, -698, -789, -97852, [19] = -25, [48] = 39, [49] = 2556}}; printf("\nSaving data:\n"); ret = mtd_save(&test_save, sizeof(test_save), MTD_START_ADDR); + mtd_dump(); if (ret < 0) { DEBUG("Failed Saving data\n"); } @@ -106,8 +110,8 @@ void test_load_pointed(void) { } void test_saving_reg(void) { + mtd_clear_all_regs(); int ret = 0; - mtd_erase_all(); char str[28] = {"Everyone in the mesh!!!"}; char str2[20] = {"Contributor: CW"}; uint8_t age = 24; @@ -116,7 +120,7 @@ void test_saving_reg(void) { int8_t i8val = -123; int16_t i16val = -3258; int32_t i32val = -9000; - + uint8_t index, numreg; ret = mtd_put_str(str, (uint8_t *)"KEY0", sizeof(str)); if (ret < 0) { DEBUG("Failed Saving data"); @@ -150,7 +154,7 @@ void test_saving_reg(void) { if (ret < 0) { DEBUG("Failed Saving data\n"); } - mtd_available_idx(); + mtd_available_idx(&index, &numreg); TEST_ASSERT_EQUAL_INT(0, ret); mtd_dump(); } @@ -194,7 +198,7 @@ void test_loading_reg(void) { DEBUG("Failed Loading data"); } ret = mtd_get_i32(&i32val, (uint8_t *)"KEY7"); - + mtd_reg_del((uint8_t*)"KEY2", sizeof(uint8_t)); printf("string#1 loaded: %s\n", str); printf("string#2 loaded: %s\n", str2); printf("uint8_t loaded: %d\n", age); @@ -203,6 +207,7 @@ void test_loading_reg(void) { printf("int8_t loaded: %d\n", i8val); printf("int16_t loaded: %" PRId16 " \n", i16val); printf("int32_t loaded: %" PRId32 " \n", i32val); + mtd_dump(); TEST_ASSERT_EQUAL_INT(0, ret); }