[EFR32] Rework NVM3 instances and refactor our KVS implementation to use nvm3 (#16877)
* Merge chip_nvm3 section into silabs default nvm3 section. Rework the efr32Config nvm3 driver, tweaks to linkerfile for the nvm3 section
* Refactore efr32 kvs implementation to use silabs nvm3 driver
* Fix some return codes for KVS
* Update ldscript for mg24. Add verifications in kvs implementation. Regroup nvm3 and kvs init. Set ble default connection params
* Delay keymap commit to nvm, Build argument for kvs entry count, Clean up
* Add build option in efr32_sdk.gni and detail in build script
* add info in read me
* Fix typo, add NVM to wordlist
* undo unwanted change to zap and pigweed submodule.
* remove mv command
diff --git a/src/platform/EFR32/BLEManagerImpl.cpp b/src/platform/EFR32/BLEManagerImpl.cpp
index bbbf591..13805fe 100644
--- a/src/platform/EFR32/BLEManagerImpl.cpp
+++ b/src/platform/EFR32/BLEManagerImpl.cpp
@@ -76,6 +76,14 @@
#define BLE_CONFIG_RF_PATH_GAIN_TX (0)
#define BLE_CONFIG_RF_PATH_GAIN_RX (0)
+// Default Connection parameters
+#define BLE_CONFIG_MIN_INTERVAL (16) // Time = Value x 1.25 ms = 30ms
+#define BLE_CONFIG_MAX_INTERVAL (80) // Time = Value x 1.25 ms = 100ms
+#define BLE_CONFIG_LATENCY (0)
+#define BLE_CONFIG_TIMEOUT (100) // Time = Value x 10 ms = 1s
+#define BLE_CONFIG_MIN_CE_LENGTH (0) // Leave to min value
+#define BLE_CONFIG_MAX_CE_LENGTH (0xFFFF) // Leave to max value
+
TimerHandle_t sbleAdvTimeoutTimer; // FreeRTOS sw timer.
/* Bluetooth stack configuration parameters (see "UG136: Silicon Labs Bluetooth C Application Developer's Guide" for
@@ -249,6 +257,8 @@
RAIL_GetVersion(&railVer, true);
ChipLogProgress(DeviceLayer, "RAIL version:, v%d.%d.%d-b%d", railVer.major, railVer.minor, railVer.rev,
railVer.build);
+ sl_bt_connection_set_default_parameters(BLE_CONFIG_MIN_INTERVAL, BLE_CONFIG_MAX_INTERVAL, BLE_CONFIG_LATENCY,
+ BLE_CONFIG_TIMEOUT, BLE_CONFIG_MIN_CE_LENGTH, BLE_CONFIG_MAX_CE_LENGTH);
}
break;
@@ -257,7 +267,7 @@
}
break;
case sl_bt_evt_connection_parameters_id: {
- // ChipLogProgress(DeviceLayer, "Connection parameter ID received. Nothing to do");
+ // ChipLogProgress(DeviceLayer, "Connection parameter ID received");
}
break;
case sl_bt_evt_connection_phy_status_id: {
@@ -307,6 +317,11 @@
}
break;
+ case sl_bt_evt_connection_remote_used_features_id: {
+ // ChipLogProgress(DeviceLayer, "link layer features supported by the remote device");
+ }
+ break;
+
default:
ChipLogProgress(DeviceLayer, "evt_UNKNOWN id = %08" PRIx32, SL_BT_MSG_ID(bluetooth_evt->header));
break;
diff --git a/src/platform/EFR32/CHIPDevicePlatformConfig.h b/src/platform/EFR32/CHIPDevicePlatformConfig.h
index ba22bed..0303a7b 100644
--- a/src/platform/EFR32/CHIPDevicePlatformConfig.h
+++ b/src/platform/EFR32/CHIPDevicePlatformConfig.h
@@ -56,51 +56,6 @@
// These are configuration options that are unique to the EFR32 platform.
// These can be overridden by the application as needed.
-// -------------- EFR32 NVM3 Storage Configuration -------------
-
-/**
- * @def CHIP_DEVICE_CONFIG_NVM3_MAX_NUM_OBJECTS
- *
- * @brief
- * Configures the size of the nvm3 cache and should be set >= the
- * maximum number of Chip Config objects, e.g...
- * Factory configs[5], System configs[23], Counter configs[32] + margin[4] = 64.
- *
- */
-#ifndef CHIP_DEVICE_CONFIG_NVM3_MAX_NUM_OBJECTS
-#define CHIP_DEVICE_CONFIG_NVM3_MAX_NUM_OBJECTS 64
-#endif // CHIP_DEVICE_CONFIG_NVM3_MAX_NUM_OBJECTS
-
-/**
- * @def CHIP_DEVICE_CONFIG_NVM3_MAX_OBJECT_SIZE
- *
- * @brief
- * This determines the max size for any Chip nvm3 object
- * (e.g. for Config 'string' or 'binary' types).
- */
-#ifndef CHIP_DEVICE_CONFIG_NVM3_MAX_OBJECT_SIZE
-#define CHIP_DEVICE_CONFIG_NVM3_MAX_OBJECT_SIZE 1000
-#endif // CHIP_DEVICE_CONFIG_NVM3_MAX_OBJECT_SIZE
-
-/**
- * @def CHIP_DEVICE_CONFIG_NVM3_NUM_FLASH_PAGES_FOR_STORAGE
- *
- * @brief
- * This determines the Flash size used for nvm3 data storage:-
- * (assuming 2k Flash page size) => Total Flash size for nvm3: 8 * 2k = 16k
- * The total size should allow sufficient margin for wear-levelling and
- * repacking.
- *
- * MG21 and MG 24 a 8k per page. 3 * 8k = 24k
- */
-#ifndef CHIP_DEVICE_CONFIG_NVM3_NUM_FLASH_PAGES_FOR_STORAGE
-#if defined(EFR32MG21) || defined(EFR32MG24)
-#define CHIP_DEVICE_CONFIG_NVM3_NUM_FLASH_PAGES_FOR_STORAGE 3
-#else
-#define CHIP_DEVICE_CONFIG_NVM3_NUM_FLASH_PAGES_FOR_STORAGE 8
-#endif
-#endif // CHIP_DEVICE_CONFIG_NVM3_NUM_FLASH_PAGES_FOR_STORAGE
-
// ========== Platform-specific Configuration Overrides =========
#ifndef CHIP_DEVICE_CONFIG_BLE_LL_TASK_PRIORITY
diff --git a/src/platform/EFR32/ConfigurationManagerImpl.cpp b/src/platform/EFR32/ConfigurationManagerImpl.cpp
index b5a2664..9c370bf 100644
--- a/src/platform/EFR32/ConfigurationManagerImpl.cpp
+++ b/src/platform/EFR32/ConfigurationManagerImpl.cpp
@@ -284,9 +284,7 @@
#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
-#if CHIP_KVS_AVAILABLE
PersistedStorage::KeyValueStoreMgrImpl().ErasePartition();
-#endif // CHIP_KVS_AVAILABLE
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
ChipLogProgress(DeviceLayer, "Clearing WiFi provision");
diff --git a/src/platform/EFR32/ConfigurationManagerImpl.h b/src/platform/EFR32/ConfigurationManagerImpl.h
index 7a157cc..baa3e58 100644
--- a/src/platform/EFR32/ConfigurationManagerImpl.h
+++ b/src/platform/EFR32/ConfigurationManagerImpl.h
@@ -26,7 +26,7 @@
#include <platform/internal/GenericConfigurationManagerImpl.h>
-#include "EFR32Config.h"
+#include <platform/EFR32/EFR32Config.h>
namespace chip {
namespace DeviceLayer {
diff --git a/src/platform/EFR32/EFR32Config.cpp b/src/platform/EFR32/EFR32Config.cpp
index da1734e..f78797c 100644
--- a/src/platform/EFR32/EFR32Config.cpp
+++ b/src/platform/EFR32/EFR32Config.cpp
@@ -31,55 +31,38 @@
#include "FreeRTOS.h"
#include "nvm3.h"
+#include "nvm3_default.h"
#include "nvm3_hal_flash.h"
+// Substitute the GSDK weak nvm3_lockBegin and nvm3_lockEnd
+// for an application controlled re-entrance protection
+#define EFR32_SEM_TIMEOUT_ms 5
+static SemaphoreHandle_t nvm3_Sem;
+static StaticSemaphore_t nvm3_SemStruct;
+
+void nvm3_lockBegin(void)
+{
+ VerifyOrDie(nvm3_Sem != NULL);
+ xSemaphoreTake(nvm3_Sem, EFR32_SEM_TIMEOUT_ms);
+}
+
+void nvm3_lockEnd(void)
+{
+ VerifyOrDie(nvm3_Sem != NULL);
+ xSemaphoreGive(nvm3_Sem);
+}
+
namespace chip {
namespace DeviceLayer {
namespace Internal {
-// Two macros are provided to support the creation of the Silicon Labs NVM3 area and
-// initialization data- NVM3_DEFINE_SECTION_STATIC_DATA() and NVM3_DEFINE_SECTION_INIT_DATA().
-// A linker section called 'name'_section is defined by NVM3_DEFINE_SECTION_STATIC_DATA().
-// The NVM3 area is placed at the top of the device FLASH section by the linker
-// script file: chip-efr32-bringup-MG12P.ld. An error is returned
-// by nvm3_open() on alignment or size violation.
-
-// Local version of SDK macro (avoids uninitialized var compile error).
-#define CHIP_NVM3_DEFINE_SECTION_STATIC_DATA(name, nvmSize, cacheSize) \
- static nvm3_CacheEntry_t name##_cache[cacheSize]; \
- static uint8_t name##_nvm[nvmSize] SL_ATTRIBUTE_SECTION(STRINGIZE(name##_section))
-
-// Local version of SDK macro (allows CHIP to configure the maximum nvm3 object size and headroom).
-#define CHIP_NVM3_DEFINE_SECTION_INIT_DATA(name, maxObjectSize, repackHeadroom) \
- static nvm3_Init_t name = { \
- (nvm3_HalPtr_t) name##_nvm, \
- sizeof(name##_nvm), \
- name##_cache, \
- sizeof(name##_cache) / sizeof(nvm3_CacheEntry_t), \
- maxObjectSize, \
- repackHeadroom, \
- &nvm3_halFlashHandle, \
- }
-
-#define CHIP_NVM3_REPACK_HEADROOM 64 // Threshold for User non-forced nvm3 flash repacking.
-
-#define EFR32_SEM_TIMEOUT_ms 5
-
-static nvm3_Handle_t handle;
-static SemaphoreHandle_t nvm3_Sem;
-static StaticSemaphore_t nvm3_SemStruct;
-
-// Declare NVM3 data area and cache.
-
-CHIP_NVM3_DEFINE_SECTION_STATIC_DATA(chipNvm3, CHIP_DEVICE_CONFIG_NVM3_NUM_FLASH_PAGES_FOR_STORAGE * FLASH_PAGE_SIZE,
- CHIP_DEVICE_CONFIG_NVM3_MAX_NUM_OBJECTS);
-
-CHIP_NVM3_DEFINE_SECTION_INIT_DATA(chipNvm3, CHIP_DEVICE_CONFIG_NVM3_MAX_OBJECT_SIZE, CHIP_NVM3_REPACK_HEADROOM);
+// Matter NVM3 space is placed in the silabs default nvm3 section shared with other stack.
+// 'kMatterNvm3KeyDomain' identify the matter nvm3 domain.
+// The NVM3 default section is placed at end of Flash minus 1 page byt the linker file
+// See examples/platform/efr32/ldscripts/efr32mgXX.ld
CHIP_ERROR EFR32Config::Init()
{
- CHIP_ERROR err;
-
nvm3_Sem = xSemaphoreCreateBinaryStatic(&nvm3_SemStruct);
if (nvm3_Sem == NULL)
@@ -87,12 +70,13 @@
return CHIP_ERROR_NO_MEMORY;
}
- err = MapNvm3Error(nvm3_open(&handle, &chipNvm3));
- SuccessOrExit(err);
+ return MapNvm3Error(nvm3_open(nvm3_defaultHandle, nvm3_defaultInit));
+}
-exit:
- OnExit();
- return err;
+void EFR32Config::DeInit()
+{
+ vSemaphoreDelete(nvm3_Sem);
+ nvm3_close(nvm3_defaultHandle);
}
CHIP_ERROR EFR32Config::ReadConfigValue(Key key, bool & val)
@@ -102,28 +86,18 @@
size_t dataLen;
bool tmpVal;
- if (pdFALSE == xSemaphoreTake(nvm3_Sem, pdMS_TO_TICKS(EFR32_SEM_TIMEOUT_ms)))
- {
- err = CHIP_ERROR_TIMEOUT;
- SuccessOrExit(err);
- }
-
VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
- err = MapNvm3Error(nvm3_open(&handle, &chipNvm3));
- SuccessOrExit(err);
-
// Get nvm3 object info.
- err = MapNvm3Error(nvm3_getObjectInfo(&handle, key, &objectType, &dataLen));
+ err = MapNvm3Error(nvm3_getObjectInfo(nvm3_defaultHandle, key, &objectType, &dataLen));
SuccessOrExit(err);
// Read nvm3 bytes into tmp.
- err = MapNvm3Error(nvm3_readData(&handle, key, &tmpVal, dataLen));
+ err = MapNvm3Error(nvm3_readData(nvm3_defaultHandle, key, &tmpVal, dataLen));
SuccessOrExit(err);
val = tmpVal;
exit:
- OnExit();
return err;
}
@@ -134,27 +108,18 @@
size_t dataLen;
uint32_t tmpVal;
- if (pdFALSE == xSemaphoreTake(nvm3_Sem, pdMS_TO_TICKS(EFR32_SEM_TIMEOUT_ms)))
- {
- err = CHIP_ERROR_TIMEOUT;
- SuccessOrExit(err);
- }
VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
- err = MapNvm3Error(nvm3_open(&handle, &chipNvm3));
- SuccessOrExit(err);
-
// Get nvm3 object info.
- err = MapNvm3Error(nvm3_getObjectInfo(&handle, key, &objectType, &dataLen));
+ err = MapNvm3Error(nvm3_getObjectInfo(nvm3_defaultHandle, key, &objectType, &dataLen));
SuccessOrExit(err);
// Read nvm3 bytes into tmp.
- err = MapNvm3Error(nvm3_readData(&handle, key, &tmpVal, dataLen));
+ err = MapNvm3Error(nvm3_readData(nvm3_defaultHandle, key, &tmpVal, dataLen));
SuccessOrExit(err);
val = tmpVal;
exit:
- OnExit();
return err;
}
@@ -165,28 +130,18 @@
size_t dataLen;
uint64_t tmpVal;
- if (pdFALSE == xSemaphoreTake(nvm3_Sem, pdMS_TO_TICKS(EFR32_SEM_TIMEOUT_ms)))
- {
- err = CHIP_ERROR_TIMEOUT;
- SuccessOrExit(err);
- }
-
VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
- err = MapNvm3Error(nvm3_open(&handle, &chipNvm3));
- SuccessOrExit(err);
-
// Get nvm3 object info.
- err = MapNvm3Error(nvm3_getObjectInfo(&handle, key, &objectType, &dataLen));
+ err = MapNvm3Error(nvm3_getObjectInfo(nvm3_defaultHandle, key, &objectType, &dataLen));
SuccessOrExit(err);
// Read nvm3 bytes into tmp.
- err = MapNvm3Error(nvm3_readData(&handle, key, &tmpVal, dataLen));
+ err = MapNvm3Error(nvm3_readData(nvm3_defaultHandle, key, &tmpVal, dataLen));
SuccessOrExit(err);
val = tmpVal;
exit:
- OnExit();
return err;
}
@@ -198,19 +153,10 @@
outLen = 0;
- if (pdFALSE == xSemaphoreTake(nvm3_Sem, pdMS_TO_TICKS(EFR32_SEM_TIMEOUT_ms)))
- {
- err = CHIP_ERROR_TIMEOUT;
- SuccessOrExit(err);
- }
-
VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
- err = MapNvm3Error(nvm3_open(&handle, &chipNvm3));
- SuccessOrExit(err);
-
// Get nvm3 object info.
- err = MapNvm3Error(nvm3_getObjectInfo(&handle, key, &objectType, &dataLen));
+ err = MapNvm3Error(nvm3_getObjectInfo(nvm3_defaultHandle, key, &objectType, &dataLen));
SuccessOrExit(err);
VerifyOrExit(dataLen > 0, err = CHIP_ERROR_INVALID_STRING_LENGTH);
@@ -221,7 +167,7 @@
// terminator char).
VerifyOrExit((bufSize > dataLen), err = CHIP_ERROR_BUFFER_TOO_SMALL);
- err = MapNvm3Error(nvm3_readData(&handle, key, buf, dataLen));
+ err = MapNvm3Error(nvm3_readData(nvm3_defaultHandle, key, buf, dataLen));
SuccessOrExit(err);
outLen = ((dataLen == 1) && (buf[0] == 0)) ? 0 : dataLen;
@@ -237,7 +183,7 @@
{
// Read the first byte of the nvm3 string into a tmp var.
char firstByte;
- err = MapNvm3Error(nvm3_readData(&handle, key, &firstByte, 1));
+ err = MapNvm3Error(nvm3_readData(nvm3_defaultHandle, key, &firstByte, 1));
SuccessOrExit(err);
outLen = (firstByte == 0) ? 0 : dataLen;
@@ -245,7 +191,6 @@
}
exit:
- OnExit();
return err;
}
@@ -256,19 +201,10 @@
size_t dataLen;
outLen = 0;
- if (pdFALSE == xSemaphoreTake(nvm3_Sem, pdMS_TO_TICKS(EFR32_SEM_TIMEOUT_ms)))
- {
- err = CHIP_ERROR_TIMEOUT;
- SuccessOrExit(err);
- }
-
VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
- err = MapNvm3Error(nvm3_open(&handle, &chipNvm3));
- SuccessOrExit(err);
-
// Get nvm3 object info.
- err = MapNvm3Error(nvm3_getObjectInfo(&handle, key, &objectType, &dataLen));
+ err = MapNvm3Error(nvm3_getObjectInfo(nvm3_defaultHandle, key, &objectType, &dataLen));
SuccessOrExit(err);
VerifyOrExit(dataLen > 0, err = CHIP_ERROR_INVALID_STRING_LENGTH);
@@ -278,14 +214,51 @@
// enough to take the data.
VerifyOrExit((bufSize >= dataLen), err = CHIP_ERROR_BUFFER_TOO_SMALL);
- err = MapNvm3Error(nvm3_readData(&handle, key, buf, dataLen));
+ err = MapNvm3Error(nvm3_readData(nvm3_defaultHandle, key, buf, dataLen));
SuccessOrExit(err);
+
+ outLen = dataLen;
}
- outLen = dataLen;
-
exit:
- OnExit();
+ return err;
+}
+
+CHIP_ERROR EFR32Config::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen, size_t offset)
+{
+ CHIP_ERROR err;
+ uint32_t objectType;
+ size_t dataLen;
+
+ outLen = 0;
+ VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
+
+ // Get nvm3 object info.
+ err = MapNvm3Error(nvm3_getObjectInfo(nvm3_defaultHandle, key, &objectType, &dataLen));
+ SuccessOrExit(err);
+ VerifyOrExit(dataLen > 0, err = CHIP_ERROR_INVALID_STRING_LENGTH);
+
+ if (buf != NULL)
+ {
+ // Read nvm3 bytes directly into output buffer- check buffer is long enough to take the data
+ // else read what we can but return CHIP_ERROR_BUFFER_TOO_SMALL.
+ size_t maxReadLength = dataLen - offset;
+ if (bufSize >= maxReadLength)
+ {
+ err = MapNvm3Error(nvm3_readPartialData(nvm3_defaultHandle, key, buf, offset, maxReadLength));
+ SuccessOrExit(err);
+ outLen = maxReadLength;
+ }
+ else
+ {
+ err = MapNvm3Error(nvm3_readPartialData(nvm3_defaultHandle, key, buf, offset, bufSize));
+ SuccessOrExit(err);
+ // read was successful, but we did not read all the data from the object.
+ err = CHIP_ERROR_BUFFER_TOO_SMALL;
+ outLen = bufSize;
+ }
+ }
+exit:
return err;
}
@@ -293,26 +266,16 @@
{
CHIP_ERROR err;
uint32_t tmpVal;
- Key key = kMinConfigKey_ChipCounter + counterIdx;
-
- if (pdFALSE == xSemaphoreTake(nvm3_Sem, pdMS_TO_TICKS(EFR32_SEM_TIMEOUT_ms)))
- {
- err = CHIP_ERROR_TIMEOUT;
- SuccessOrExit(err);
- }
+ Key key = kMinConfigKey_MatterCounter + counterIdx;
VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
- err = MapNvm3Error(nvm3_open(&handle, &chipNvm3));
- SuccessOrExit(err);
-
// Read bytes into tmp.
- err = MapNvm3Error(nvm3_readCounter(&handle, key, &tmpVal));
+ err = MapNvm3Error(nvm3_readCounter(nvm3_defaultHandle, key, &tmpVal));
SuccessOrExit(err);
val = tmpVal;
exit:
- OnExit();
return err;
}
@@ -320,22 +283,12 @@
{
CHIP_ERROR err;
- if (pdFALSE == xSemaphoreTake(nvm3_Sem, pdMS_TO_TICKS(EFR32_SEM_TIMEOUT_ms)))
- {
- err = CHIP_ERROR_TIMEOUT;
- SuccessOrExit(err);
- }
-
VerifyOrExit(ValidConfigKey(key), err = CHIP_ERROR_INVALID_ARGUMENT); // Verify key id.
- err = MapNvm3Error(nvm3_open(&handle, &chipNvm3));
- SuccessOrExit(err);
-
- err = MapNvm3Error(nvm3_writeData(&handle, key, &val, sizeof(val)));
+ err = MapNvm3Error(nvm3_writeData(nvm3_defaultHandle, key, &val, sizeof(val)));
SuccessOrExit(err);
exit:
- OnExit();
return err;
}
@@ -343,22 +296,12 @@
{
CHIP_ERROR err;
- if (pdFALSE == xSemaphoreTake(nvm3_Sem, pdMS_TO_TICKS(EFR32_SEM_TIMEOUT_ms)))
- {
- err = CHIP_ERROR_TIMEOUT;
- SuccessOrExit(err);
- }
-
VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
- err = MapNvm3Error(nvm3_open(&handle, &chipNvm3));
- SuccessOrExit(err);
-
- err = MapNvm3Error(nvm3_writeData(&handle, key, &val, sizeof(val)));
+ err = MapNvm3Error(nvm3_writeData(nvm3_defaultHandle, key, &val, sizeof(val)));
SuccessOrExit(err);
exit:
- OnExit();
return err;
}
@@ -366,22 +309,12 @@
{
CHIP_ERROR err;
- if (pdFALSE == xSemaphoreTake(nvm3_Sem, pdMS_TO_TICKS(EFR32_SEM_TIMEOUT_ms)))
- {
- err = CHIP_ERROR_TIMEOUT;
- SuccessOrExit(err);
- }
-
VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
- err = MapNvm3Error(nvm3_open(&handle, &chipNvm3));
- SuccessOrExit(err);
-
- err = MapNvm3Error(nvm3_writeData(&handle, key, &val, sizeof(val)));
+ err = MapNvm3Error(nvm3_writeData(nvm3_defaultHandle, key, &val, sizeof(val)));
SuccessOrExit(err);
exit:
- OnExit();
return err;
}
@@ -394,31 +327,21 @@
{
CHIP_ERROR err;
- if (pdFALSE == xSemaphoreTake(nvm3_Sem, pdMS_TO_TICKS(EFR32_SEM_TIMEOUT_ms)))
- {
- err = CHIP_ERROR_TIMEOUT;
- SuccessOrExit(err);
- }
-
VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
- err = MapNvm3Error(nvm3_open(&handle, &chipNvm3));
- SuccessOrExit(err);
-
if (str != NULL)
{
// Write the string to nvm3 without the terminator char (apart from
// empty strings where only the terminator char is stored in nvm3).
- err = MapNvm3Error(nvm3_writeData(&handle, key, str, (strLen > 0) ? strLen : 1));
+ err = MapNvm3Error(nvm3_writeData(nvm3_defaultHandle, key, str, (strLen > 0) ? strLen : 1));
SuccessOrExit(err);
}
else
{
- nvm3_deleteObject(&handle, key); // no error checking here.
+ nvm3_deleteObject(nvm3_defaultHandle, key); // no error checking here.
}
exit:
- OnExit();
return err;
}
@@ -426,57 +349,37 @@
{
CHIP_ERROR err;
- if (pdFALSE == xSemaphoreTake(nvm3_Sem, pdMS_TO_TICKS(EFR32_SEM_TIMEOUT_ms)))
- {
- err = CHIP_ERROR_TIMEOUT;
- SuccessOrExit(err);
- }
-
VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
- err = MapNvm3Error(nvm3_open(&handle, &chipNvm3));
- SuccessOrExit(err);
-
if (data != NULL)
{
if (dataLen > 0)
{
// Write the binary data to nvm3.
- err = MapNvm3Error(nvm3_writeData(&handle, key, data, dataLen));
+ err = MapNvm3Error(nvm3_writeData(nvm3_defaultHandle, key, data, dataLen));
SuccessOrExit(err);
}
}
else
{
- nvm3_deleteObject(&handle, key); // no error checking here.
+ nvm3_deleteObject(nvm3_defaultHandle, key); // no error checking here.
}
exit:
- OnExit();
return err;
}
CHIP_ERROR EFR32Config::WriteConfigValueCounter(uint8_t counterIdx, uint32_t val)
{
CHIP_ERROR err;
- Key key = kMinConfigKey_ChipCounter + counterIdx;
-
- if (pdFALSE == xSemaphoreTake(nvm3_Sem, pdMS_TO_TICKS(EFR32_SEM_TIMEOUT_ms)))
- {
- err = CHIP_ERROR_TIMEOUT;
- SuccessOrExit(err);
- }
+ Key key = kMinConfigKey_MatterCounter + counterIdx;
VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
- err = MapNvm3Error(nvm3_open(&handle, &chipNvm3));
- SuccessOrExit(err);
-
- err = MapNvm3Error(nvm3_writeCounter(&handle, key, val));
+ err = MapNvm3Error(nvm3_writeCounter(nvm3_defaultHandle, key, val));
SuccessOrExit(err);
exit:
- OnExit();
return err;
}
@@ -484,44 +387,21 @@
{
CHIP_ERROR err;
- if (pdFALSE == xSemaphoreTake(nvm3_Sem, pdMS_TO_TICKS(EFR32_SEM_TIMEOUT_ms)))
- {
- err = CHIP_ERROR_TIMEOUT;
- SuccessOrExit(err);
- }
-
- err = MapNvm3Error(nvm3_open(&handle, &chipNvm3));
- SuccessOrExit(err);
-
// Delete the nvm3 object with the given key id.
- err = MapNvm3Error(nvm3_deleteObject(&handle, key));
+ err = MapNvm3Error(nvm3_deleteObject(nvm3_defaultHandle, key));
SuccessOrExit(err);
exit:
- OnExit();
return err;
}
bool EFR32Config::ConfigValueExists(Key key)
{
- CHIP_ERROR err;
uint32_t objectType;
size_t dataLen;
- if (pdFALSE == xSemaphoreTake(nvm3_Sem, pdMS_TO_TICKS(EFR32_SEM_TIMEOUT_ms)))
- {
- err = CHIP_ERROR_TIMEOUT;
- SuccessOrExit(err);
- }
-
- err = MapNvm3Error(nvm3_open(&handle, &chipNvm3));
- SuccessOrExit(err);
-
// Find object with key id.
- err = MapNvm3Error(nvm3_getObjectInfo(&handle, key, &objectType, &dataLen));
-
-exit:
- OnExit();
+ CHIP_ERROR err = MapNvm3Error(nvm3_getObjectInfo(nvm3_defaultHandle, key, &objectType, &dataLen));
return (err == CHIP_NO_ERROR);
}
@@ -533,15 +413,14 @@
CHIP_ERROR err;
// Iterate over all the CHIP Config nvm3 records and delete each one...
- err = ForEachRecord(kMinConfigKey_ChipConfig, kMaxConfigKey_ChipConfig, false,
+ err = ForEachRecord(kMinConfigKey_MatterConfig, kMaxConfigKey_MatterConfig, false,
[](const Key & nvm3Key, const size_t & length) -> CHIP_ERROR {
CHIP_ERROR err2;
// Delete the nvm3 object with the given key id.
- err2 = MapNvm3Error(nvm3_deleteObject(&handle, nvm3Key));
+ err2 = ClearConfigValue(nvm3Key);
SuccessOrExit(err2);
exit:
- nvm3_close(&handle);
return err2;
});
@@ -580,11 +459,6 @@
// Invokes the callers CB function when appropriate.
CHIP_ERROR err = CHIP_NO_ERROR;
- if (pdFALSE == xSemaphoreTake(nvm3_Sem, pdMS_TO_TICKS(EFR32_SEM_TIMEOUT_ms)))
- {
- err = CHIP_ERROR_TIMEOUT;
- SuccessOrExit(err);
- }
for (Key nvm3Key = firstNvm3Key; nvm3Key <= lastNvm3Key; ++nvm3Key)
{
@@ -592,12 +466,8 @@
uint32_t objectType;
size_t dataLen;
- // Open nvm3 handle for reading on each iteration.
- err = MapNvm3Error(nvm3_open(&handle, &chipNvm3));
- SuccessOrExit(err);
-
// Find nvm3 object with current nvm3 iteration key.
- nvm3Res = nvm3_getObjectInfo(&handle, nvm3Key, &objectType, &dataLen);
+ nvm3Res = nvm3_getObjectInfo(nvm3_defaultHandle, nvm3Key, &objectType, &dataLen);
switch (nvm3Res)
{
case ECODE_NVM3_OK:
@@ -624,16 +494,14 @@
SuccessOrExit(err);
}
-exit:
- OnExit();
+exit:;
return err;
}
bool EFR32Config::ValidConfigKey(Key key)
{
- // Returns true if the key is in the valid CHIP Config nvm3 key range.
-
- if ((key >= kMinConfigKey_ChipFactory) && (key <= kMaxConfigKey_ChipCounter))
+ // Returns true if the key is in the valid Matter Config nvm3 key range.
+ if ((key >= kMinConfigKey_MatterFactory) && (key <= kMaxConfigKey_MatterKvs))
{
return true;
}
@@ -652,13 +520,7 @@
// Repack nvm3 flash if nvm3 space < headroom threshold.
// Note- checking periodically during idle periods should prevent
// forced repack events on any write operation.
- nvm3_repack(&handle);
-}
-
-void EFR32Config::OnExit()
-{
- xSemaphoreGive(nvm3_Sem);
- nvm3_close(&handle);
+ nvm3_repack(nvm3_defaultHandle);
}
} // namespace Internal
diff --git a/src/platform/EFR32/EFR32Config.h b/src/platform/EFR32/EFR32Config.h
index 638dd53..6b8bf52 100644
--- a/src/platform/EFR32/EFR32Config.h
+++ b/src/platform/EFR32/EFR32Config.h
@@ -31,6 +31,13 @@
#include "nvm3.h"
#include "nvm3_hal_flash.h"
+#ifndef KVS_MAX_ENTRIES
+#define KVS_MAX_ENTRIES 75 // Available key slot count for Kvs Key mapping.
+#endif
+
+static_assert((KVS_MAX_ENTRIES <= 255), "Implementation supports up to 255 Kvs entries");
+static_assert((KVS_MAX_ENTRIES >= 30), "Mininimal Kvs entries requirement is not met");
+
namespace chip {
namespace DeviceLayer {
namespace Internal {
@@ -46,78 +53,94 @@
* the template class (e.g. the ReadConfigValue() method).
*/
-// Silabs NVM3 objects use a 20-bit number, however User key range is
-// restricted to 16 bits i.e. 0x0000 -> 0xFFFF.
-// e.g. key = 0xA201
+// Silabs NVM3 objects use a 20-bit number,
+// NVM3 Key 19:16 Stack region
+// NVM3 Key 15:0 Available NVM3 keys 0x0000 -> 0xFFFF.
+// e.g. key = 0x0AA201
+// '0A' = Matter nvm3 region
// 'A2' = the nv group base offest (Factory, Config or Counter)
// '01' = the id offset inside the group.
+constexpr uint32_t kMatterNvm3KeyDomain = 0x0A0000U;
constexpr inline uint32_t EFR32ConfigKey(uint8_t keyBaseOffset, uint8_t id)
{
- return static_cast<uint32_t>(keyBaseOffset) << 8 | id;
+ return kMatterNvm3KeyDomain | static_cast<uint32_t>(keyBaseOffset) << 8 | id;
}
class EFR32Config
{
public:
-public:
// Definitions for Silicon Labs EFR32 NVM3 driver:-
using Key = uint32_t;
// NVM3 key base offsets used by the CHIP Device Layer.
- static constexpr uint8_t kChipFactory_KeyBase =
- 0xA2; // Persistent config values set at manufacturing time. Retained during factory reset.
- static constexpr uint8_t kChipConfig_KeyBase = 0xA3; // Persistent config values set at runtime. Cleared during factory reset.
- static constexpr uint8_t kChipCounter_KeyBase =
- 0xA4; // Persistent counter values set at runtime. Retained during factory reset.
+ // Persistent config values set at manufacturing time. Retained during factory reset.
+ static constexpr uint8_t kMatterFactory_KeyBase = 0xA2;
+ // Persistent config values set at runtime. Cleared during factory reset.
+ static constexpr uint8_t kMatterConfig_KeyBase = 0xA3;
+ // Persistent counter values set at runtime. Retained during factory reset.
+ static constexpr uint8_t kMatterCounter_KeyBase = 0xA4;
+ // Persistent config values set at runtime. Cleared during factory reset.
+ static constexpr uint8_t kMatterKvs_KeyBase = 0xA5;
// Key definitions for well-known configuration values.
// Factory config keys
- static constexpr Key kConfigKey_SerialNum = EFR32ConfigKey(kChipFactory_KeyBase, 0x00);
- static constexpr Key kConfigKey_MfrDeviceId = EFR32ConfigKey(kChipFactory_KeyBase, 0x01);
- static constexpr Key kConfigKey_MfrDeviceCert = EFR32ConfigKey(kChipFactory_KeyBase, 0x02);
- static constexpr Key kConfigKey_MfrDevicePrivateKey = EFR32ConfigKey(kChipFactory_KeyBase, 0x03);
- static constexpr Key kConfigKey_ManufacturingDate = EFR32ConfigKey(kChipFactory_KeyBase, 0x04);
- static constexpr Key kConfigKey_SetupPinCode = EFR32ConfigKey(kChipFactory_KeyBase, 0x05);
- static constexpr Key kConfigKey_MfrDeviceICACerts = EFR32ConfigKey(kChipFactory_KeyBase, 0x06);
- static constexpr Key kConfigKey_SetupDiscriminator = EFR32ConfigKey(kChipFactory_KeyBase, 0x07);
- static constexpr Key kConfigKey_Spake2pIterationCount = EFR32ConfigKey(kChipFactory_KeyBase, 0x08);
- static constexpr Key kConfigKey_Spake2pSalt = EFR32ConfigKey(kChipFactory_KeyBase, 0x09);
- static constexpr Key kConfigKey_Spake2pVerifier = EFR32ConfigKey(kChipFactory_KeyBase, 0x0A);
- // CHIP Config Keys
- static constexpr Key kConfigKey_FabricId = EFR32ConfigKey(kChipConfig_KeyBase, 0x00);
- static constexpr Key kConfigKey_ServiceConfig = EFR32ConfigKey(kChipConfig_KeyBase, 0x01);
- static constexpr Key kConfigKey_PairedAccountId = EFR32ConfigKey(kChipConfig_KeyBase, 0x02);
- static constexpr Key kConfigKey_ServiceId = EFR32ConfigKey(kChipConfig_KeyBase, 0x03);
- static constexpr Key kConfigKey_FabricSecret = EFR32ConfigKey(kChipConfig_KeyBase, 0x04);
- static constexpr Key kConfigKey_LastUsedEpochKeyId = EFR32ConfigKey(kChipConfig_KeyBase, 0x05);
- static constexpr Key kConfigKey_FailSafeArmed = EFR32ConfigKey(kChipConfig_KeyBase, 0x06);
- static constexpr Key kConfigKey_GroupKey = EFR32ConfigKey(kChipConfig_KeyBase, 0x07);
- static constexpr Key kConfigKey_HardwareVersion = EFR32ConfigKey(kChipConfig_KeyBase, 0x08);
- static constexpr Key kConfigKey_RegulatoryLocation = EFR32ConfigKey(kChipConfig_KeyBase, 0x09);
- static constexpr Key kConfigKey_CountryCode = EFR32ConfigKey(kChipConfig_KeyBase, 0x0A);
- static constexpr Key kConfigKey_Breadcrumb = EFR32ConfigKey(kChipConfig_KeyBase, 0x0B);
- static constexpr Key kConfigKey_WiFiSSID = EFR32ConfigKey(kChipConfig_KeyBase, 0x0C);
- static constexpr Key kConfigKey_WiFiPSK = EFR32ConfigKey(kChipConfig_KeyBase, 0x0D);
- static constexpr Key kConfigKey_WiFiSEC = EFR32ConfigKey(kChipConfig_KeyBase, 0x0E);
- static constexpr Key kConfigKey_GroupKeyBase = EFR32ConfigKey(kChipConfig_KeyBase, 0x0F);
- static constexpr Key kConfigKey_GroupKeyMax = EFR32ConfigKey(kChipConfig_KeyBase, 0x1E); // Allows 16 Group Keys to be created.
- static constexpr Key kConfigKey_UniqueId = EFR32ConfigKey(kChipFactory_KeyBase, 0x1F);
+ static constexpr Key kConfigKey_SerialNum = EFR32ConfigKey(kMatterFactory_KeyBase, 0x00);
+ static constexpr Key kConfigKey_MfrDeviceId = EFR32ConfigKey(kMatterFactory_KeyBase, 0x01);
+ static constexpr Key kConfigKey_MfrDeviceCert = EFR32ConfigKey(kMatterFactory_KeyBase, 0x02);
+ static constexpr Key kConfigKey_MfrDevicePrivateKey = EFR32ConfigKey(kMatterFactory_KeyBase, 0x03);
+ static constexpr Key kConfigKey_ManufacturingDate = EFR32ConfigKey(kMatterFactory_KeyBase, 0x04);
+ static constexpr Key kConfigKey_SetupPinCode = EFR32ConfigKey(kMatterFactory_KeyBase, 0x05);
+ static constexpr Key kConfigKey_MfrDeviceICACerts = EFR32ConfigKey(kMatterFactory_KeyBase, 0x06);
+ static constexpr Key kConfigKey_SetupDiscriminator = EFR32ConfigKey(kMatterFactory_KeyBase, 0x07);
+ static constexpr Key kConfigKey_Spake2pIterationCount = EFR32ConfigKey(kMatterFactory_KeyBase, 0x08);
+ static constexpr Key kConfigKey_Spake2pSalt = EFR32ConfigKey(kMatterFactory_KeyBase, 0x09);
+ static constexpr Key kConfigKey_Spake2pVerifier = EFR32ConfigKey(kMatterFactory_KeyBase, 0x0A);
+ // Matter Config Keys
+ static constexpr Key kConfigKey_FabricId = EFR32ConfigKey(kMatterConfig_KeyBase, 0x00);
+ static constexpr Key kConfigKey_ServiceConfig = EFR32ConfigKey(kMatterConfig_KeyBase, 0x01);
+ static constexpr Key kConfigKey_PairedAccountId = EFR32ConfigKey(kMatterConfig_KeyBase, 0x02);
+ static constexpr Key kConfigKey_ServiceId = EFR32ConfigKey(kMatterConfig_KeyBase, 0x03);
+ static constexpr Key kConfigKey_FabricSecret = EFR32ConfigKey(kMatterConfig_KeyBase, 0x04);
+ static constexpr Key kConfigKey_LastUsedEpochKeyId = EFR32ConfigKey(kMatterConfig_KeyBase, 0x05);
+ static constexpr Key kConfigKey_FailSafeArmed = EFR32ConfigKey(kMatterConfig_KeyBase, 0x06);
+ static constexpr Key kConfigKey_GroupKey = EFR32ConfigKey(kMatterConfig_KeyBase, 0x07);
+ static constexpr Key kConfigKey_HardwareVersion = EFR32ConfigKey(kMatterConfig_KeyBase, 0x08);
+ static constexpr Key kConfigKey_RegulatoryLocation = EFR32ConfigKey(kMatterConfig_KeyBase, 0x09);
+ static constexpr Key kConfigKey_CountryCode = EFR32ConfigKey(kMatterConfig_KeyBase, 0x0A);
+ static constexpr Key kConfigKey_Breadcrumb = EFR32ConfigKey(kMatterConfig_KeyBase, 0x0B);
+ static constexpr Key kConfigKey_WiFiSSID = EFR32ConfigKey(kMatterConfig_KeyBase, 0x0C);
+ static constexpr Key kConfigKey_WiFiPSK = EFR32ConfigKey(kMatterConfig_KeyBase, 0x0D);
+ static constexpr Key kConfigKey_WiFiSEC = EFR32ConfigKey(kMatterConfig_KeyBase, 0x0E);
+ static constexpr Key kConfigKey_GroupKeyBase = EFR32ConfigKey(kMatterConfig_KeyBase, 0x0F);
+ static constexpr Key kConfigKey_GroupKeyMax =
+ EFR32ConfigKey(kMatterConfig_KeyBase, 0x1E); // Allows 16 Group Keys to be created.
+ static constexpr Key kConfigKey_UniqueId = EFR32ConfigKey(kMatterFactory_KeyBase, 0x1F);
- // CHIP Counter Keys
- static constexpr Key kConfigKey_BootCount = EFR32ConfigKey(kChipCounter_KeyBase, 0x00);
- static constexpr Key kConfigKey_TotalOperationalHours = EFR32ConfigKey(kChipCounter_KeyBase, 0x01);
+ // Matter Counter Keys
+ static constexpr Key kConfigKey_BootCount = EFR32ConfigKey(kMatterCounter_KeyBase, 0x00);
+ static constexpr Key kConfigKey_TotalOperationalHours = EFR32ConfigKey(kMatterCounter_KeyBase, 0x01);
+
+ // Matter KVS storage Keys
+ static constexpr Key kConfigKey_KvsStringKeyMap = EFR32ConfigKey(kMatterKvs_KeyBase, 0x00);
+ static constexpr Key kConfigKey_KvsFirstKeySlot = EFR32ConfigKey(kMatterKvs_KeyBase, 0x01);
+ static constexpr Key kConfigKey_KvsLastKeySlot = EFR32ConfigKey(kMatterKvs_KeyBase, KVS_MAX_ENTRIES);
// Set key id limits for each group.
- static constexpr Key kMinConfigKey_ChipFactory = EFR32ConfigKey(kChipFactory_KeyBase, 0x00);
- static constexpr Key kMaxConfigKey_ChipFactory = EFR32ConfigKey(kChipFactory_KeyBase, 0x0A);
- static constexpr Key kMinConfigKey_ChipConfig = EFR32ConfigKey(kChipConfig_KeyBase, 0x00);
- static constexpr Key kMaxConfigKey_ChipConfig = EFR32ConfigKey(kChipConfig_KeyBase, 0x1B);
- static constexpr Key kMinConfigKey_ChipCounter = EFR32ConfigKey(kChipCounter_KeyBase, 0x00);
- static constexpr Key kMaxConfigKey_ChipCounter =
- EFR32ConfigKey(kChipCounter_KeyBase, 0x1F); // Allows 32 Counters to be created.
+ static constexpr Key kMinConfigKey_MatterFactory = EFR32ConfigKey(kMatterFactory_KeyBase, 0x00);
+ static constexpr Key kMaxConfigKey_MatterFactory = EFR32ConfigKey(kMatterFactory_KeyBase, 0x0A);
+ static constexpr Key kMinConfigKey_MatterConfig = EFR32ConfigKey(kMatterConfig_KeyBase, 0x00);
+ static constexpr Key kMaxConfigKey_MatterConfig = EFR32ConfigKey(kMatterConfig_KeyBase, 0x1B);
+
+ // Allows 32 Counters to be created.
+ static constexpr Key kMinConfigKey_MatterCounter = EFR32ConfigKey(kMatterCounter_KeyBase, 0x00);
+ static constexpr Key kMaxConfigKey_MatterCounter = EFR32ConfigKey(kMatterCounter_KeyBase, 0x1F);
+
+ static constexpr Key kMinConfigKey_MatterKvs = EFR32ConfigKey(kMatterKvs_KeyBase, 0x00);
+ static constexpr Key kMaxConfigKey_MatterKvs = EFR32ConfigKey(kMatterKvs_KeyBase, 0xFF);
static CHIP_ERROR Init(void);
+ static void DeInit(void);
// Configuration methods used by the GenericConfigurationManagerImpl<> template.
static CHIP_ERROR ReadConfigValue(Key key, bool & val);
@@ -125,6 +148,7 @@
static CHIP_ERROR ReadConfigValue(Key key, uint64_t & val);
static CHIP_ERROR ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen);
static CHIP_ERROR ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen);
+ static CHIP_ERROR ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen, size_t offset);
static CHIP_ERROR ReadConfigValueCounter(uint8_t counterIdx, uint32_t & val);
static CHIP_ERROR WriteConfigValue(Key key, bool val);
static CHIP_ERROR WriteConfigValue(Key key, uint32_t val);
@@ -147,7 +171,6 @@
private:
static CHIP_ERROR MapNvm3Error(Ecode_t nvm3Res);
- static void OnExit(void);
};
} // namespace Internal
diff --git a/src/platform/EFR32/KeyValueStoreManagerImpl.cpp b/src/platform/EFR32/KeyValueStoreManagerImpl.cpp
index 28f6ea4..d46079f 100644
--- a/src/platform/EFR32/KeyValueStoreManagerImpl.cpp
+++ b/src/platform/EFR32/KeyValueStoreManagerImpl.cpp
@@ -21,122 +21,183 @@
* Platform-specific key value storage implementation for EFR32
*/
+#include <lib/support/CodeUtils.h>
+#include <platform/CHIPDeviceLayer.h>
+#include <platform/EFR32/EFR32Config.h>
#include <platform/KeyValueStoreManager.h>
+#include <stdio.h>
+#include <string.h>
-/* ignore GCC Wconversion warnings for pigweed */
-#if defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wconversion"
-#endif
+using namespace ::chip;
+using namespace ::chip::DeviceLayer::Internal;
-#include <pw_log/log.h>
-
-#if defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
+#define CONVERT_KEYMAP_INDEX_TO_NVM3KEY(index) (EFR32Config::kConfigKey_KvsFirstKeySlot + index)
+#define CONVERT_NVM3KEY_TO_KEYMAP_INDEX(nvm3Key) (nvm3Key - EFR32Config::kConfigKey_KvsFirstKeySlot)
namespace chip {
namespace DeviceLayer {
namespace PersistedStorage {
KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance;
+char mKvsStoredKeyString[KeyValueStoreManagerImpl::kMaxEntries][PersistentStorageDelegate::kKeyLengthMax + 1];
-#if defined(CHIP_KVS_AVAILABLE) && CHIP_KVS_AVAILABLE
+CHIP_ERROR KeyValueStoreManagerImpl::Init(void)
+{
+ CHIP_ERROR err;
+ err = EFR32Config::Init();
+ SuccessOrExit(err);
+
+ memset(mKvsStoredKeyString, 0, sizeof(mKvsStoredKeyString));
+ size_t outLen;
+ err = EFR32Config::ReadConfigValueBin(EFR32Config::kConfigKey_KvsStringKeyMap, reinterpret_cast<uint8_t *>(mKvsStoredKeyString),
+ sizeof(mKvsStoredKeyString), outLen);
+
+ if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) // Initial boot
+ {
+ err = CHIP_NO_ERROR;
+ }
+
+exit:
+ return err;
+}
+
+bool KeyValueStoreManagerImpl::IsValidKvsNvm3Key(uint32_t nvm3Key) const
+{
+ return ((EFR32Config::kConfigKey_KvsFirstKeySlot <= nvm3Key) && (nvm3Key <= EFR32Config::kConfigKey_KvsLastKeySlot));
+}
+
+CHIP_ERROR KeyValueStoreManagerImpl::MapKvsKeyToNvm3(const char * key, uint32_t & nvm3Key, bool isSlotNeeded) const
+{
+ CHIP_ERROR err;
+ uint8_t firstEmptyKeySlot = kMaxEntries;
+ for (uint8_t keyIndex = 0; keyIndex < kMaxEntries; keyIndex++)
+ {
+ if (strcmp(key, mKvsStoredKeyString[keyIndex]) == 0)
+ {
+ nvm3Key = CONVERT_KEYMAP_INDEX_TO_NVM3KEY(keyIndex);
+ VerifyOrDie(IsValidKvsNvm3Key(nvm3Key) == true);
+ return CHIP_NO_ERROR;
+ }
+
+ if (isSlotNeeded && (firstEmptyKeySlot == kMaxEntries) && (mKvsStoredKeyString[keyIndex][0] == 0))
+ {
+ firstEmptyKeySlot = keyIndex;
+ }
+ }
+
+ if (isSlotNeeded)
+ {
+ if (firstEmptyKeySlot != kMaxEntries)
+ {
+ nvm3Key = CONVERT_KEYMAP_INDEX_TO_NVM3KEY(firstEmptyKeySlot);
+ VerifyOrDie(IsValidKvsNvm3Key(nvm3Key) == true);
+ err = CHIP_NO_ERROR;
+ }
+ else
+ {
+ err = CHIP_ERROR_PERSISTED_STORAGE_FAILED;
+ }
+ }
+ else
+ {
+ err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
+ }
+ return err;
+}
+
+void KeyValueStoreManagerImpl::OnScheduledKeyMapSave(System::Layer * systemLayer, void * appState)
+{
+ EFR32Config::WriteConfigValueBin(EFR32Config::kConfigKey_KvsStringKeyMap,
+ reinterpret_cast<const uint8_t *>(mKvsStoredKeyString), sizeof(mKvsStoredKeyString));
+}
+
+void KeyValueStoreManagerImpl::ScheduleKeyMapSave(void)
+{
+ /*
+ During commissioning, the key map will be modified multiples times subsequently.
+ Commit the key map in nvm once it as stabilized.
+ */
+ SystemLayer().StartTimer(std::chrono::duration_cast<System::Clock::Timeout>(System::Clock::Seconds32(5)),
+ KeyValueStoreManagerImpl::OnScheduledKeyMapSave, NULL);
+}
CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size,
size_t offset_bytes) const
{
- assert(CHIP_KVS_AVAILABLE);
- auto status_and_size = mKvs.Get(key, std::span<std::byte>(reinterpret_cast<std::byte *>(value), value_size), offset_bytes);
+ VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(value != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(value != 0, CHIP_ERROR_INVALID_ARGUMENT);
+
+ uint32_t nvm3Key;
+ CHIP_ERROR err = MapKvsKeyToNvm3(key, nvm3Key);
+ VerifyOrReturnError(err == CHIP_NO_ERROR, err);
+
+ size_t outLen;
+ err = EFR32Config::ReadConfigValueBin(nvm3Key, reinterpret_cast<uint8_t *>(value), value_size, outLen, offset_bytes);
if (read_bytes_size)
{
- *read_bytes_size = status_and_size.size();
+ *read_bytes_size = outLen;
}
- switch (status_and_size.status().code())
- {
- case pw::OkStatus().code():
- return CHIP_NO_ERROR;
- case pw::Status::NotFound().code():
- return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
- case pw::Status::DataLoss().code():
- return CHIP_ERROR_INTEGRITY_CHECK_FAILED;
- case pw::Status::ResourceExhausted().code():
- return CHIP_ERROR_BUFFER_TOO_SMALL;
- case pw::Status::FailedPrecondition().code():
- return CHIP_ERROR_WELL_UNINITIALIZED;
- case pw::Status::InvalidArgument().code():
- return CHIP_ERROR_INVALID_ARGUMENT;
- default:
- break;
- }
- return CHIP_ERROR_INTERNAL; // Unexpected KVS status.
+
+ return err;
}
CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, size_t value_size)
{
- assert(CHIP_KVS_AVAILABLE);
- auto status = mKvs.Put(key, std::span<const std::byte>(reinterpret_cast<const std::byte *>(value), value_size));
- switch (status.code())
+ VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(value != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+ uint32_t nvm3Key;
+ CHIP_ERROR err = MapKvsKeyToNvm3(key, nvm3Key, /* isSlotNeeded */ true);
+ VerifyOrReturnError(err == CHIP_NO_ERROR, err);
+
+ err = EFR32Config::WriteConfigValueBin(nvm3Key, reinterpret_cast<const uint8_t *>(value), value_size);
+ if (err == CHIP_NO_ERROR)
{
- case pw::OkStatus().code():
- return CHIP_NO_ERROR;
- case pw::Status::DataLoss().code():
- return CHIP_ERROR_INTEGRITY_CHECK_FAILED;
- case pw::Status::ResourceExhausted().code():
- case pw::Status::AlreadyExists().code():
- return CHIP_ERROR_PERSISTED_STORAGE_FAILED;
- case pw::Status::FailedPrecondition().code():
- return CHIP_ERROR_WELL_UNINITIALIZED;
- case pw::Status::InvalidArgument().code():
- return CHIP_ERROR_INVALID_ARGUMENT;
- default:
- break;
+ uint32_t keyIndex = nvm3Key - EFR32Config::kConfigKey_KvsFirstKeySlot;
+ strncpy(mKvsStoredKeyString[keyIndex], key, sizeof(mKvsStoredKeyString[keyIndex]) - 1);
+ ScheduleKeyMapSave();
}
- return CHIP_ERROR_INTERNAL; // Unexpected KVS status.
+
+ return err;
}
CHIP_ERROR KeyValueStoreManagerImpl::_Delete(const char * key)
{
- assert(CHIP_KVS_AVAILABLE);
- auto status = mKvs.Delete(key);
- switch (status.code())
+ VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+ uint32_t nvm3Key;
+ CHIP_ERROR err = MapKvsKeyToNvm3(key, nvm3Key);
+ VerifyOrReturnError(err == CHIP_NO_ERROR, err);
+
+ err = EFR32Config::ClearConfigValue(nvm3Key);
+ if (err == CHIP_NO_ERROR)
{
- case pw::OkStatus().code():
- return CHIP_NO_ERROR;
- case pw::Status::NotFound().code():
- return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
- case pw::Status::DataLoss().code():
- return CHIP_ERROR_INTEGRITY_CHECK_FAILED;
- case pw::Status::ResourceExhausted().code():
- return CHIP_ERROR_PERSISTED_STORAGE_FAILED;
- case pw::Status::FailedPrecondition().code():
- return CHIP_ERROR_WELL_UNINITIALIZED;
- case pw::Status::InvalidArgument().code():
- return CHIP_ERROR_INVALID_ARGUMENT;
- default:
- break;
+ uint32_t keyIndex = CONVERT_NVM3KEY_TO_KEYMAP_INDEX(nvm3Key);
+ memset(mKvsStoredKeyString[keyIndex], 0, sizeof(mKvsStoredKeyString[keyIndex]));
+ ScheduleKeyMapSave();
}
- return CHIP_ERROR_INTERNAL; // Unexpected KVS status.
+
+ return err;
}
-CHIP_ERROR KeyValueStoreManagerImpl::ErasePartition()
+CHIP_ERROR KeyValueStoreManagerImpl::ErasePartition(void)
{
- assert(CHIP_KVS_AVAILABLE);
- auto status = mKvsPartition.Erase();
- switch (status.code())
+ // Iterate over all the Matter Kvs nvm3 records and delete each one...
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ for (uint32_t nvm3Key = EFR32Config::kMinConfigKey_MatterKvs; nvm3Key < EFR32Config::kMaxConfigKey_MatterKvs; nvm3Key++)
{
- case pw::OkStatus().code():
- return CHIP_NO_ERROR;
- case pw::Status::DeadlineExceeded().code():
- return CHIP_ERROR_TIMEOUT;
- case pw::Status::PermissionDenied().code():
- return CHIP_ERROR_ACCESS_DENIED;
- default:
- break;
+ err = EFR32Config::ClearConfigValue(nvm3Key);
+
+ if (err != CHIP_NO_ERROR)
+ {
+ break;
+ }
}
- return CHIP_ERROR_INTERNAL; // Unexpected KVS status.
+
+ memset(mKvsStoredKeyString, 0, sizeof(mKvsStoredKeyString));
+ return err;
}
-#endif // defined(CHIP_KVS_AVAILABLE) && CHIP_KVS_AVAILABLE
} // namespace PersistedStorage
} // namespace DeviceLayer
diff --git a/src/platform/EFR32/KeyValueStoreManagerImpl.h b/src/platform/EFR32/KeyValueStoreManagerImpl.h
index 32650db..daf5ff8 100644
--- a/src/platform/EFR32/KeyValueStoreManagerImpl.h
+++ b/src/platform/EFR32/KeyValueStoreManagerImpl.h
@@ -23,35 +23,14 @@
*/
#pragma once
-
-#include "em_msc.h"
-
-/* ignore GCC Wconversion warnings for pigweed */
-#if defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wconversion"
-#endif
-
-#include <pw_kvs/crc16_checksum.h>
-#include <pw_kvs/flash_memory.h>
-#include <pw_kvs/key_value_store.h>
-
-#if defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
-
-// KVS is only available for EFR32 when these macros are defined.
-#if defined(CHIP_KVS_SECTOR_COUNT) && defined(CHIP_KVS_BASE_SECTOR_INDEX)
-#define CHIP_KVS_AVAILABLE 1
-#else // defined(CHIP_KVS_SECTOR_COUNT) && defined(CHIP_KVS_BASE_ADDRESS)
-#define CHIP_KVS_AVAILABLE 0
-#endif // defined(CHIP_KVS_SECTOR_COUNT) && defined(CHIP_KVS_BASE_ADDRESS)
+#include <lib/core/CHIPPersistentStorageDelegate.h>
+#include <system/SystemClock.h>
+#include <system/SystemLayer.h>
namespace chip {
namespace DeviceLayer {
namespace PersistedStorage {
-#if defined(CHIP_KVS_AVAILABLE) && CHIP_KVS_AVAILABLE
class KeyValueStoreManagerImpl final : public KeyValueStoreManager
{
// Allow the KeyValueStoreManager interface class to delegate method calls to
@@ -59,136 +38,27 @@
friend class KeyValueStoreManager;
public:
- void Init() { mKvs.Init(); }
-
- CHIP_ERROR _Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size = nullptr, size_t offset = 0) const;
-
- CHIP_ERROR _Delete(const char * key);
-
- /**
- * @brief
- * Erases all data in the KVS partition, KVS needs to be initialized after
- * this operation.
- *
- * @return CHIP_NO_ERROR the partiton was erased.
- * CHIP_ERROR_TIMEOUT timed out while doing erase.
- * CHIP_ERROR_ACCESS_DENIED flash locked, erase failed.
- */
- CHIP_ERROR ErasePartition();
-
+ CHIP_ERROR Init(void);
CHIP_ERROR _Put(const char * key, const void * value, size_t value_size);
+ CHIP_ERROR _Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size = nullptr, size_t offset = 0) const;
+ CHIP_ERROR _Delete(const char * key);
+ CHIP_ERROR ErasePartition(void);
+
+ static constexpr size_t kMaxEntries = KVS_MAX_ENTRIES;
private:
- // KVS flash interface
- class Efr32FlashMemory : public pw::kvs::FlashMemory
- {
- public:
- Efr32FlashMemory() : pw::kvs::FlashMemory(FLASH_PAGE_SIZE, FLASH_SIZE / FLASH_PAGE_SIZE, sizeof(uint32_t), FLASH_BASE) {}
+ static void OnScheduledKeyMapSave(System::Layer * systemLayer, void * appState);
+ void ScheduleKeyMapSave(void);
+ bool IsValidKvsNvm3Key(const uint32_t nvm3Key) const;
+ CHIP_ERROR MapKvsKeyToNvm3(const char * key, uint32_t & nvm3Key, bool isSlotNeeded = false) const;
- // Enabling flash handled by platform
- pw::Status Enable() override { return pw::OkStatus(); }
- pw::Status Disable() override { return pw::OkStatus(); }
- bool IsEnabled() const override { return true; }
-
- pw::Status Erase(Address flash_address, size_t num_sectors) override
- {
- assert((flash_address % sizeof(uint32_t)) == 0);
- for (size_t i = 0; i < num_sectors; i++)
- {
- auto status =
- MscStatusToPwStatus(MSC_ErasePage(reinterpret_cast<uint32_t *>(flash_address + i * sector_size_bytes())));
- if (!status.ok())
- {
- return status;
- }
- }
- return pw::OkStatus();
- }
-
- pw::StatusWithSize Read(Address address, std::span<std::byte> output) override
- {
- memcpy(output.data(), reinterpret_cast<void *>(address), output.size());
- return pw::StatusWithSize(output.size());
- }
-
- pw::StatusWithSize Write(Address destination_flash_address, std::span<const std::byte> data) override
- {
- assert((destination_flash_address % sizeof(uint32_t)) == 0);
- return pw::StatusWithSize(MscStatusToPwStatus(MSC_WriteWord(reinterpret_cast<uint32_t *>(destination_flash_address),
- data.data(), data.size())),
- data.size());
- }
-
- private:
- static pw::Status MscStatusToPwStatus(MSC_Status_TypeDef msc_status)
- {
- switch (msc_status)
- {
- case mscReturnOk:
- return pw::OkStatus();
- case mscReturnUnaligned:
- case mscReturnInvalidAddr:
- return pw::Status::InvalidArgument();
- case mscReturnLocked:
- return pw::Status::PermissionDenied();
- case mscReturnTimeOut:
- return pw::Status::DeadlineExceeded();
- default:
- break;
- }
- return pw::Status::Internal();
- }
- };
-
- static constexpr size_t kMaxEntries = 50;
- pw::kvs::ChecksumCrc16 mKvsChecksum;
- const pw::kvs::EntryFormat kEntryFormat{ .magic = 0x64d51134, .checksum = &mKvsChecksum };
-
- Efr32FlashMemory mFlash;
- pw::kvs::FlashPartition mKvsPartition{ &mFlash, CHIP_KVS_BASE_SECTOR_INDEX, CHIP_KVS_SECTOR_COUNT };
- pw::kvs::KeyValueStoreBuffer<kMaxEntries, CHIP_KVS_SECTOR_COUNT> mKvs{ &mKvsPartition, kEntryFormat };
-
- // ===== Members for internal use by the following friends.
-
+ // ===== Members for internal use by the following friends.
friend KeyValueStoreManager & KeyValueStoreMgr();
friend KeyValueStoreManagerImpl & KeyValueStoreMgrImpl();
static KeyValueStoreManagerImpl sInstance;
};
-#else // defined(CHIP_KVS_AVAILABLE) && CHIP_KVS_AVAILABLE
-
-// Empty implementation which just asserts if used
-class KeyValueStoreManagerImpl final : public KeyValueStoreManager
-{
-public:
- CHIP_ERROR _Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size = nullptr, size_t offset = 0) const
- {
- assert(CHIP_KVS_AVAILABLE);
- return CHIP_ERROR_NOT_IMPLEMENTED;
- }
- CHIP_ERROR _Delete(const char * key)
- {
- assert(CHIP_KVS_AVAILABLE);
- return CHIP_ERROR_NOT_IMPLEMENTED;
- }
- CHIP_ERROR _Put(const char * key, const void * value, size_t value_size)
- {
- assert(CHIP_KVS_AVAILABLE);
- return CHIP_ERROR_NOT_IMPLEMENTED;
- }
-
-private:
- // ===== Members for internal use by the following friends.
-
- friend KeyValueStoreManager & KeyValueStoreMgr();
- friend KeyValueStoreManagerImpl & KeyValueStoreMgrImpl();
-
- static KeyValueStoreManagerImpl sInstance;
-};
-
-#endif // defined(CHIP_KVS_AVAILABLE) && CHIP_KVS_AVAILABLE
-
/**
* Returns the public interface of the KeyValueStoreManager singleton object.
*
diff --git a/src/platform/EFR32/PlatformManagerImpl.cpp b/src/platform/EFR32/PlatformManagerImpl.cpp
index 5acf098..391e2be 100644
--- a/src/platform/EFR32/PlatformManagerImpl.cpp
+++ b/src/platform/EFR32/PlatformManagerImpl.cpp
@@ -26,6 +26,7 @@
#include <platform/EFR32/DiagnosticDataProviderImpl.h>
#include <platform/FreeRTOS/SystemTimeSupport.h>
+#include <platform/KeyValueStoreManager.h>
#include <platform/PlatformManager.h>
#include <platform/internal/GenericPlatformManagerImpl_FreeRTOS.ipp>
@@ -44,8 +45,9 @@
CHIP_ERROR err;
// Initialize the configuration system.
- err = Internal::EFR32Config::Init();
+ err = chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init();
SuccessOrExit(err);
+
SetConfigurationMgr(&ConfigurationManagerImpl::GetDefaultInstance());
SetDiagnosticDataProvider(&DiagnosticDataProviderImpl::GetDefaultInstance());
diff --git a/src/test_driver/efr32/src/main.cpp b/src/test_driver/efr32/src/main.cpp
index a99e39e..c3d6028 100644
--- a/src/test_driver/efr32/src/main.cpp
+++ b/src/test_driver/efr32/src/main.cpp
@@ -186,7 +186,6 @@
mbedtls_platform_set_calloc_free(CHIPPlatformMemoryCalloc, CHIPPlatformMemoryFree);
chip::Platform::MemoryInit();
- chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init();
chip::DeviceLayer::PlatformMgr().InitChipStack();