From 3da3aa89d21bbe4d08e162ff7c6fc22c48d3cdbb Mon Sep 17 00:00:00 2001 From: jmartinez-silabs <67972863+jmartinez-silabs@users.noreply.github.com> Date: Thu, 31 Mar 2022 23:54:17 -0400 Subject: [PATCH] [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 --- .github/.wordlist.txt | 1 + examples/light-switch-app/efr32/README.md | 9 + examples/light-switch-app/efr32/src/main.cpp | 1 - examples/lighting-app/efr32/README.md | 9 + examples/lighting-app/efr32/src/main.cpp | 1 - examples/lock-app/efr32/README.md | 9 + examples/lock-app/efr32/src/main.cpp | 1 - examples/ota-requestor-app/efr32/src/main.cpp | 1 - examples/persistent-storage/efr32/BUILD.gn | 9 +- examples/persistent-storage/efr32/README.md | 10 +- examples/persistent-storage/efr32/main.cpp | 2 + .../platform/efr32/ldscripts/efr32mg12.ld | 45 +-- .../platform/efr32/ldscripts/efr32mg24.ld | 48 +-- examples/shell/efr32/src/main.cpp | 1 - examples/window-app/efr32/README.md | 9 + examples/window-app/efr32/src/main.cpp | 1 - scripts/examples/gn_efr32_example.sh | 11 +- src/platform/EFR32/BLEManagerImpl.cpp | 17 +- src/platform/EFR32/CHIPDevicePlatformConfig.h | 45 --- .../EFR32/ConfigurationManagerImpl.cpp | 2 - src/platform/EFR32/ConfigurationManagerImpl.h | 2 +- src/platform/EFR32/EFR32Config.cpp | 332 +++++------------- src/platform/EFR32/EFR32Config.h | 127 ++++--- .../EFR32/KeyValueStoreManagerImpl.cpp | 223 +++++++----- src/platform/EFR32/KeyValueStoreManagerImpl.h | 154 +------- src/platform/EFR32/PlatformManagerImpl.cpp | 4 +- src/test_driver/efr32/src/main.cpp | 1 - third_party/efr32_sdk/efr32_sdk.gni | 11 +- 28 files changed, 427 insertions(+), 659 deletions(-) diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index 37131914b0f8ce..f8d0a2dc434631 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -865,6 +865,7 @@ NTAG nullable nullptr NUM +NVM nwk NXP objcopy diff --git a/examples/light-switch-app/efr32/README.md b/examples/light-switch-app/efr32/README.md index a4c9d154c5a6c8..831b66406cd7d2 100644 --- a/examples/light-switch-app/efr32/README.md +++ b/examples/light-switch-app/efr32/README.md @@ -406,3 +406,12 @@ is_debug show_qr_code $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A "show_qr_code=false" + +### KVS maximum entry count + +kvs_max_entries + + Set the maximum Kvs entries that can be stored in NVM (Default 75) + Thresholds: 30 <= kvs_max_entries <= 255 + + $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A kvs_max_entries=50 diff --git a/examples/light-switch-app/efr32/src/main.cpp b/examples/light-switch-app/efr32/src/main.cpp index 7ca14521d301e5..5a587b75371184 100644 --- a/examples/light-switch-app/efr32/src/main.cpp +++ b/examples/light-switch-app/efr32/src/main.cpp @@ -132,7 +132,6 @@ int main(void) EFR32_LOG("Init CHIP Stack"); // Init Chip memory management before the stack chip::Platform::MemoryInit(); - chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init(); CHIP_ERROR ret = PlatformMgr().InitChipStack(); if (ret != CHIP_NO_ERROR) diff --git a/examples/lighting-app/efr32/README.md b/examples/lighting-app/efr32/README.md index a6fc76292a8d4a..a4e45a380c07af 100644 --- a/examples/lighting-app/efr32/README.md +++ b/examples/lighting-app/efr32/README.md @@ -356,3 +356,12 @@ is_debug show_qr_code $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A "show_qr_code=false" + +### KVS maximum entry count + +kvs_max_entries + + Set the maximum Kvs entries that can be stored in NVM (Default 75) + Thresholds: 30 <= kvs_max_entries <= 255 + + $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A kvs_max_entries=50 diff --git a/examples/lighting-app/efr32/src/main.cpp b/examples/lighting-app/efr32/src/main.cpp index e0f1a4bc26fc1c..d521646e5f87fe 100644 --- a/examples/lighting-app/efr32/src/main.cpp +++ b/examples/lighting-app/efr32/src/main.cpp @@ -136,7 +136,6 @@ int main(void) EFR32_LOG("Init CHIP Stack"); // Init Chip memory management before the stack chip::Platform::MemoryInit(); - chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init(); CHIP_ERROR ret = PlatformMgr().InitChipStack(); if (ret != CHIP_NO_ERROR) diff --git a/examples/lock-app/efr32/README.md b/examples/lock-app/efr32/README.md index 65442b31d84229..61c53124287916 100644 --- a/examples/lock-app/efr32/README.md +++ b/examples/lock-app/efr32/README.md @@ -321,3 +321,12 @@ is_debug show_qr_code $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A "show_qr_code=false" + +### KVS maximum entry count + +kvs_max_entries + + Set the maximum Kvs entries that can be stored in NVM (Default 75) + Thresholds: 30 <= kvs_max_entries <= 255 + + $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A kvs_max_entries=50 diff --git a/examples/lock-app/efr32/src/main.cpp b/examples/lock-app/efr32/src/main.cpp index 2ed647b327aa72..79496aba236330 100644 --- a/examples/lock-app/efr32/src/main.cpp +++ b/examples/lock-app/efr32/src/main.cpp @@ -132,7 +132,6 @@ int main(void) // Init Chip memory management before the stack chip::Platform::MemoryInit(); - chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init(); CHIP_ERROR ret = PlatformMgr().InitChipStack(); if (ret != CHIP_NO_ERROR) diff --git a/examples/ota-requestor-app/efr32/src/main.cpp b/examples/ota-requestor-app/efr32/src/main.cpp index c268cdd94ca56b..b193b31aae3ac1 100644 --- a/examples/ota-requestor-app/efr32/src/main.cpp +++ b/examples/ota-requestor-app/efr32/src/main.cpp @@ -169,7 +169,6 @@ int main(void) EFR32_LOG("Init CHIP Stack"); // Init Chip memory management before the stack chip::Platform::MemoryInit(); - chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init(); CHIP_ERROR ret = PlatformMgr().InitChipStack(); if (ret != CHIP_NO_ERROR) diff --git a/examples/persistent-storage/efr32/BUILD.gn b/examples/persistent-storage/efr32/BUILD.gn index 3508a4a1b8a882..05877c4e879656 100644 --- a/examples/persistent-storage/efr32/BUILD.gn +++ b/examples/persistent-storage/efr32/BUILD.gn @@ -37,6 +37,7 @@ efr32_sdk("sdk") { "${chip_root}/src/platform/EFR32", "${efr32_project_dir}/include", "${examples_plat_dir}", + "${chip_root}/src/lib", ] defines = [ "BOARD_ID=${efr32_board}" ] @@ -46,22 +47,20 @@ efr32_executable("persistent_storage") { output_name = "chip-efr32-persistent_storage-example.out" sources = [ - "${efr32_project_dir}/../KeyValueStorageTest.cpp", "${examples_plat_dir}/heap_4_silabs.c", "${examples_plat_dir}/init_efrPlatform.cpp", + "../KeyValueStorageTest.cpp", "main.cpp", ] deps = [ ":sdk", - "$dir_pw_assert", - "$dir_pw_kvs:crc16", "${chip_root}/src/lib", ] include_dirs = [ - "${efr32_project_dir}/..", - "${efr32_project_dir}/include", + "..", + "include", ] ldscript = "${examples_plat_dir}/ldscripts/${efr32_family}.ld" diff --git a/examples/persistent-storage/efr32/README.md b/examples/persistent-storage/efr32/README.md index 2f3b5773821006..841a72fe82727b 100644 --- a/examples/persistent-storage/efr32/README.md +++ b/examples/persistent-storage/efr32/README.md @@ -28,15 +28,7 @@ platforms. ## EFR32 -The EFR32 platform KVS is fully implemented, the KVS is enabled and configured -using these defines: - -``` -defines = [ - "CHIP_KVS_SECTOR_COUNT=4", - "CHIP_KVS_BASE_SECTOR_INDEX=((FLASH_SIZE/FLASH_PAGE_SIZE)-(CHIP_KVS_SECTOR_COUNT))", -] -``` +The EFR32 platform KVS is fully implemented diff --git a/examples/persistent-storage/efr32/main.cpp b/examples/persistent-storage/efr32/main.cpp index 04d8aa428b4fa9..3d9674369fa153 100644 --- a/examples/persistent-storage/efr32/main.cpp +++ b/examples/persistent-storage/efr32/main.cpp @@ -31,6 +31,8 @@ #include "KeyValueStorageTest.h" #include "init_efrPlatform.h" #include "sl_system_kernel.h" +#include +#include #include static TaskHandle_t sTestTaskHandle; diff --git a/examples/platform/efr32/ldscripts/efr32mg12.ld b/examples/platform/efr32/ldscripts/efr32mg12.ld index f55f03521bc1e4..9dba3e1ded84e2 100644 --- a/examples/platform/efr32/ldscripts/efr32mg12.ld +++ b/examples/platform/efr32/ldscripts/efr32mg12.ld @@ -177,36 +177,6 @@ SECTIONS __etext = .; - /*******************************************************************/ - /* Define flash block for BLE-simee & chip-nvm3 */ - /* simee: 9000H (36k) bytes for BLE nvm3 */ - /* chipNvm3_section: 4000H (16k) bytes for chip nvm3. */ - /* 8K is reserved for OpenThread's NVM which is mapped directly at */ - /* the top of flash */ - /*******************************************************************/ - - OPENTHREAD_NVM_SIZE = 8192; - - .nvm_dummy (DSECT): - { - __nvm3_dummy_begin = .; - . = ALIGN (8192); - __nvm3_dummy_simee = .; - KEEP(*(.simee)); - . = ALIGN (8192); - __nvm3_dummy_chip = .; - KEEP(*(chipNvm3_section)); - . = ALIGN (8192); - . += DEFINED(SILABS_WIFI) ? 0 : OPENTHREAD_NVM_SIZE; - . = DEFINED(SILABS_WIFI) ? . : ALIGN (8192); - } > FLASH - - /* Set NVM to end of FLASH */ - __nvm3Base = LENGTH(FLASH) - SIZEOF(.nvm_dummy) + (__nvm3_dummy_simee - __nvm3_dummy_begin); - __chipNvm3Base = LENGTH(FLASH) - SIZEOF(.nvm_dummy) + (__nvm3_dummy_chip - __nvm3_dummy_begin); - - - /*******************************************************************/ .data : AT (__etext) { @@ -264,6 +234,8 @@ SECTIONS KEEP(*(.heap*)) __HeapLimit = .; } > RAM + + __main_flash_end__ = ORIGIN(FLASH) + LENGTH(FLASH); /* .stack_dummy section doesn't contains any symbols. It is only * used for linker to calculate size of stack sections, and assign @@ -279,9 +251,18 @@ SECTIONS __StackLimit = __StackTop - SIZEOF(.stack_dummy); PROVIDE(__stack = __StackTop); - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") + .nvm (DSECT) : { + KEEP(*(.simee*)) + } > FLASH + linker_nvm_end = __main_flash_end__ - 2048; + linker_nvm_begin = linker_nvm_end - SIZEOF(.nvm); + linker_nvm_size = SIZEOF(.nvm); + __nvm3Base = linker_nvm_begin; + + /* Check if data + heap + stack exceeds RAM limit */ + /*ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")*/ + ASSERT( (linker_nvm_begin + SIZEOF(.nvm)) <= __main_flash_end__, "NVM3 is excessing the flash size !") /* Check if FLASH usage exceeds FLASH size */ ASSERT( LENGTH(FLASH) >= (__etext), "FLASH memory overflowed !") diff --git a/examples/platform/efr32/ldscripts/efr32mg24.ld b/examples/platform/efr32/ldscripts/efr32mg24.ld index 8a7835f6cf2fd0..06bfc7c1842170 100644 --- a/examples/platform/efr32/ldscripts/efr32mg24.ld +++ b/examples/platform/efr32/ldscripts/efr32mg24.ld @@ -177,36 +177,6 @@ SECTIONS __etext = .; - /*******************************************************************/ - /* Define flash block for BLE-simee & chip-nvm3 */ - /* simee: 9000H (36k) bytes for BLE nvm3 */ - /* chipNvm3_section: 4000H (16k) bytes for chip nvm3. */ - /* 8K is reserved for OpenThread's NVM which is mapped directly at */ - /* the top of flash */ - /*******************************************************************/ - - OPENTHREAD_NVM_SIZE = 8192; - - .nvm_dummy (DSECT): - { - __nvm3_dummy_begin = .; - . = ALIGN (8192); - __nvm3_dummy_simee = .; - KEEP(*(.simee)); - . = ALIGN (8192); - __nvm3_dummy_chip = .; - KEEP(*(chipNvm3_section)); - . = ALIGN (8192); - . += DEFINED(SILABS_WIFI) ? 0 : OPENTHREAD_NVM_SIZE; - . = DEFINED(SILABS_WIFI) ? . : ALIGN (8192); - } > FLASH - - /* Set NVM to end of FLASH */ - __nvm3Base = (ORIGIN(FLASH) + LENGTH(FLASH)) - SIZEOF(.nvm_dummy) + (__nvm3_dummy_simee - __nvm3_dummy_begin); - __chipNvm3Base = (ORIGIN(FLASH) + LENGTH(FLASH)) - SIZEOF(.nvm_dummy) + (__nvm3_dummy_chip - __nvm3_dummy_begin); - - - /*******************************************************************/ .data : AT (__etext) { @@ -265,6 +235,8 @@ SECTIONS __HeapLimit = .; } > RAM + __main_flash_end__ = ORIGIN(FLASH) + LENGTH(FLASH); + /* .stack_dummy section doesn't contains any symbols. It is only * used for linker to calculate size of stack sections, and assign * values to stack symbols later */ @@ -279,11 +251,17 @@ SECTIONS __StackLimit = __StackTop - SIZEOF(.stack_dummy); PROVIDE(__stack = __StackTop); - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") + .nvm (DSECT) : { + KEEP(*(.simee*)) + } > FLASH + + linker_nvm_end = __main_flash_end__; + linker_nvm_begin = linker_nvm_end - SIZEOF(.nvm); + linker_nvm_size = SIZEOF(.nvm); + __nvm3Base = linker_nvm_begin; + /* Check if data + heap + stack exceeds RAM limit */ + /*ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")*/ + ASSERT( (linker_nvm_begin + SIZEOF(.nvm)) <= __main_flash_end__, "NVM3 is excessing the flash size !") - /* Check if FLASH usage exceeds FLASH size */ - ASSERT( (ORIGIN(FLASH) + LENGTH(FLASH)) >= (__etext + SIZEOF(.data)), "FLASH memory overflowed !") - ASSERT((__etext + SIZEOF(.data)) <= __nvm3Base, "FLASH memory overlapped with NVM section.") } diff --git a/examples/shell/efr32/src/main.cpp b/examples/shell/efr32/src/main.cpp index 7592513a730448..9bb827a3d4ea0c 100644 --- a/examples/shell/efr32/src/main.cpp +++ b/examples/shell/efr32/src/main.cpp @@ -110,7 +110,6 @@ int main(void) // Init Chip memory management before the stack chip::Platform::MemoryInit(); - chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init(); CHIP_ERROR ret = PlatformMgr().InitChipStack(); if (ret != CHIP_NO_ERROR) diff --git a/examples/window-app/efr32/README.md b/examples/window-app/efr32/README.md index 8fac6941c0a8d8..8756365f3a7570 100644 --- a/examples/window-app/efr32/README.md +++ b/examples/window-app/efr32/README.md @@ -356,3 +356,12 @@ is_debug show_qr_code $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A "show_qr_code=false" + +### KVS maximum entry count + +kvs_max_entries + + Set the maximum Kvs entries that can be stored in NVM (Default 75) + Thresholds: 30 <= kvs_max_entries <= 255 + + $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A kvs_max_entries=50 diff --git a/examples/window-app/efr32/src/main.cpp b/examples/window-app/efr32/src/main.cpp index cfffc9dc071d87..4e844ccd847e34 100644 --- a/examples/window-app/efr32/src/main.cpp +++ b/examples/window-app/efr32/src/main.cpp @@ -108,7 +108,6 @@ int main(void) // Init Chip memory management before the stack chip::Platform::MemoryInit(); - chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init(); err = PlatformMgr().InitChipStack(); if (err != CHIP_NO_ERROR) diff --git a/scripts/examples/gn_efr32_example.sh b/scripts/examples/gn_efr32_example.sh index 0ce40ef66d7287..37346facff934d 100755 --- a/scripts/examples/gn_efr32_example.sh +++ b/scripts/examples/gn_efr32_example.sh @@ -24,7 +24,7 @@ source "$(dirname "$0")/../../scripts/activate.sh" set -x env USE_WIFI=false - +CHIP_ROOT="$(dirname "$0")/../.." USAGE="./scripts/examples/gn_efr32_example.sh []" if [ "$#" == "0" ]; then @@ -63,6 +63,9 @@ if [ "$#" == "0" ]; then Monitor & log memory usage at runtime. (Default false) enable_openthread_cli Enables openthread cli without matter shell. (Default true) + kvs_max_entries + Set the maxium Kvs entries that can be store in NVM (Default 75) + Thresholds: 30 <= kvs_max_entries <= 255 show_qr_code Enables QR code on LCD for devices with an LCD setupDiscriminator @@ -144,14 +147,14 @@ else BUILD_DIR=$OUTDIR/$EFR32_BOARD echo BUILD_DIR="$BUILD_DIR" if [ "$USE_WIFI" == true ]; then - gn gen --check --fail-on-unused-args --root="$ROOT" --dotfile="$ROOT"/build_for_wifi_gnfile.gn --args="efr32_board=\"$EFR32_BOARD\" $optArgs" "$BUILD_DIR" + gn gen --check --fail-on-unused-args --export-compile-commands --root="$ROOT" --dotfile="$ROOT"/build_for_wifi_gnfile.gn --args="efr32_board=\"$EFR32_BOARD\" $optArgs" "$BUILD_DIR" else # thread build # if [ -z "$optArgs" ]; then - gn gen --check --fail-on-unused-args --root="$ROOT" --args="efr32_board=\"$EFR32_BOARD\"" "$BUILD_DIR" + gn gen --check --fail-on-unused-args --export-compile-commands --root="$ROOT" --args="efr32_board=\"$EFR32_BOARD\"" "$BUILD_DIR" else - gn gen --check --fail-on-unused-args --root="$ROOT" --args="efr32_board=\"$EFR32_BOARD\" $optArgs" "$BUILD_DIR" + gn gen --check --fail-on-unused-args --export-compile-commands --root="$ROOT" --args="efr32_board=\"$EFR32_BOARD\" $optArgs" "$BUILD_DIR" fi fi ninja -v -C "$BUILD_DIR"/ diff --git a/src/platform/EFR32/BLEManagerImpl.cpp b/src/platform/EFR32/BLEManagerImpl.cpp index bbbf59105bdba5..13805feebb1f24 100644 --- a/src/platform/EFR32/BLEManagerImpl.cpp +++ b/src/platform/EFR32/BLEManagerImpl.cpp @@ -76,6 +76,14 @@ namespace { #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 @@ void BLEManagerImpl::bluetoothStackEventHandler(void * p_arg) 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 @@ void BLEManagerImpl::bluetoothStackEventHandler(void * p_arg) } 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 @@ void BLEManagerImpl::bluetoothStackEventHandler(void * p_arg) } 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 ba22beda6ab6d9..0303a7b90059af 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 b5a266454d6961..9c370bf3b52e6d 100644 --- a/src/platform/EFR32/ConfigurationManagerImpl.cpp +++ b/src/platform/EFR32/ConfigurationManagerImpl.cpp @@ -284,9 +284,7 @@ void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg) #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 7a157ccc3b7fac..baa3e5849afaec 100644 --- a/src/platform/EFR32/ConfigurationManagerImpl.h +++ b/src/platform/EFR32/ConfigurationManagerImpl.h @@ -26,7 +26,7 @@ #include -#include "EFR32Config.h" +#include namespace chip { namespace DeviceLayer { diff --git a/src/platform/EFR32/EFR32Config.cpp b/src/platform/EFR32/EFR32Config.cpp index da1734e34d898f..f78797c504c6e8 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" -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. - +// Substitute the GSDK weak nvm3_lockBegin and nvm3_lockEnd +// for an application controlled re-entrance protection #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. +void nvm3_lockBegin(void) +{ + VerifyOrDie(nvm3_Sem != NULL); + xSemaphoreTake(nvm3_Sem, EFR32_SEM_TIMEOUT_ms); +} -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); +void nvm3_lockEnd(void) +{ + VerifyOrDie(nvm3_Sem != NULL); + xSemaphoreGive(nvm3_Sem); +} -CHIP_NVM3_DEFINE_SECTION_INIT_DATA(chipNvm3, CHIP_DEVICE_CONFIG_NVM3_MAX_OBJECT_SIZE, CHIP_NVM3_REPACK_HEADROOM); +namespace chip { +namespace DeviceLayer { +namespace Internal { + +// 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 @@ CHIP_ERROR EFR32Config::Init() 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 @@ CHIP_ERROR EFR32Config::ReadConfigValue(Key key, bool & val) 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 @@ CHIP_ERROR EFR32Config::ReadConfigValue(Key key, uint32_t & val) 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 @@ CHIP_ERROR EFR32Config::ReadConfigValue(Key key, uint64_t & val) 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 @@ CHIP_ERROR EFR32Config::ReadConfigValueStr(Key key, char * buf, size_t bufSize, 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 @@ CHIP_ERROR EFR32Config::ReadConfigValueStr(Key key, char * buf, size_t bufSize, // 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 @@ CHIP_ERROR EFR32Config::ReadConfigValueStr(Key key, char * buf, size_t bufSize, { // 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 @@ CHIP_ERROR EFR32Config::ReadConfigValueStr(Key key, char * buf, size_t bufSize, } exit: - OnExit(); return err; } @@ -256,19 +201,10 @@ CHIP_ERROR EFR32Config::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSiz 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,41 +214,68 @@ CHIP_ERROR EFR32Config::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSiz // 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::ReadConfigValueCounter(uint8_t counterIdx, uint32_t & val) +CHIP_ERROR EFR32Config::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen, size_t offset) { CHIP_ERROR err; - uint32_t tmpVal; - Key key = kMinConfigKey_ChipCounter + counterIdx; + 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 (pdFALSE == xSemaphoreTake(nvm3_Sem, pdMS_TO_TICKS(EFR32_SEM_TIMEOUT_ms))) + if (buf != NULL) { - err = CHIP_ERROR_TIMEOUT; - SuccessOrExit(err); + // 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; +} - VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. +CHIP_ERROR EFR32Config::ReadConfigValueCounter(uint8_t counterIdx, uint32_t & val) +{ + CHIP_ERROR err; + uint32_t tmpVal; + Key key = kMinConfigKey_MatterCounter + counterIdx; - err = MapNvm3Error(nvm3_open(&handle, &chipNvm3)); - SuccessOrExit(err); + VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. // 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 EFR32Config::WriteConfigValue(Key key, bool val) { 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 EFR32Config::WriteConfigValue(Key key, uint32_t val) { 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 EFR32Config::WriteConfigValue(Key key, uint64_t val) { 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 EFR32Config::WriteConfigValueStr(Key key, const char * str, size_t st { 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 EFR32Config::WriteConfigValueBin(Key key, const uint8_t * data, size_ { 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 EFR32Config::ClearConfigValue(Key key) { 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 EFR32Config::FactoryResetConfig(void) 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 @@ CHIP_ERROR EFR32Config::ForEachRecord(Key firstNvm3Key, Key lastNvm3Key, bool ad // 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 @@ CHIP_ERROR EFR32Config::ForEachRecord(Key firstNvm3Key, Key lastNvm3Key, bool ad 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 @@ CHIP_ERROR EFR32Config::ForEachRecord(Key firstNvm3Key, Key lastNvm3Key, bool ad 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 @@ void EFR32Config::RepackNvm3Flash(void) // 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 638dd534e578fe..6b8bf52428a04f 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 @@ namespace Internal { * 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(keyBaseOffset) << 8 | id; + return kMatterNvm3KeyDomain | static_cast(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); - - // CHIP Counter Keys - static constexpr Key kConfigKey_BootCount = EFR32ConfigKey(kChipCounter_KeyBase, 0x00); - static constexpr Key kConfigKey_TotalOperationalHours = EFR32ConfigKey(kChipCounter_KeyBase, 0x01); + 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); + + // 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 @@ class EFR32Config 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 @@ class EFR32Config 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 28f6ea44d72430..d46079fcc78163 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 +#include +#include #include +#include +#include -/* 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 - -#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]; + +CHIP_ERROR KeyValueStoreManagerImpl::Init(void) +{ + CHIP_ERROR err; + err = EFR32Config::Init(); + SuccessOrExit(err); -#if defined(CHIP_KVS_AVAILABLE) && CHIP_KVS_AVAILABLE + memset(mKvsStoredKeyString, 0, sizeof(mKvsStoredKeyString)); + size_t outLen; + err = EFR32Config::ReadConfigValueBin(EFR32Config::kConfigKey_KvsStringKeyMap, reinterpret_cast(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(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::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(reinterpret_cast(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(value), value_size, outLen, offset_bytes); if (read_bytes_size) { - *read_bytes_size = status_and_size.size(); - } - 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; + *read_bytes_size = outLen; } - 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(reinterpret_cast(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(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 32650db28215b7..daf5ff8ce32c42 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 -#include -#include - -#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 +#include +#include 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 @@ class KeyValueStoreManagerImpl final : public KeyValueStoreManager friend class KeyValueStoreManager; public: - void Init() { mKvs.Init(); } - + 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); - /** - * @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 _Put(const char * key, const void * value, size_t value_size); - -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) {} - - // 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(flash_address + i * sector_size_bytes()))); - if (!status.ok()) - { - return status; - } - } - return pw::OkStatus(); - } - - pw::StatusWithSize Read(Address address, std::span output) override - { - memcpy(output.data(), reinterpret_cast(address), output.size()); - return pw::StatusWithSize(output.size()); - } - - pw::StatusWithSize Write(Address destination_flash_address, std::span data) override - { - assert((destination_flash_address % sizeof(uint32_t)) == 0); - return pw::StatusWithSize(MscStatusToPwStatus(MSC_WriteWord(reinterpret_cast(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 mKvs{ &mKvsPartition, kEntryFormat }; - - // ===== 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; - } + static constexpr size_t kMaxEntries = KVS_MAX_ENTRIES; private: - // ===== Members for internal use by the following friends. + 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; + // ===== 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 5acf098528605b..391e2becf4e48f 100644 --- a/src/platform/EFR32/PlatformManagerImpl.cpp +++ b/src/platform/EFR32/PlatformManagerImpl.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -44,8 +45,9 @@ CHIP_ERROR PlatformManagerImpl::_InitChipStack(void) 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 a99e39e10879fa..c3d6028ab136b5 100644 --- a/src/test_driver/efr32/src/main.cpp +++ b/src/test_driver/efr32/src/main.cpp @@ -186,7 +186,6 @@ int main(void) mbedtls_platform_set_calloc_free(CHIPPlatformMemoryCalloc, CHIPPlatformMemoryFree); chip::Platform::MemoryInit(); - chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init(); chip::DeviceLayer::PlatformMgr().InitChipStack(); diff --git a/third_party/efr32_sdk/efr32_sdk.gni b/third_party/efr32_sdk/efr32_sdk.gni index 5af0f01991c1da..846733d07e4e7a 100644 --- a/third_party/efr32_sdk/efr32_sdk.gni +++ b/third_party/efr32_sdk/efr32_sdk.gni @@ -24,6 +24,7 @@ declare_args() { # Location of the efr32 SDK. efr32_sdk_root = "${chip_root}/third_party/efr32_sdk/repo" enable_openthread_cli = true + kvs_max_entries = 75 } assert(efr32_sdk_root != "", "efr32_sdk_root must be specified") @@ -130,6 +131,8 @@ template("efr32_sdk") { "CORTEXM3_EFM32_MICRO", "EFR32_LOG_ENABLED=1", "NVM3_DEFAULT_NVM_SIZE=40960", + "NVM3_DEFAULT_MAX_OBJECT_SIZE=4092", + "KVS_MAX_ENTRIES=${kvs_max_entries}", "EFR32_OPENTHREAD_API", "PHY=EMBER_PHY_RAIL", "CORTEXM3", @@ -138,7 +141,6 @@ template("efr32_sdk") { "${efr32_mcu}=1", "${efr32_board}=1", "SL_SUPRESS_DEPRECATION_WARNINGS_SDK_3_1", - "CHIP_KVS_BASE_SECTOR_INDEX=((FLASH_SIZE/FLASH_PAGE_SIZE)-(CHIP_KVS_SECTOR_COUNT))", "__HEAP_SIZE=0", "SL_CATALOG_FREERTOS_KERNEL_PRESENT=1", "MBEDTLS_THREADING_C=1", @@ -218,10 +220,7 @@ template("efr32_sdk") { "${efr32_sdk_root}/platform/emdrv/nvm3/lib/libnvm3_CM4_gcc.a", ] - defines += [ - "EFR32MG12", - "CHIP_KVS_SECTOR_COUNT=6", - ] + defines += [ "EFR32MG12" ] } else if (efr32_family == "efr32mg21") { _include_dirs += [ "${efr32_sdk_root}/hardware/kit/EFR32MG21_${efr32_board}/config", @@ -242,7 +241,6 @@ template("efr32_sdk") { defines += [ "EFR32MG21", "EFR32_SERIES2_CONFIG1_MICRO", - "CHIP_KVS_SECTOR_COUNT=4", ] } else if (efr32_family == "efr32mg24") { _include_dirs += [ @@ -264,7 +262,6 @@ template("efr32_sdk") { defines += [ "EFR32MG24", "EFR32_SERIES2_CONFIG4_MICRO", - "CHIP_KVS_SECTOR_COUNT=4", ] } if (use_wf200) {