diff --git a/components/openthread/CMakeLists.txt b/components/openthread/CMakeLists.txt index 119eb17543..176823e11f 100644 --- a/components/openthread/CMakeLists.txt +++ b/components/openthread/CMakeLists.txt @@ -174,7 +174,7 @@ idf_component_register(SRC_DIRS "${src_dirs}" REQUIRES esp_netif lwip driver LDFRAGMENTS linker.lf PRIV_REQUIRES console esp_event esp_partition esp_timer - ieee802154 mbedtls spi_flash) + ieee802154 mbedtls nvs_flash) if(CONFIG_OPENTHREAD_ENABLED) if(CONFIG_OPENTHREAD_RADIO) diff --git a/components/openthread/private_include/esp_openthread_platform.h b/components/openthread/private_include/esp_openthread_platform.h index 4c7f4ddcb4..6919e914be 100644 --- a/components/openthread/private_include/esp_openthread_platform.h +++ b/components/openthread/private_include/esp_openthread_platform.h @@ -139,6 +139,13 @@ void esp_openthread_platform_update(esp_openthread_mainloop_context_t *mainloop) */ esp_err_t esp_openthread_platform_process(otInstance *instance, const esp_openthread_mainloop_context_t *mainloop); +/** + * @brief This function set the OpenThread storage name + * + * @param[in] name The OpenThread storage name. + * + */ +void esp_openthread_set_storage_name(const char *name); #ifdef __cplusplus } // end of extern "C" #endif diff --git a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h index ab8e41a586..cc75cd9432 100644 --- a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h @@ -32,7 +32,7 @@ * When defined to 1, the platform MUST implement the otPlatFlash* APIs instead of the otPlatSettings* APIs. * */ -#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 1 +#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 0 /** * @def OPENTHREAD_CONFIG_LOG_OUTPUT diff --git a/components/openthread/private_include/openthread-core-esp32x-mtd-config.h b/components/openthread/private_include/openthread-core-esp32x-mtd-config.h index 7ecfbca1c1..f84a6f80eb 100644 --- a/components/openthread/private_include/openthread-core-esp32x-mtd-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-mtd-config.h @@ -32,7 +32,7 @@ * When defined to 1, the platform MUST implement the otPlatFlash* APIs instead of the otPlatSettings* APIs. * */ -#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 1 +#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 0 /** * @def OPENTHREAD_CONFIG_LOG_OUTPUT diff --git a/components/openthread/private_include/openthread-core-esp32x-radio-config.h b/components/openthread/private_include/openthread-core-esp32x-radio-config.h index 24942a7f31..6a292f2d6e 100644 --- a/components/openthread/private_include/openthread-core-esp32x-radio-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-radio-config.h @@ -31,7 +31,7 @@ * When defined to 1, the platform MUST implement the otPlatFlash* APIs instead of the otPlatSettings* APIs. * */ -#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 1 +#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 0 /** * @def OPENTHREAD_CONFIG_LOG_OUTPUT diff --git a/components/openthread/src/esp_openthread_platform.cpp b/components/openthread/src/esp_openthread_platform.cpp index 2197807aee..24b39b6531 100644 --- a/components/openthread/src/esp_openthread_platform.cpp +++ b/components/openthread/src/esp_openthread_platform.cpp @@ -102,18 +102,12 @@ esp_err_t esp_openthread_platform_init(const esp_openthread_platform_config_t *c s_openthread_platform_initialized = true; esp_err_t ret = ESP_OK; -/* Avoid to compile flash in RADIO type device */ -#if !CONFIG_OPENTHREAD_RADIO - const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, - config->port_config.storage_partition_name); - ESP_RETURN_ON_FALSE(partition, ESP_ERR_INVALID_ARG, OT_PLAT_LOG_TAG, "OpenThread storage partition not found"); - esp_openthread_flash_set_partition(partition); -#endif - s_platform_config = *config; ESP_GOTO_ON_ERROR(esp_openthread_lock_init(), exit, OT_PLAT_LOG_TAG, "esp_openthread_lock_init failed"); ESP_GOTO_ON_ERROR(esp_openthread_alarm_init(), exit, OT_PLAT_LOG_TAG, "esp_openthread_alarm_init failed"); + esp_openthread_set_storage_name(config->port_config.storage_partition_name); + if (config->host_config.host_connection_mode == HOST_CONNECTION_MODE_RCP_SPI) { ESP_GOTO_ON_ERROR(esp_openthread_spi_slave_init(config), exit, OT_PLAT_LOG_TAG, "esp_openthread_spi_slave_init failed"); diff --git a/components/openthread/src/port/esp_openthread_settings.c b/components/openthread/src/port/esp_openthread_settings.c new file mode 100644 index 0000000000..8f877bd724 --- /dev/null +++ b/components/openthread/src/port/esp_openthread_settings.c @@ -0,0 +1,214 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "nvs.h" +#include "esp_check.h" +#include "esp_openthread_common_macro.h" +#include "openthread/instance.h" +#include "openthread/platform/settings.h" + +#define OT_NAMESPACE "openthread" +#define OT_PART_NAME s_storage_name +#define OT_KEY_PATTERN "OT%02x" +#define OT_KEY_INDEX_PATTERN "OT%02x%02x" +#define OT_KEY_PATTERN_LEN 5 +#define OT_KEY_INDEX_PATTERN_LEN 7 +static nvs_handle_t s_ot_nvs_handle; +static const char *s_storage_name; + +void esp_openthread_set_storage_name(const char *name) +{ + s_storage_name = name; +} + +static esp_err_t get_next_empty_index(uint16_t aKey, uint8_t *index) +{ + ESP_RETURN_ON_FALSE((s_ot_nvs_handle != 0), ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG, "OT NVS handle is invalid."); + esp_err_t ret = ESP_OK; + static volatile uint8_t s_unused_pos = 0; + char ot_nvs_key[OT_KEY_INDEX_PATTERN_LEN] = { 0 }; + nvs_iterator_t nvs_it = NULL; + bool found = false; + + for (uint8_t i = 0; i != UINT8_MAX; i++) { + s_unused_pos++; + snprintf(ot_nvs_key, sizeof(ot_nvs_key), OT_KEY_INDEX_PATTERN, (uint8_t)aKey, s_unused_pos); + ret = nvs_entry_find(OT_PART_NAME, OT_NAMESPACE, NVS_TYPE_BLOB, &nvs_it); + while (ret == ESP_OK) { + nvs_entry_info_t info; + nvs_entry_info(nvs_it, &info); + if (memcmp(ot_nvs_key, info.key, OT_KEY_INDEX_PATTERN_LEN - 1) == 0) { + found = true; + break; + } + ret = nvs_entry_next(&nvs_it); + } + nvs_release_iterator(nvs_it); + if (!found) { + // find an empty position, return ESP_OK + *index = s_unused_pos; + return ESP_OK; + } + } + // all index was used, no memory for current data, return ESP_ERR_NOT_FOUND. + return ESP_ERR_NOT_FOUND; +} + +static esp_err_t find_target_key_using_index(uint16_t aKey, int aIndex, char *key, size_t key_len) +{ + ESP_RETURN_ON_FALSE((s_ot_nvs_handle != 0), ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG, "OT NVS handle is invalid."); + esp_err_t ret = ESP_OK; + nvs_iterator_t nvs_it = NULL; + int cur_index = 0; + char ot_nvs_key[OT_KEY_PATTERN_LEN] = { 0 }; + + ret = nvs_entry_find(OT_PART_NAME, OT_NAMESPACE, NVS_TYPE_BLOB, &nvs_it); + if (ret != ESP_OK) { + return ret; + } + snprintf(ot_nvs_key, sizeof(ot_nvs_key), OT_KEY_PATTERN, (uint8_t)aKey); + while (ret == ESP_OK) { + nvs_entry_info_t info; + nvs_entry_info(nvs_it, &info); + if (memcmp(ot_nvs_key, info.key, OT_KEY_PATTERN_LEN - 1) == 0) { + if (cur_index == aIndex) { + memcpy(key, info.key, key_len); + break; + } else { + cur_index++; + } + } + ret = nvs_entry_next(&nvs_it); + } + nvs_release_iterator(nvs_it); + + if ((cur_index != aIndex) || (ret != ESP_OK)) { + return ESP_FAIL; + } + return ESP_OK; +} + +static esp_err_t erase_all_key(uint16_t aKey) +{ + ESP_RETURN_ON_FALSE((s_ot_nvs_handle != 0), ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG, "OT NVS handle is invalid."); + esp_err_t ret = ESP_OK; + nvs_iterator_t nvs_it = NULL; + char ot_nvs_key[OT_KEY_PATTERN_LEN] = { 0 }; + + ret = nvs_entry_find(OT_PART_NAME, OT_NAMESPACE, NVS_TYPE_BLOB, &nvs_it); + if (ret == ESP_ERR_NVS_NOT_FOUND) { + return ESP_OK; + } + ESP_RETURN_ON_FALSE((ret == ESP_OK && nvs_it != NULL), ESP_FAIL, OT_PLAT_LOG_TAG, "Can not find any data in nvs flash, err: %d", ret); + while (ret == ESP_OK) { + snprintf(ot_nvs_key, sizeof(ot_nvs_key), OT_KEY_PATTERN, (uint8_t)aKey); + nvs_entry_info_t info; + nvs_entry_info(nvs_it, &info); + if (memcmp(ot_nvs_key, info.key, OT_KEY_PATTERN_LEN - 1) == 0) { + ret = nvs_erase_key(s_ot_nvs_handle, info.key); + if (ret != ESP_OK) { + break; + } + } + ret = nvs_entry_next(&nvs_it); + } + nvs_release_iterator(nvs_it); + ret = nvs_commit(s_ot_nvs_handle); + if (ret != ESP_OK) { + return ESP_FAIL; + } + return ESP_OK; +} + +void otPlatSettingsInit(otInstance *aInstance, const uint16_t *aSensitiveKeys, uint16_t aSensitiveKeysLength) +{ + esp_err_t err = nvs_open(OT_NAMESPACE, NVS_READWRITE, &s_ot_nvs_handle); + if (err != ESP_OK) { + ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to open NVS namespace (0x%x)", err); + assert(0); + } +} + +void otPlatSettingsDeinit(otInstance *aInstance) +{ + if (s_ot_nvs_handle != 0) { + nvs_close(s_ot_nvs_handle); + } +} + +otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength) +{ + ESP_RETURN_ON_FALSE((s_ot_nvs_handle != 0), OT_ERROR_NOT_FOUND, OT_PLAT_LOG_TAG, "OT NVS handle is invalid."); + esp_err_t ret = ESP_OK; + char ot_nvs_key[OT_KEY_INDEX_PATTERN_LEN] = { 0 }; + + ret = find_target_key_using_index(aKey, aIndex, ot_nvs_key, OT_KEY_INDEX_PATTERN_LEN); + if (ret != ESP_OK) { + return OT_ERROR_NOT_FOUND; + } + ret = nvs_get_blob(s_ot_nvs_handle, ot_nvs_key, aValue, (size_t *)aValueLength); + ESP_RETURN_ON_FALSE((ret == ESP_OK), OT_ERROR_NOT_FOUND, OT_PLAT_LOG_TAG, "Data not found, err: %d", ret); + return OT_ERROR_NONE; +} + +otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength) +{ + ESP_RETURN_ON_FALSE((s_ot_nvs_handle != 0), OT_ERROR_NOT_FOUND, OT_PLAT_LOG_TAG, "OT NVS handle is invalid."); + esp_err_t ret = ESP_OK; + char ot_nvs_key[OT_KEY_INDEX_PATTERN_LEN]= { 0 }; + + snprintf(ot_nvs_key, sizeof(ot_nvs_key), OT_KEY_INDEX_PATTERN, (uint8_t)aKey, 0); + ret = nvs_set_blob(s_ot_nvs_handle, ot_nvs_key, aValue, aValueLength); + ESP_RETURN_ON_FALSE((ret == ESP_OK), OT_ERROR_NO_BUFS, OT_PLAT_LOG_TAG, "No buffers, err: %d", ret); + ret = nvs_commit(s_ot_nvs_handle); + ESP_RETURN_ON_FALSE((ret == ESP_OK), OT_ERROR_NO_BUFS, OT_PLAT_LOG_TAG, "OT NVS handle shut down, err: %d", ret); + return OT_ERROR_NONE; +} + +otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength) +{ + ESP_RETURN_ON_FALSE((s_ot_nvs_handle != 0), OT_ERROR_NOT_FOUND, OT_PLAT_LOG_TAG, "OT NVS handle is invalid."); + esp_err_t ret = ESP_OK; + uint8_t unused_pos; + char ot_nvs_key[OT_KEY_INDEX_PATTERN_LEN] = { 0 }; + + ret = get_next_empty_index(aKey, &unused_pos); + ESP_RETURN_ON_FALSE((ret == ESP_OK), OT_ERROR_NO_BUFS, OT_PLAT_LOG_TAG, "No buffers, err: %d", ret); + snprintf(ot_nvs_key, sizeof(ot_nvs_key), OT_KEY_INDEX_PATTERN, (uint8_t)aKey, unused_pos); + ret = nvs_set_blob(s_ot_nvs_handle, ot_nvs_key, aValue, aValueLength); + ESP_RETURN_ON_FALSE((ret == ESP_OK), OT_ERROR_NO_BUFS, OT_PLAT_LOG_TAG, "No buffers, err: %d", ret); + ret = nvs_commit(s_ot_nvs_handle); + ESP_RETURN_ON_FALSE((ret == ESP_OK), OT_ERROR_NO_BUFS, OT_PLAT_LOG_TAG, "OT NVS handle shut down, err: %d", ret); + return OT_ERROR_NONE; +} + +otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex) +{ + ESP_RETURN_ON_FALSE((s_ot_nvs_handle != 0), OT_ERROR_NOT_FOUND, OT_PLAT_LOG_TAG, "OT NVS handle is invalid."); + esp_err_t ret = ESP_OK; + + if (aIndex == -1) { + ret = erase_all_key(aKey); + } else { + char ot_nvs_key[OT_KEY_INDEX_PATTERN_LEN] = { 0 }; + ret = find_target_key_using_index(aKey, aIndex, ot_nvs_key, OT_KEY_INDEX_PATTERN_LEN); + if (ret != ESP_OK) { + return OT_ERROR_NOT_FOUND; + } + ret = nvs_erase_key(s_ot_nvs_handle, ot_nvs_key); + nvs_commit(s_ot_nvs_handle); + } + return OT_ERROR_NONE; +} + +void otPlatSettingsWipe(otInstance *aInstance) +{ + nvs_erase_all(s_ot_nvs_handle); +} diff --git a/examples/openthread/ot_br/main/esp_ot_config.h b/examples/openthread/ot_br/main/esp_ot_config.h index 9e9953966a..d8c4265cba 100644 --- a/examples/openthread/ot_br/main/esp_ot_config.h +++ b/examples/openthread/ot_br/main/esp_ot_config.h @@ -96,7 +96,7 @@ #define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \ { \ - .storage_partition_name = "ot_storage", \ + .storage_partition_name = "nvs", \ .netif_queue_size = 10, \ .task_queue_size = 10, \ } diff --git a/examples/openthread/ot_br/partitions.csv b/examples/openthread/ot_br/partitions.csv index a484b99010..4305c74725 100644 --- a/examples/openthread/ot_br/partitions.csv +++ b/examples/openthread/ot_br/partitions.csv @@ -3,4 +3,3 @@ nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, factory, app, factory, 0x10000, 1600K, -ot_storage, data, 0x3a, , 0x2000, diff --git a/examples/openthread/ot_cli/main/esp_ot_config.h b/examples/openthread/ot_cli/main/esp_ot_config.h index c1defedae5..a0a1a37a9e 100644 --- a/examples/openthread/ot_cli/main/esp_ot_config.h +++ b/examples/openthread/ot_cli/main/esp_ot_config.h @@ -66,7 +66,7 @@ #define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \ { \ - .storage_partition_name = "ot_storage", \ + .storage_partition_name = "nvs", \ .netif_queue_size = 10, \ .task_queue_size = 10, \ } diff --git a/examples/openthread/ot_cli/partitions.csv b/examples/openthread/ot_cli/partitions.csv index 1874ddc89f..6c0e048dba 100644 --- a/examples/openthread/ot_cli/partitions.csv +++ b/examples/openthread/ot_cli/partitions.csv @@ -3,4 +3,3 @@ nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, factory, app, factory, 0x10000, 0x120000, -ot_storage, data, 0x3a, , 0x2000, diff --git a/examples/openthread/ot_rcp/main/esp_ot_config.h b/examples/openthread/ot_rcp/main/esp_ot_config.h index 24c434c12d..42e91bbb18 100644 --- a/examples/openthread/ot_rcp/main/esp_ot_config.h +++ b/examples/openthread/ot_rcp/main/esp_ot_config.h @@ -75,7 +75,7 @@ #define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \ { \ - .storage_partition_name = "ot_storage", \ + .storage_partition_name = "nvs", \ .netif_queue_size = 10, \ .task_queue_size = 10, \ } diff --git a/examples/openthread/ot_rcp/partitions.csv b/examples/openthread/ot_rcp/partitions.csv index 738122467a..88795c6b03 100644 --- a/examples/openthread/ot_rcp/partitions.csv +++ b/examples/openthread/ot_rcp/partitions.csv @@ -3,4 +3,3 @@ nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, , 0x1000, factory, app, factory, 0x10000, 1M, -ot_storage, data, 0x3a, , 0x2000,