From 5d6ed3dd7143746eaeb447b8c3b643dbca97de6c Mon Sep 17 00:00:00 2001 From: Joseph Newman Date: Mon, 3 Jun 2019 16:24:49 +0100 Subject: [PATCH] [settings] add option to store settings in volatile storage (#3811) --- examples/common-switches.mk | 5 + examples/platforms/qpg6095/Makefile.am | 2 + examples/platforms/qpg6095/settings.cpp | 22 +-- examples/platforms/utils/Makefile.am | 1 + examples/platforms/utils/settings_flash.c | 4 + examples/platforms/utils/settings_ram.c | 229 ++++++++++++++++++++++ include/openthread/platform/settings.h | 4 + 7 files changed, 249 insertions(+), 18 deletions(-) create mode 100644 examples/platforms/utils/settings_ram.c diff --git a/examples/common-switches.mk b/examples/common-switches.mk index 6d2d635ad..5d4d68e2b 100644 --- a/examples/common-switches.mk +++ b/examples/common-switches.mk @@ -53,6 +53,7 @@ MAC_FILTER ?= 0 MTD_NETDIAG ?= 0 PLATFORM_UDP ?= 0 SERVICE ?= 0 +SETTINGS_RAM ?= 0 # SLAAC is enabled by default SLAAC ?= 1 SNTP_CLIENT ?= 0 @@ -195,6 +196,10 @@ CFLAGS += -DOPENTHREAD_CONFIG_LOG_OUTPUT=OPENTHREAD_CONFIG_LOG_OUTPUT_DEBUG_UA CXXFLAGS += -DOPENTHREAD_CONFIG_LOG_OUTPUT=OPENTHREAD_CONFIG_LOG_OUTPUT_DEBUG_UART endif +ifeq ($(SETTINGS_RAM),1) +COMMONCFLAGS += -DOPENTHREAD_SETTINGS_RAM=1 +endif + ifeq ($(FULL_LOGS),1) # HINT: Add more here, or comment out ones you do not need/want LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_LEVEL=OT_LOG_LEVEL_DEBG diff --git a/examples/platforms/qpg6095/Makefile.am b/examples/platforms/qpg6095/Makefile.am index b15e46c80..2b8835e72 100644 --- a/examples/platforms/qpg6095/Makefile.am +++ b/examples/platforms/qpg6095/Makefile.am @@ -52,6 +52,8 @@ libopenthread_qpg6095_a_SOURCES = \ uart.c \ $(NULL) +libopenthread_qpg6095_a_LIBADD = \ + $(top_builddir)/examples/platforms/utils/libopenthread_platform_utils_a-settings_ram.o if OPENTHREAD_ENABLE_DIAG libopenthread_qpg6095_a_SOURCES += \ diff --git a/examples/platforms/qpg6095/settings.cpp b/examples/platforms/qpg6095/settings.cpp index 88a0754c7..1cc6ba559 100644 --- a/examples/platforms/qpg6095/settings.cpp +++ b/examples/platforms/qpg6095/settings.cpp @@ -42,6 +42,8 @@ #include "settings_qorvo.h" +#if !OPENTHREAD_SETTINGS_RAM + /***************************************************************************** * Public Function Definitions *****************************************************************************/ @@ -53,24 +55,6 @@ void otPlatSettingsInit(otInstance *aInstance) qorvoSettingsInit(); } -otError otPlatSettingsBeginChange(otInstance *aInstance) -{ - OT_UNUSED_VARIABLE(aInstance); - return OT_ERROR_NONE; -} - -otError otPlatSettingsCommitChange(otInstance *aInstance) -{ - OT_UNUSED_VARIABLE(aInstance); - return OT_ERROR_NONE; -} - -otError otPlatSettingsAbandonChange(otInstance *aInstance) -{ - OT_UNUSED_VARIABLE(aInstance); - return OT_ERROR_NONE; -} - otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength) { otError error = OT_ERROR_NOT_FOUND; @@ -136,3 +120,5 @@ void otPlatSettingsWipe(otInstance *aInstance) qorvoSettingsWipe(); otPlatSettingsInit(aInstance); } + +#endif /* OPENTHREAD_SETTINGS_RAM */ diff --git a/examples/platforms/utils/Makefile.am b/examples/platforms/utils/Makefile.am index 74bac9565..40cd14027 100644 --- a/examples/platforms/utils/Makefile.am +++ b/examples/platforms/utils/Makefile.am @@ -40,6 +40,7 @@ libopenthread_platform_utils_a_CPPFLAGS = \ libopenthread_platform_utils_a_SOURCES = \ debug_uart.c \ logging_rtt.c \ + settings_ram.c \ settings_flash.c \ soft_source_match_table.c \ $(NULL) diff --git a/examples/platforms/utils/settings_flash.c b/examples/platforms/utils/settings_flash.c index 7131b9295..4ea5f3b73 100644 --- a/examples/platforms/utils/settings_flash.c +++ b/examples/platforms/utils/settings_flash.c @@ -101,6 +101,8 @@ struct settingsBlock #error "Invalid value for `SETTINGS_CONFIG_PAGE_NUM` (should be >= 2)" #endif +#if !OPENTHREAD_SETTINGS_RAM + static uint32_t sSettingsBaseAddress; static uint32_t sSettingsUsedSize; @@ -446,3 +448,5 @@ void otPlatSettingsWipe(otInstance *aInstance) initSettings(sSettingsBaseAddress, (uint32_t)OT_SETTINGS_IN_USE); otPlatSettingsInit(aInstance); } + +#endif /* OPENTHREAD_SETTINGS_RAM */ diff --git a/examples/platforms/utils/settings_ram.c b/examples/platforms/utils/settings_ram.c new file mode 100644 index 000000000..ed4d8213a --- /dev/null +++ b/examples/platforms/utils/settings_ram.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2019, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements OpenThread platform abstraction for storage of settings in RAM. + * + */ + +#include + +#include +#include +#include +#include + +#include +#include + +#define SETTINGS_BUFFER_SIZE 1024 + +#if OPENTHREAD_SETTINGS_RAM + +static uint8_t sSettingsBuf[SETTINGS_BUFFER_SIZE]; +static uint16_t sSettingsBufLength; + +struct settingsBlock +{ + uint16_t key; + uint16_t length; +}; + +// settings API +void otPlatSettingsInit(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + + sSettingsBufLength = 0; +} + +otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength) +{ + OT_UNUSED_VARIABLE(aInstance); + + uint16_t i = 0; + uint16_t valueLength = 0; + uint16_t readLength; + int currentIndex = 0; + const struct settingsBlock *currentBlock; + otError error = OT_ERROR_NOT_FOUND; + + while (i < sSettingsBufLength) + { + currentBlock = (struct settingsBlock *)&sSettingsBuf[i]; + + if (aKey == currentBlock->key) + { + if (currentIndex == aIndex) + { + readLength = currentBlock->length; + + // Perform read only if an input buffer was passed in + if (aValue != NULL && aValueLength != NULL) + { + // Adjust read length if input buffer size is smaller + if (readLength > *aValueLength) + { + readLength = *aValueLength; + } + + memcpy(aValue, &sSettingsBuf[i + sizeof(struct settingsBlock)], readLength); + } + + valueLength = currentBlock->length; + error = OT_ERROR_NONE; + break; + } + + currentIndex++; + } + + i += sizeof(struct settingsBlock) + currentBlock->length; + } + + if (aValueLength != NULL) + { + *aValueLength = valueLength; + } + + return error; +} + +otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength) +{ + uint16_t i = 0; + uint16_t currentBlockLength; + uint16_t nextBlockStart; + const struct settingsBlock *currentBlock; + + // Delete all entries of aKey + while (i < sSettingsBufLength) + { + currentBlock = (struct settingsBlock *)&sSettingsBuf[i]; + currentBlockLength = sizeof(struct settingsBlock) + currentBlock->length; + + if (aKey == currentBlock->key) + { + nextBlockStart = i + currentBlockLength; + + if (nextBlockStart < sSettingsBufLength) + { + memmove(&sSettingsBuf[i], &sSettingsBuf[nextBlockStart], sSettingsBufLength - nextBlockStart); + } + + assert(sSettingsBufLength >= currentBlockLength); + sSettingsBufLength -= currentBlockLength; + } + else + { + i += currentBlockLength; + } + } + + return otPlatSettingsAdd(aInstance, aKey, aValue, aValueLength); +} + +otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength) +{ + OT_UNUSED_VARIABLE(aInstance); + + otError error; + struct settingsBlock *currentBlock; + const uint16_t newBlockLength = sizeof(struct settingsBlock) + aValueLength; + + if (sSettingsBufLength + newBlockLength <= sizeof(sSettingsBuf)) + { + currentBlock = (struct settingsBlock *)&sSettingsBuf[sSettingsBufLength]; + currentBlock->key = aKey; + currentBlock->length = aValueLength; + + memcpy(&sSettingsBuf[sSettingsBufLength + sizeof(struct settingsBlock)], aValue, aValueLength); + sSettingsBufLength += newBlockLength; + + error = OT_ERROR_NONE; + } + else + { + error = OT_ERROR_NO_BUFS; + } + + return error; +} + +otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex) +{ + OT_UNUSED_VARIABLE(aInstance); + + uint16_t i = 0; + int currentIndex = 0; + uint16_t nextBlockStart; + uint16_t currentBlockLength; + const struct settingsBlock *currentBlock; + otError error = OT_ERROR_NOT_FOUND; + + while (i < sSettingsBufLength) + { + currentBlock = (struct settingsBlock *)&sSettingsBuf[i]; + currentBlockLength = sizeof(struct settingsBlock) + currentBlock->length; + + if (aKey == currentBlock->key) + { + if (currentIndex == aIndex) + { + nextBlockStart = i + currentBlockLength; + + if (nextBlockStart < sSettingsBufLength) + { + memmove(&sSettingsBuf[i], &sSettingsBuf[nextBlockStart], sSettingsBufLength - nextBlockStart); + } + + assert(sSettingsBufLength >= currentBlockLength); + sSettingsBufLength -= currentBlockLength; + + error = OT_ERROR_NONE; + break; + } + else + { + currentIndex++; + } + } + + i += currentBlockLength; + } + + return error; +} + +void otPlatSettingsWipe(otInstance *aInstance) +{ + otPlatSettingsInit(aInstance); +} + +#endif // OPENTHREAD_SETTINGS_RAM diff --git a/include/openthread/platform/settings.h b/include/openthread/platform/settings.h index 2aa8027d2..115cc67a9 100644 --- a/include/openthread/platform/settings.h +++ b/include/openthread/platform/settings.h @@ -130,6 +130,8 @@ otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint * The given setting was changed or staged. * @retval OT_ERROR_NOT_IMPLEMENTED * This function is not implemented on this platform. + * @retval OT_ERROR_NO_BUFS + * No space remaining to store the given setting. */ otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength); @@ -163,6 +165,8 @@ otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *a * The given setting was added or staged to be added. * @retval OT_ERROR_NOT_IMPLEMENTED * This function is not implemented on this platform. + * @retval OT_ERROR_NO_BUFS + * No space remaining to store the given setting. */ otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);