From 2e1ebe8c10473839ddb39ac7c61d32f1802240b0 Mon Sep 17 00:00:00 2001 From: Marius Preda Date: Thu, 24 Mar 2022 16:16:22 +0200 Subject: [PATCH] [MATTER-125] Move K32W0 PDM writes to the idle task Updated the Matter NVM implementation to use PDM save on idle to reduce commissioning time. Changed the Matter Config implementation to use a ram buffer as storage for all Key elements stored as TLV elements. The buffer is then saved in NVM memory and restored to ram at boot time. This ram buffer is dynamically allocated from the FreeRtos heap and has support for reallocation in case the size is too small. --- .../nxp/k32w/k32w0/main/AppTask.cpp | 52 +-- .../k32w/k32w0/app/support/FreeRtosHooks.c | 23 +- src/platform/nxp/k32w/k32w0/BUILD.gn | 2 + src/platform/nxp/k32w/k32w0/K32W0Config.cpp | 406 ++++++++---------- src/platform/nxp/k32w/k32w0/K32W0Config.h | 4 +- .../k32w/k32w0/KeyValueStoreManagerImpl.cpp | 233 ++++------ src/platform/nxp/k32w/k32w0/ram_storage.c | 211 +++++++++ src/platform/nxp/k32w/k32w0/ram_storage.h | 60 +++ 8 files changed, 580 insertions(+), 411 deletions(-) create mode 100644 src/platform/nxp/k32w/k32w0/ram_storage.c create mode 100644 src/platform/nxp/k32w/k32w0/ram_storage.h diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp b/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp index d94aafea5ac791..0c9b8e96b1a120 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp +++ b/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp @@ -507,7 +507,7 @@ void AppTask::OTAHandler(AppEvent * aEvent) #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR void AppTask::StartOTAQuery(intptr_t arg) { - static_cast(GetRequestorInstance())->TriggerImmediateQuery(); + static_cast(GetRequestorInstance())->TriggerImmediateQuery(); } #endif @@ -543,19 +543,19 @@ void AppTask::BleHandler(AppEvent * aEvent) } #if CONFIG_CHIP_NFC_COMMISSIONING -void AppTask::ThreadProvisioningHandler(const ChipDeviceEvent * event, intptr_t) -{ - if (event->Type == DeviceEventType::kServiceProvisioningChange && event->ServiceProvisioningChange.IsServiceProvisioned) - { - if (event->ServiceProvisioningChange.IsServiceProvisioned) - { - sIsThreadProvisioned = TRUE; - } - else - { - sIsThreadProvisioned = FALSE; - } - } + void AppTask::ThreadProvisioningHandler(const ChipDeviceEvent * event, intptr_t) + { + if (event->Type == DeviceEventType::kServiceProvisioningChange && event->ServiceProvisioningChange.IsServiceProvisioned) + { + if (event->ServiceProvisioningChange.IsServiceProvisioned) + { + sIsThreadProvisioned = TRUE; + } + else + { + sIsThreadProvisioned = FALSE; + } + } if (event->Type == DeviceEventType::kCHIPoBLEAdvertisingChange && event->CHIPoBLEAdvertisingChange.Result == kActivity_Stopped) { @@ -689,18 +689,6 @@ void AppTask::OTAResumeEventHandler(AppEvent * aEvent) } } -extern "C" void vApplicationIdleHook( void ) -{ -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - OTA_TransactionResume(); - - if (shouldReset) - { - ResetMCU(); - } -#endif -} - void AppTask::PostEvent(const AppEvent * aEvent) { if (sAppEventQueue != NULL) @@ -744,12 +732,12 @@ void AppTask::UpdateClusterStateInternal(intptr_t arg) void AppTask::UpdateDeviceState(void) { - bool onoffAttrValue = 0; + bool onoffAttrValue = 0; - /* get onoff attribute value */ - (void)emberAfReadAttribute(1, ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, - (uint8_t *) &onoffAttrValue, 1, NULL); + /* get onoff attribute value */ + (void)emberAfReadAttribute(1, ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, + (uint8_t *) &onoffAttrValue, 1, NULL); - /* set the device state */ - sLightLED.Set(onoffAttrValue); + /* set the device state */ + sLightLED.Set(onoffAttrValue); } diff --git a/examples/platform/nxp/k32w/k32w0/app/support/FreeRtosHooks.c b/examples/platform/nxp/k32w/k32w0/app/support/FreeRtosHooks.c index 0884a8f261f226..49086acc400c46 100644 --- a/examples/platform/nxp/k32w/k32w0/app/support/FreeRtosHooks.c +++ b/examples/platform/nxp/k32w/k32w0/app/support/FreeRtosHooks.c @@ -30,6 +30,7 @@ #include "PWR_Interface.h" #include "TimersManager.h" #include "board.h" +#include "PDM.h" /* Bluetooth Low Energy */ #include "ble_config.h" @@ -52,6 +53,10 @@ #define APP_DBG_LOG(...) #endif +#define PDM_MAX_WRITES_INFINITE 0xFF + +extern bool shouldReset; + static inline void mutex_init(mbedtls_threading_mutex_t * p_mutex) { assert(p_mutex != NULL); @@ -218,6 +223,8 @@ void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime) OSA_InterruptEnable(); } +#endif /* (cPWR_UsePowerDownMode) && (configUSE_TICKLESS_IDLE != 0) */ + static void BOARD_ActionOnIdle(void) { #if ((defined gTcxo32k_ModeEn_c) && (gTcxo32k_ModeEn_c != 0)) @@ -230,7 +237,17 @@ static void BOARD_ActionOnIdle(void) void vApplicationIdleHook(void) { - BOARD_ActionOnIdle(); -} + PDM_vIdleTask(PDM_MAX_WRITES_INFINITE); -#endif /* (cPWR_UsePowerDownMode) && (configUSE_TICKLESS_IDLE != 0) */ +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + OTA_TransactionResume(); + + if (shouldReset) + { + ResetMCU(); + } +#endif + + + BOARD_ActionOnIdle(); +} \ No newline at end of file diff --git a/src/platform/nxp/k32w/k32w0/BUILD.gn b/src/platform/nxp/k32w/k32w0/BUILD.gn index eb3e52b0becaf0..074d737c4c27a8 100644 --- a/src/platform/nxp/k32w/k32w0/BUILD.gn +++ b/src/platform/nxp/k32w/k32w0/BUILD.gn @@ -40,6 +40,8 @@ static_library("k32w0") { "DiagnosticDataProviderImpl.h", "K32W0Config.cpp", "K32W0Config.h", + "ram_storage.c", + "ram_storage.h", "KeyValueStoreManagerImpl.cpp", "KeyValueStoreManagerImpl.h", "Logging.cpp", diff --git a/src/platform/nxp/k32w/k32w0/K32W0Config.cpp b/src/platform/nxp/k32w/k32w0/K32W0Config.cpp index bf4910285160c4..2fe4220313c7ba 100644 --- a/src/platform/nxp/k32w/k32w0/K32W0Config.cpp +++ b/src/platform/nxp/k32w/k32w0/K32W0Config.cpp @@ -36,15 +36,87 @@ namespace chip { namespace DeviceLayer { namespace Internal { +#define BUFFER_LOG_SIZE 256 +#define CHIP_CONFIG_RAM_BUFFER_SIZE 3072 + +#ifndef NVM_ID_CHIP_CONFIG_DATA +#define NVM_ID_CHIP_CONFIG_DATA 0x5000 +#endif + +typedef struct +{ + uint16_t chipConfigRamBufferLen; + uint8_t chipConfigRamBuffer[1]; +} ChipConfigRamStruct_t; + +static ChipConfigRamStruct_t *chipConfigRamStruct; +static ramBufferDescriptor ramDescr = { 0 }; + +static rsError AddToRamStorage(ramBufferDescriptor * pBuffer, uint16_t aKey, const uint8_t * aValue, uint16_t aValueLength) +{ + rsError err; + uint32_t allocSize = ramDescr.ramBufferMaxLen; + + if ( allocSize <= *(pBuffer->ramBufferLen) + aValueLength ) + { + while (allocSize < *(pBuffer->ramBufferLen) + aValueLength) + { + /* Need to realocate the memory buffer, increase size by 512B until nvm data fits */ + allocSize += 512; + } + + allocSize += sizeof (uint16_t); + chipConfigRamStruct = (ChipConfigRamStruct_t *) realloc((void *)chipConfigRamStruct, allocSize); + VerifyOrExit((NULL != chipConfigRamStruct), err = RS_ERROR_NO_BUFS); + + ramDescr.ramBufferLen = &chipConfigRamStruct->chipConfigRamBufferLen; + ramDescr.ramBufferMaxLen = allocSize - sizeof(uint16_t); + ramDescr.pRamBuffer = &chipConfigRamStruct->chipConfigRamBuffer[0]; + } + + err = ramStorageSet(pBuffer, aKey, aValue, aValueLength); + +exit: + return err; +} CHIP_ERROR K32WConfig::Init() { CHIP_ERROR err; - int pdmStatus; + int pdmStatus;; + uint16_t bytesRead, recordSize; + bool bLoadDataFromNvm = false; + uint32_t allocSize = CHIP_CONFIG_RAM_BUFFER_SIZE; /* Initialise the Persistent Data Manager */ pdmStatus = PDM_Init(); SuccessOrExit(err = MapPdmInitStatus(pdmStatus)); + /* Check if dataset is present and get its size */ + if (PDM_bDoesDataExist((uint16_t) NVM_ID_CHIP_CONFIG_DATA, &recordSize)) + { + bLoadDataFromNvm = true; + while (recordSize > allocSize) + { + //increase size by 1k until nvm data fits + allocSize += 1024; + } + } + + chipConfigRamStruct = (ChipConfigRamStruct_t *) malloc(allocSize); + VerifyOrExit((NULL != chipConfigRamStruct), err = CHIP_ERROR_NO_MEMORY); + + chipConfigRamStruct->chipConfigRamBufferLen = 0; + ramDescr.ramBufferLen = &chipConfigRamStruct->chipConfigRamBufferLen; + ramDescr.ramBufferMaxLen = allocSize - sizeof(uint16_t); + ramDescr.pRamBuffer = &chipConfigRamStruct->chipConfigRamBuffer[0]; + + if(bLoadDataFromNvm) + { + /* Try to load the dataset in RAM */ + PDM_eReadDataFromRecord((uint16_t) NVM_ID_CHIP_CONFIG_DATA, chipConfigRamStruct, recordSize, &bytesRead); + + } + exit: return err; } @@ -53,12 +125,12 @@ CHIP_ERROR K32WConfig::ReadConfigValue(Key key, bool & val) { CHIP_ERROR err; bool tempVal; - uint16_t bytesRead; - PDM_teStatus pdmStatus; + rsError status; + uint16_t sizeToRead = sizeof(tempVal); VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. - pdmStatus = PDM_eReadDataFromRecord((uint16_t) key, &tempVal, sizeof(bool), &bytesRead); - SuccessOrExit(err = MapPdmStatus(pdmStatus)); + status = ramStorageGet(&ramDescr, key, 0, (uint8_t*) &tempVal, &sizeToRead); + SuccessOrExit(err = MapRamStorageStatus(status)); val = tempVal; exit: @@ -69,22 +141,13 @@ CHIP_ERROR K32WConfig::ReadConfigValue(Key key, uint32_t & val) { CHIP_ERROR err; uint32_t tempVal; - uint16_t bytesRead; - uint16_t recordSize; - PDM_teStatus pdmStatus; - + rsError status; + uint16_t sizeToRead = sizeof(tempVal); + VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. - if (PDM_bDoesDataExist((uint16_t) key, &recordSize)) - { - pdmStatus = PDM_eReadDataFromRecord((uint16_t) key, &tempVal, sizeof(uint32_t), &bytesRead); - SuccessOrExit(err = MapPdmStatus(pdmStatus)); - val = tempVal; - } - else - { - err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; - goto exit; - } + status = ramStorageGet(&ramDescr, key, 0, (uint8_t*) &tempVal, &sizeToRead); + SuccessOrExit(err = MapRamStorageStatus(status)); + val = tempVal; exit: return err; @@ -93,24 +156,14 @@ CHIP_ERROR K32WConfig::ReadConfigValue(Key key, uint32_t & val) CHIP_ERROR K32WConfig::ReadConfigValue(Key key, uint64_t & val) { CHIP_ERROR err; - uint64_t tempVal; - uint16_t bytesRead; - uint16_t recordSize; - PDM_teStatus pdmStatus; - + uint32_t tempVal; + rsError status; + uint16_t sizeToRead = sizeof(tempVal); + VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. - - if (PDM_bDoesDataExist((uint16_t) key, &recordSize)) - { - pdmStatus = PDM_eReadDataFromRecord((uint16_t) key, &tempVal, sizeof(uint64_t), &bytesRead); - SuccessOrExit(err = MapPdmStatus(pdmStatus)); - val = tempVal; - } - else - { - err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; - goto exit; - } + status = ramStorageGet(&ramDescr, key, 0, (uint8_t*) &tempVal, &sizeToRead); + SuccessOrExit(err = MapRamStorageStatus(status)); + val = tempVal; exit: return err; @@ -119,130 +172,44 @@ CHIP_ERROR K32WConfig::ReadConfigValue(Key key, uint64_t & val) CHIP_ERROR K32WConfig::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen) { CHIP_ERROR err; - const uint8_t * strEnd; - char * pData = NULL; - uint16_t bytesRead; - uint16_t recordSize; - PDM_teStatus pdmStatus; - - outLen = 0; + rsError status; + uint16_t sizeToRead = bufSize; VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. - - if (PDM_bDoesDataExist((uint16_t) key, &recordSize)) - { - pData = (char *) pvPortMalloc(recordSize); - VerifyOrExit((pData != NULL), err = CHIP_ERROR_NO_MEMORY); - - pdmStatus = PDM_eReadDataFromRecord((uint16_t) key, pData, recordSize, &bytesRead); - SuccessOrExit(err = MapPdmStatus(pdmStatus)); - - strEnd = (const uint8_t *) memchr(pData, 0, bytesRead); - VerifyOrExit(strEnd != NULL, err = CHIP_ERROR_INVALID_ARGUMENT); - - outLen = strEnd - (const uint8_t *) pData; - - // NOTE: the caller is allowed to pass NULL for buf to query the length of the stored value. - - if (buf != NULL) - { - VerifyOrExit(bufSize > outLen, err = CHIP_ERROR_BUFFER_TOO_SMALL); - - memcpy(buf, pData, outLen + 1); - } - } - else - { - err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; - goto exit; - } + + //We can call ramStorageGet with null pointer to only retrieve the size + status = ramStorageGet(&ramDescr, key, 0, (uint8_t*) buf, &sizeToRead); + SuccessOrExit(err = MapRamStorageStatus(status)); + outLen = sizeToRead; exit: - if (pData != NULL) - { - vPortFree((void *) pData); - } return err; } CHIP_ERROR K32WConfig::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen) { - CHIP_ERROR err; - uint8_t * pData = NULL; - uint16_t bytesRead; - uint16_t recordSize; - PDM_teStatus pdmStatus; - - outLen = 0; - - VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. - - if (PDM_bDoesDataExist((uint16_t) key, &recordSize)) - { - pData = (uint8_t *) pvPortMalloc(recordSize); - VerifyOrExit((pData != NULL), err = CHIP_ERROR_NO_MEMORY); - - pdmStatus = PDM_eReadDataFromRecord((uint16_t) key, pData, recordSize, &bytesRead); - SuccessOrExit(err = MapPdmStatus(pdmStatus)); - - if (buf != NULL) - { - VerifyOrExit((bufSize >= bytesRead), err = CHIP_ERROR_BUFFER_TOO_SMALL); - memcpy(buf, pData, bytesRead); - } - outLen = bytesRead; - } - else - { - err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; - goto exit; - } - -exit: - if (pData != NULL) - { - vPortFree((void *) pData); - } - - return err; + return ReadConfigValueStr(key, (char*) buf, bufSize, outLen); } CHIP_ERROR K32WConfig::ReadConfigValueCounter(uint8_t counterIdx, uint32_t & val) { - CHIP_ERROR err; - uint32_t tempVal; - uint16_t bytesRead; - uint16_t recordSize; - PDM_teStatus pdmStatus; - Key key = kMinConfigKey_ChipCounter + counterIdx; - VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. - - if (PDM_bDoesDataExist((uint16_t) key, &recordSize)) - { - pdmStatus = PDM_eReadDataFromRecord((uint16_t) key, &tempVal, sizeof(uint32_t), &bytesRead); - SuccessOrExit(err = MapPdmStatus(pdmStatus)); - val = tempVal; - } - else - { - err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; - goto exit; - } - -exit: - return err; + return ReadConfigValue(key, val); } CHIP_ERROR K32WConfig::WriteConfigValue(Key key, bool val) { CHIP_ERROR err; + rsError status; PDM_teStatus pdmStatus; VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. - pdmStatus = PDM_eSaveRecordData((uint16_t) key, &val, sizeof(bool)); - SuccessOrExit(err = MapPdmStatus(pdmStatus)); + status = AddToRamStorage(&ramDescr, key, (uint8_t *) &val, sizeof(bool)); + SuccessOrExit(err = MapRamStorageStatus(status)); + pdmStatus = PDM_eSaveRecordDataInIdleTask((uint16_t) NVM_ID_CHIP_CONFIG_DATA, chipConfigRamStruct, + chipConfigRamStruct->chipConfigRamBufferLen + sizeof(uint16_t)); + SuccessOrExit(err = MapPdmStatus(pdmStatus)); exit: return err; } @@ -250,10 +217,15 @@ CHIP_ERROR K32WConfig::WriteConfigValue(Key key, bool val) CHIP_ERROR K32WConfig::WriteConfigValue(Key key, uint32_t val) { CHIP_ERROR err; + rsError status; PDM_teStatus pdmStatus; VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. - pdmStatus = PDM_eSaveRecordData((uint16_t) key, &val, sizeof(uint32_t)); + status = AddToRamStorage(&ramDescr, key, (uint8_t *)&val, sizeof(uint32_t)); + SuccessOrExit(err = MapRamStorageStatus(status)); + + pdmStatus = PDM_eSaveRecordDataInIdleTask((uint16_t) NVM_ID_CHIP_CONFIG_DATA, chipConfigRamStruct, + chipConfigRamStruct->chipConfigRamBufferLen + sizeof(uint16_t)); SuccessOrExit(err = MapPdmStatus(pdmStatus)); exit: @@ -263,10 +235,15 @@ CHIP_ERROR K32WConfig::WriteConfigValue(Key key, uint32_t val) CHIP_ERROR K32WConfig::WriteConfigValue(Key key, uint64_t val) { CHIP_ERROR err; + rsError status; PDM_teStatus pdmStatus; VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. - pdmStatus = PDM_eSaveRecordData((uint16_t) key, &val, sizeof(uint64_t)); + status = AddToRamStorage(&ramDescr, key, (uint8_t *)&val, sizeof(uint64_t)); + SuccessOrExit(err = MapRamStorageStatus(status)); + + pdmStatus = PDM_eSaveRecordDataInIdleTask((uint16_t) NVM_ID_CHIP_CONFIG_DATA, chipConfigRamStruct, + chipConfigRamStruct->chipConfigRamBufferLen + sizeof(uint16_t)); SuccessOrExit(err = MapPdmStatus(pdmStatus)); exit: @@ -282,12 +259,17 @@ CHIP_ERROR K32WConfig::WriteConfigValueStr(Key key, const char * str, size_t str { CHIP_ERROR err; PDM_teStatus pdmStatus; - + rsError status; + VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. if (str != NULL) { - pdmStatus = PDM_eSaveRecordData((uint16_t) key, (void *) str, strLen); + status = AddToRamStorage(&ramDescr, key, (uint8_t *) str, strLen); + SuccessOrExit(err = MapRamStorageStatus(status)); + + pdmStatus = PDM_eSaveRecordDataInIdleTask((uint16_t) NVM_ID_CHIP_CONFIG_DATA, chipConfigRamStruct, + chipConfigRamStruct->chipConfigRamBufferLen + sizeof(uint16_t)); SuccessOrExit(err = MapPdmStatus(pdmStatus)); } else @@ -295,55 +277,34 @@ CHIP_ERROR K32WConfig::WriteConfigValueStr(Key key, const char * str, size_t str err = ClearConfigValue(key); SuccessOrExit(err); } - exit: return err; } CHIP_ERROR K32WConfig::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen) { - CHIP_ERROR err; - PDM_teStatus pdmStatus; - - VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. - - if ((data != NULL) && (dataLen > 0)) - { - pdmStatus = PDM_eSaveRecordData((uint16_t) key, (void *) data, dataLen); - SuccessOrExit(err = MapPdmStatus(pdmStatus)); - } - else - { - err = ClearConfigValue(key); - SuccessOrExit(err); - } - -exit: - return err; + return WriteConfigValueStr(key, (char *) data, dataLen); } CHIP_ERROR K32WConfig::WriteConfigValueCounter(uint8_t counterIdx, uint32_t val) { - CHIP_ERROR err; - PDM_teStatus pdmStatus; - Key key = kMinConfigKey_ChipCounter + counterIdx; - VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. - pdmStatus = PDM_eSaveRecordData((uint16_t) key, &val, sizeof(uint32_t)); - SuccessOrExit(err = MapPdmStatus(pdmStatus)); - -exit: - return err; + return WriteConfigValue(key, val); } CHIP_ERROR K32WConfig::ClearConfigValue(Key key) { CHIP_ERROR err = CHIP_NO_ERROR; - + rsError status; + PDM_teStatus pdmStatus; + VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. - PDM_vDeleteDataRecord((uint16_t) key); + status = ramStorageDelete(&ramDescr, key, 0); + SuccessOrExit(err = MapRamStorageStatus(status)); - SuccessOrExit(err); + pdmStatus = PDM_eSaveRecordDataInIdleTask((uint16_t) NVM_ID_CHIP_CONFIG_DATA, chipConfigRamStruct, + chipConfigRamStruct->chipConfigRamBufferLen + sizeof(uint16_t)); + SuccessOrExit(err = MapPdmStatus(pdmStatus)); exit: return err; @@ -351,20 +312,22 @@ CHIP_ERROR K32WConfig::ClearConfigValue(Key key) bool K32WConfig::ConfigValueExists(Key key) { - CHIP_ERROR err; - uint16_t size = 0; - - VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. - VerifyOrExit(PDM_bDoesDataExist((uint16_t) key, &size), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); + rsError status; + uint16_t sizeToRead; + bool found = false; -exit: - // Return true if the record was found. - return (err == CHIP_NO_ERROR); + if (ValidConfigKey(key)) + { + status = ramStorageGet(&ramDescr, key, 0, NULL, &sizeToRead); + found = (status == RS_ERROR_NONE && sizeToRead != 0); + } + return found; } CHIP_ERROR K32WConfig::FactoryResetConfig(void) { CHIP_ERROR err; + PDM_teStatus pdmStatus; err = FactoryResetConfigInternal(kMinConfigKey_ChipConfig, kMaxConfigKey_ChipConfig); @@ -373,28 +336,21 @@ CHIP_ERROR K32WConfig::FactoryResetConfig(void) err = FactoryResetConfigInternal(kMinConfigKey_KVS, kMaxConfigKey_KVS); } + pdmStatus = PDM_eSaveRecordData((uint16_t) NVM_ID_CHIP_CONFIG_DATA, chipConfigRamStruct, + chipConfigRamStruct->chipConfigRamBufferLen + sizeof(uint16_t)); + SuccessOrExit(err = MapPdmStatus(pdmStatus)); + +exit: return err; } CHIP_ERROR K32WConfig::FactoryResetConfigInternal(Key firstKey, Key lastKey) { - CHIP_ERROR err; - - // Iterate over all the CHIP Config PDM ID records and delete each one - err = ForEachRecord(firstKey, lastKey, false, [](const Key & pdmKey, const size_t & length) -> CHIP_ERROR { - CHIP_ERROR err2; - - err2 = ClearConfigValue(pdmKey); - SuccessOrExit(err2); - - exit: - return err2; - }); + CHIP_ERROR err = CHIP_NO_ERROR; - // Return success at end of iterations. - if (err == CHIP_END_OF_INPUT) + for (Key key = firstKey; key <= lastKey; key++) { - err = CHIP_NO_ERROR; + ramStorageDelete(&ramDescr, key, 0); } return err; @@ -417,6 +373,29 @@ CHIP_ERROR K32WConfig::MapPdmStatus(PDM_teStatus pdmStatus) return err; } +CHIP_ERROR K32WConfig::MapRamStorageStatus(rsError rsStatus) +{ + CHIP_ERROR err; + + switch (rsStatus) + { + case RS_ERROR_NONE: + err = CHIP_NO_ERROR; + break; + case RS_ERROR_NOT_FOUND: + err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; + break; + default: + err = CHIP_ERROR_BUFFER_TOO_SMALL; + break; + } + + return err; +} + + + + CHIP_ERROR K32WConfig::MapPdmInitStatus(int pdmStatus) { return (pdmStatus == 0) ? CHIP_NO_ERROR : CHIP_ERROR(ChipError::Range::kPlatform, pdmStatus); @@ -425,7 +404,6 @@ CHIP_ERROR K32WConfig::MapPdmInitStatus(int pdmStatus) bool K32WConfig::ValidConfigKey(Key key) { // Returns true if the key is in the valid CHIP Config PDM key range. - if ((key >= kMinConfigKey_ChipFactory) && (key <= kMaxConfigKey_KVS)) { return true; @@ -434,40 +412,6 @@ bool K32WConfig::ValidConfigKey(Key key) return false; } -CHIP_ERROR K32WConfig::ForEachRecord(Key firstKey, Key lastKey, bool addNewRecord, ForEachRecordFunct funct) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - - for (Key pdmKey = firstKey; pdmKey <= lastKey; pdmKey++) - { - uint16_t dataLen; - - if (PDM_bDoesDataExist((uint16_t) pdmKey, &dataLen)) - { - if (!addNewRecord) - { - // Invoke the caller's function - // (for retrieve,store,delete,enumerate GroupKey operations). - err = funct(pdmKey, dataLen); - } - } - else - { - if (addNewRecord) - { - // Invoke caller's function - // (for add GroupKey operation). - err = funct(pdmKey, dataLen); - } - } - - SuccessOrExit(err); - } - -exit: - return err; -} - void K32WConfig::RunConfigUnitTest() {} } // namespace Internal diff --git a/src/platform/nxp/k32w/k32w0/K32W0Config.h b/src/platform/nxp/k32w/k32w0/K32W0Config.h index 789906049f7eb7..957a0aa980cc07 100644 --- a/src/platform/nxp/k32w/k32w0/K32W0Config.h +++ b/src/platform/nxp/k32w/k32w0/K32W0Config.h @@ -30,6 +30,7 @@ #include "MemManager.h" #include "PDM.h" +#include "ram_storage.h" namespace chip { namespace DeviceLayer { @@ -132,13 +133,12 @@ class K32WConfig static void RunConfigUnitTest(void); protected: - using ForEachRecordFunct = std::function; - static CHIP_ERROR ForEachRecord(Key firstKey, Key lastKey, bool addNewRecord, ForEachRecordFunct funct); static constexpr uint8_t GetPDMId(uint32_t key); static constexpr uint8_t GetRecordKey(uint32_t key); private: static CHIP_ERROR MapPdmStatus(PDM_teStatus pdmStatus); + static CHIP_ERROR MapRamStorageStatus(rsError rsStatus); static CHIP_ERROR MapPdmInitStatus(int pdmStatus); static CHIP_ERROR FactoryResetConfigInternal(Key firstKey, Key lastKey); }; diff --git a/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.cpp b/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.cpp index 3db7074db3e35c..e103c0369c0511 100644 --- a/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.cpp +++ b/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.cpp @@ -43,100 +43,61 @@ constexpr size_t kMaxKeyValueBytes = 255; KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance; -/* hashmap having: - * - the matter key string as key; - * - internal PDM identifier as value; - */ -std::unordered_map g_kvs_map; - -/* set containing used PDM identifiers */ -std::set g_key_ids_set; - -/* used to check if we need to restore values from flash (e.g.: reset) */ -static bool g_restored_from_flash = false; - -CHIP_ERROR RestoreFromFlash() +uint16_t GetStringKeyId(const char * key, uint16_t * freeId) { - CHIP_ERROR err = CHIP_NO_ERROR; - uint8_t key_id = 0; - char key_string_id[kMaxKeyValueBytes] = { 0 }; - size_t key_string_id_size = 0; - uint8_t pdm_id_kvs = chip::DeviceLayer::Internal::K32WConfig::kPDMId_KVS; - uint16_t pdm_internal_id = 0; - - if (g_restored_from_flash) - { - /* already restored from flash, nothing to do */ - return err; - } - - for (key_id = 0; key_id < kMaxNumberOfKeys; key_id++) + CHIP_ERROR err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; + uint8_t keyId = 0; + uint8_t pdmIdKvs = chip::DeviceLayer::Internal::K32WConfig::kPDMId_KVS; + bool bFreeIdxFound = false; + char keyString[kMaxKeyValueBytes] = { 0 }; + size_t keyStringSize = 0; + uint16_t pdmInternalId; + + for (keyId = 0; keyId < kMaxNumberOfKeys; keyId++) { - /* key was saved as string in flash (key_string_id) using (key_id + kMaxNumberOfKeys) as PDM key - * value corresponding to key_string_id was saved in flash using key_id as PDM key - */ - - pdm_internal_id = chip::DeviceLayer::Internal::K32WConfigKey(pdm_id_kvs, key_id + kMaxNumberOfKeys); - err = chip::DeviceLayer::Internal::K32WConfig::ReadConfigValueStr(pdm_internal_id, key_string_id, kMaxKeyValueBytes, - key_string_id_size); - - if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) - { - err = CHIP_NO_ERROR; - continue; - } - else if (err != CHIP_NO_ERROR) - { - ChipLogProgress(DeviceLayer, "KVS, Error while restoring Matter key [%s] from flash with PDM id: %i", key_string_id, - pdm_internal_id); - return err; - } + pdmInternalId = chip::DeviceLayer::Internal::K32WConfigKey(pdmIdKvs, kMaxNumberOfKeys + keyId); + err = chip::DeviceLayer::Internal::K32WConfig::ReadConfigValueStr(pdmInternalId , keyString, + kMaxKeyValueBytes, keyStringSize); - if (key_string_id_size) + if (err == CHIP_NO_ERROR) { - g_key_ids_set.insert(key_id); - key_string_id_size = 0; - if (!g_kvs_map.insert(std::make_pair(std::string(key_string_id), key_id)).second) - { - /* key collision is not expected when restoring from flash */ - ChipLogProgress(DeviceLayer, "KVS, Unexpected collision while restoring Matter key [%s] from flash with PDM id: %i", - key_string_id, pdm_internal_id); - } - else + if (strcmp(key,keyString) == 0) { - ChipLogProgress(DeviceLayer, "KVS, restored Matter key [%s] from flash with PDM id: %i", key_string_id, - pdm_internal_id); + //found the entry we are looking for + break; } } + else if ((NULL != freeId) && (false == bFreeIdxFound)) + { + bFreeIdxFound = true; + *freeId = keyId; + } } - - g_restored_from_flash = true; - - return err; + return keyId; } + CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size, size_t offset_bytes) { - CHIP_ERROR err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; - uint8_t pdm_id_kvs = chip::DeviceLayer::Internal::K32WConfig::kPDMId_KVS; - std::unordered_map::const_iterator it; - size_t read_bytes = 0; - uint8_t key_id = 0; - uint16_t pdm_internal_id = 0; + CHIP_ERROR err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; + uint8_t pdmIdKvs = chip::DeviceLayer::Internal::K32WConfig::kPDMId_KVS; + size_t read_bytes = 0; + uint8_t keyId = 0; + uint16_t pdmInternalId = 0; - VerifyOrExit((key != NULL) && (value != NULL) && (RestoreFromFlash() == CHIP_NO_ERROR), err = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit((key != NULL) && (value != NULL), err = CHIP_ERROR_INVALID_ARGUMENT); - if ((it = g_kvs_map.find(key)) != g_kvs_map.end()) - { - key_id = it->second; - pdm_internal_id = chip::DeviceLayer::Internal::K32WConfigKey(pdm_id_kvs, key_id); + keyId = GetStringKeyId(key, NULL); - err = - chip::DeviceLayer::Internal::K32WConfig::ReadConfigValueBin(pdm_internal_id, (uint8_t *) value, value_size, read_bytes); + if (keyId < kMaxNumberOfKeys) + { + //This is the ID of the actual data + pdmInternalId = chip::DeviceLayer::Internal::K32WConfigKey(pdmIdKvs, keyId); + err = chip::DeviceLayer::Internal::K32WConfig::ReadConfigValueBin(pdmInternalId, (uint8_t *) value, value_size, read_bytes); *read_bytes_size = read_bytes; - ChipLogProgress(DeviceLayer, "KVS, get Matter key [%s] with PDM id: %i", key, pdm_internal_id); + ChipLogProgress(DeviceLayer, "KVS, get Matter key [%s] with PDM id: %i", key, pdmInternalId); } exit: @@ -145,69 +106,58 @@ CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, size_t value_size) { - CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; - uint8_t key_id; - bool_t put_key = false; - uint8_t pdm_id_kvs = chip::DeviceLayer::Internal::K32WConfig::kPDMId_KVS; - std::unordered_map::const_iterator it; - uint16_t pdm_internal_id = 0; - - VerifyOrExit((key != NULL) && (value != NULL) && (RestoreFromFlash() == CHIP_NO_ERROR), err = CHIP_ERROR_INVALID_ARGUMENT); - - if ((it = g_kvs_map.find(key)) == g_kvs_map.end()) /* new key */ + CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; + bool_t putKey = false; + uint8_t pdmIdKvs = chip::DeviceLayer::Internal::K32WConfig::kPDMId_KVS; + uint16_t pdmInternalId = 0; + uint16_t freeKeyId; + uint8_t keyId; + + VerifyOrExit((key != NULL) && (value != NULL), err = CHIP_ERROR_INVALID_ARGUMENT); + + keyId = GetStringKeyId(key, &freeKeyId); + + //Key allready exists + if (keyId < kMaxNumberOfKeys) { - for (key_id = 0; key_id < kMaxNumberOfKeys; key_id++) - { - std::set::iterator iter = std::find(g_key_ids_set.begin(), g_key_ids_set.end(), key_id); - - if (iter == g_key_ids_set.end()) - { - if (g_key_ids_set.size() >= kMaxNumberOfKeys) - { - return CHIP_ERROR_NO_MEMORY; - } - - g_key_ids_set.insert(key_id); - - put_key = true; - break; - } - } + //Update just the value in this case + putKey = false; } - else /* overwrite key */ + else { - put_key = true; - key_id = it->second; + //Need to write both the value and the string key + putKey = true; + keyId = freeKeyId; } - if (put_key) - { - pdm_internal_id = chip::DeviceLayer::Internal::K32WConfigKey(pdm_id_kvs, key_id); - ChipLogProgress(DeviceLayer, "KVS, save in flash the value of the Matter key [%s] with PDM id: %i", key, pdm_internal_id); + pdmInternalId = chip::DeviceLayer::Internal::K32WConfigKey(pdmIdKvs, keyId); + ChipLogProgress(DeviceLayer, "KVS, save in flash the value of the Matter key [%s] with PDM id: %i", key, pdmInternalId); - g_kvs_map.insert(std::make_pair(std::string(key), key_id)); - err = chip::DeviceLayer::Internal::K32WConfig::WriteConfigValueBin(pdm_internal_id, (uint8_t *) value, value_size); + err = chip::DeviceLayer::Internal::K32WConfig::WriteConfigValueBin(pdmInternalId, (uint8_t *) value, value_size); - /* save the 'key' in flash such that it can be retrieved later on */ - if (err == CHIP_NO_ERROR) + /* save the 'key' in flash such that it can be retrieved later on */ + if (err == CHIP_NO_ERROR) + { + if (true == putKey) { - pdm_internal_id = chip::DeviceLayer::Internal::K32WConfigKey(pdm_id_kvs, key_id + kMaxNumberOfKeys); - ChipLogProgress(DeviceLayer, "KVS, save in flash the Matter key [%s] with PDM id: %i", key, pdm_internal_id); + pdmInternalId = chip::DeviceLayer::Internal::K32WConfigKey(pdmIdKvs, keyId + kMaxNumberOfKeys); + ChipLogProgress(DeviceLayer, "KVS, save in flash the Matter key [%s] with PDM id: %i", key, pdmInternalId); - err = chip::DeviceLayer::Internal::K32WConfig::WriteConfigValueStr(pdm_internal_id, key, strlen(key) + 1); + err = chip::DeviceLayer::Internal::K32WConfig::WriteConfigValueStr(pdmInternalId, key, strlen(key) + 1); if (err != CHIP_NO_ERROR) { ChipLogProgress(DeviceLayer, "KVS, Error while saving in flash the Matter key [%s] with PDM id: %i", key, - pdm_internal_id); + pdmInternalId); } } - else - { - ChipLogProgress(DeviceLayer, "KVS, Error while saving in flash the value of the Matter key [%s] with PDM id: %i", key, - pdm_internal_id); - } } + else + { + ChipLogProgress(DeviceLayer, "KVS, Error while saving in flash the value of the Matter key [%s] with PDM id: %i", key, + pdmInternalId); + } + exit: return err; @@ -215,48 +165,45 @@ CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, CHIP_ERROR KeyValueStoreManagerImpl::_Delete(const char * key) { - CHIP_ERROR err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; - std::unordered_map::const_iterator it; - uint8_t pdm_id_kvs = chip::DeviceLayer::Internal::K32WConfig::kPDMId_KVS; - uint8_t key_id = 0; - uint16_t pdm_internal_id = 0; + CHIP_ERROR err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; + uint8_t pdmIdKvs = chip::DeviceLayer::Internal::K32WConfig::kPDMId_KVS; + uint8_t keyId = 0; + uint16_t pdmInternalId = 0; - VerifyOrExit((key != NULL) && (RestoreFromFlash() == CHIP_NO_ERROR), err = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit((key != NULL), err = CHIP_ERROR_INVALID_ARGUMENT); - if ((it = g_kvs_map.find(key)) != g_kvs_map.end()) - { - key_id = it->second; - pdm_internal_id = chip::DeviceLayer::Internal::K32WConfigKey(pdm_id_kvs, key_id); + keyId = GetStringKeyId(key, NULL); - g_key_ids_set.erase(key_id); - g_kvs_map.erase(it); + if (keyId < kMaxNumberOfKeys) + { + //entry exists so we can remove it + pdmInternalId = chip::DeviceLayer::Internal::K32WConfigKey(pdmIdKvs, keyId); - ChipLogProgress(DeviceLayer, "KVS, delete from flash the Matter key [%s] with PDM id: %i", key, pdm_internal_id); - err = chip::DeviceLayer::Internal::K32WConfig::ClearConfigValue(pdm_internal_id); + ChipLogProgress(DeviceLayer, "KVS, delete from flash the Matter key [%s] with PDM id: %i", key, pdmInternalId); + err = chip::DeviceLayer::Internal::K32WConfig::ClearConfigValue(pdmInternalId); /* also delete the 'key string' from flash */ if (err == CHIP_NO_ERROR) { - pdm_internal_id = chip::DeviceLayer::Internal::K32WConfigKey(pdm_id_kvs, key_id + kMaxNumberOfKeys); + pdmInternalId = chip::DeviceLayer::Internal::K32WConfigKey(pdmIdKvs, keyId + kMaxNumberOfKeys); ChipLogProgress(DeviceLayer, "KVS, delete from flash the value of the Matter key [%s] with PDM id: %i", key, - pdm_internal_id); + pdmInternalId); - err = chip::DeviceLayer::Internal::K32WConfig::ClearConfigValue(pdm_internal_id); + err = chip::DeviceLayer::Internal::K32WConfig::ClearConfigValue(pdmInternalId); if (err != CHIP_NO_ERROR) { ChipLogProgress(DeviceLayer, "KVS, Error while deleting from flash the value of the Matter key [%s] with PDM id: %i", key, - pdm_internal_id); + pdmInternalId); } } else { ChipLogProgress(DeviceLayer, "KVS, Error while deleting from flash the Matter key [%s] with PDM id: %i", key, - pdm_internal_id); + pdmInternalId); } } - exit: return err; } diff --git a/src/platform/nxp/k32w/k32w0/ram_storage.c b/src/platform/nxp/k32w/k32w0/ram_storage.c new file mode 100644 index 00000000000000..d60d586e40e332 --- /dev/null +++ b/src/platform/nxp/k32w/k32w0/ram_storage.c @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2021, 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. + */ +#include +#include +#include +#include + +#include "FunctionLib.h" +#include "ram_storage.h" + +#ifndef RAM_STORAGE_LOG +#define RAM_STORAGE_LOG 0 +#endif + +#if RAM_STORAGE_LOG +#include "fsl_debug_console.h" +#define RAM_STORAGE_PRINTF(...) \ + PRINTF("[%s] ", __FUNCTION__); \ + PRINTF(__VA_ARGS__); \ + PRINTF("\n\r"); +#else +#define RAM_STORAGE_PRINTF(...) +#endif + +struct settingsBlock +{ + uint16_t key; + uint16_t length; +} __attribute__((packed)); + +static rsError ramStorageAdd(ramBufferDescriptor * pBuffer, uint16_t aKey, const uint8_t * aValue, uint16_t aValueLength) +{ + rsError error; + struct settingsBlock * currentBlock; + const uint16_t newBlockLength = sizeof(struct settingsBlock) + aValueLength; + + if (*(pBuffer->ramBufferLen) + newBlockLength <= pBuffer->ramBufferMaxLen) + { + currentBlock = (struct settingsBlock *) &pBuffer->pRamBuffer[*(pBuffer->ramBufferLen)]; + currentBlock->key = aKey; + currentBlock->length = aValueLength; + + memcpy(&pBuffer->pRamBuffer[*(pBuffer->ramBufferLen) + sizeof(struct settingsBlock)], aValue, aValueLength); + *(pBuffer->ramBufferLen) += newBlockLength; + + error = RS_ERROR_NONE; + } + else + { + error = RS_ERROR_NO_BUFS; + } + + RAM_STORAGE_PRINTF("key = %d lengthWriten = %d err = %d", aKey, aValueLength, error); + + return error; +} + +rsError ramStorageGet(const ramBufferDescriptor * pBuffer, uint16_t aKey, int aIndex, uint8_t * aValue, uint16_t * aValueLength) +{ + uint16_t i = 0; + uint16_t valueLength = 0; + uint16_t readLength; + int currentIndex = 0; + const struct settingsBlock * currentBlock; + rsError error = RS_ERROR_NOT_FOUND; + + while (i < *(pBuffer->ramBufferLen)) + { + currentBlock = (struct settingsBlock *) &pBuffer->pRamBuffer[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, &pBuffer->pRamBuffer[i + sizeof(struct settingsBlock)], readLength); + } + + valueLength = currentBlock->length; + error = RS_ERROR_NONE; + break; + } + + currentIndex++; + } + + i += sizeof(struct settingsBlock) + currentBlock->length; + } + + if (aValueLength != NULL) + { + *aValueLength = valueLength; + } + + RAM_STORAGE_PRINTF("key = %d err = %d", aKey, error); + + return error; +} + +rsError ramStorageSet(ramBufferDescriptor * pBuffer, 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 < *(pBuffer->ramBufferLen)) + { + currentBlock = (struct settingsBlock *) &pBuffer->pRamBuffer[i]; + currentBlockLength = sizeof(struct settingsBlock) + currentBlock->length; + + if (aKey == currentBlock->key) + { + nextBlockStart = i + currentBlockLength; + + if (nextBlockStart < *(pBuffer->ramBufferLen)) + { + memmove(&pBuffer->pRamBuffer[i], &pBuffer->pRamBuffer[nextBlockStart], *(pBuffer->ramBufferLen) - nextBlockStart); + } + + assert(*(pBuffer->ramBufferLen) >= currentBlockLength); + *(pBuffer->ramBufferLen) -= currentBlockLength; + } + else + { + i += currentBlockLength; + } + } + + return ramStorageAdd(pBuffer, aKey, aValue, aValueLength); +} + +rsError ramStorageDelete(ramBufferDescriptor * pBuffer, uint16_t aKey, int aIndex) +{ + uint16_t i = 0; + int currentIndex = 0; + uint16_t nextBlockStart; + uint16_t currentBlockLength; + const struct settingsBlock * currentBlock; + rsError error = RS_ERROR_NOT_FOUND; + + while (i < *(pBuffer->ramBufferLen)) + { + currentBlock = (struct settingsBlock *) &pBuffer->pRamBuffer[i]; + currentBlockLength = sizeof(struct settingsBlock) + currentBlock->length; + + if (aKey == currentBlock->key) + { + if (currentIndex == aIndex) + { + nextBlockStart = i + currentBlockLength; + + if (nextBlockStart < *(pBuffer->ramBufferLen)) + { + memmove(&pBuffer->pRamBuffer[i], &pBuffer->pRamBuffer[nextBlockStart], + *(pBuffer->ramBufferLen) - nextBlockStart); + } + + assert(*(pBuffer->ramBufferLen) >= currentBlockLength); + *(pBuffer->ramBufferLen) -= currentBlockLength; + + error = RS_ERROR_NONE; + break; + } + else + { + currentIndex++; + } + } + + i += currentBlockLength; + } + RAM_STORAGE_PRINTF("key = %d err = %d", aKey, error); + return error; +} \ No newline at end of file diff --git a/src/platform/nxp/k32w/k32w0/ram_storage.h b/src/platform/nxp/k32w/k32w0/ram_storage.h new file mode 100644 index 00000000000000..50d1b8ef6d965d --- /dev/null +++ b/src/platform/nxp/k32w/k32w0/ram_storage.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021, 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. + */ + +#ifndef RAM_STORAGE_H +#define RAM_STORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + RS_ERROR_NONE, + RS_ERROR_NOT_FOUND, + RS_ERROR_NO_BUFS +} rsError; + +typedef struct +{ + uint16_t *ramBufferLen; + uint16_t ramBufferMaxLen; + uint8_t *pRamBuffer; +} ramBufferDescriptor; + +rsError ramStorageGet(const ramBufferDescriptor *pBuffer, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength); + +rsError ramStorageSet(ramBufferDescriptor *pBuffer, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength); + +rsError ramStorageDelete(ramBufferDescriptor *pBuffer, uint16_t aKey, int aIndex); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // RAM_STORAGE_H \ No newline at end of file