With SDK For Mesh v5.0.0 the replay cache is saved to flash using MESH_CONFIG_STRATEGY_ON_POWER_DOWN. In mesh_config_load() a check is made to ensure that there is enough space left to save the data on shutdown. If that is not the case the file will be cleared with mesh_config_backend_file_clean() and m_file_in_progress_cnt is incremented.
If there is an issue with the stored data on flash mesh_stack_init() will call mesh_stack_config_clear(), which among other things, ends up calling mesh_config_backend_file_clean() for the replay cache. However, this file has already been queued for cleaning and thus the backend simply ignores the request. But mesh_stack_config_clear() will still increment the m_file_in_progress_cnt.
Since m_file_in_progress_cnt never reaches 0, NRF_MESH_EVT_CONFIG_STABLE is never emitted causing things like mesh_stack_power_down() to deadlock.
The following patch reports back to the caller if the backend was already busy cleaning the file and thus can avoid incrementing the counter.
--- a/mesh/core/include/mesh_config_backend.h +++ b/mesh/core/include/mesh_config_backend.h @@ -190,9 +190,11 @@ uint32_t mesh_config_backend_power_down_time_get(void); * * It is possible to clean several files in parallel. The backend creates queue from requests. * - * @param[in] p_file File to clean content. + * @param[in] p_file File to clean content. + * @retval NRF_SUCCESS The file is successfully queued for clean. + * @retval NRF_ERROR_BUSY The file is in the process of cleaning. */ -void mesh_config_backend_file_clean(mesh_config_backend_file_t * p_file); +uint32_t mesh_config_backend_file_clean(mesh_config_backend_file_t * p_file); /** * Puts the backend in the power down mode. diff --git a/mesh/core/src/mesh_config.c b/mesh/core/src/mesh_config.c index a97644d..36d9188 100644 --- a/mesh/core/src/mesh_config.c +++ b/mesh/core/src/mesh_config.c @@ -478,8 +478,9 @@ void mesh_config_load(void) } } - m_file_in_progress_cnt++; - mesh_config_backend_file_clean(p_file->p_backend_data); + if (mesh_config_backend_file_clean(p_file->p_backend_data) == NRF_SUCCESS) { + m_file_in_progress_cnt++; + } } } } @@ -636,8 +637,9 @@ void mesh_config_file_clear(uint16_t file_id) #if PERSISTENT_STORAGE if (p_file->strategy != MESH_CONFIG_STRATEGY_NON_PERSISTENT) { - m_file_in_progress_cnt++; - mesh_config_backend_file_clean(p_file->p_backend_data); + if (mesh_config_backend_file_clean(p_file->p_backend_data) == NRF_SUCCESS) { + m_file_in_progress_cnt++; + } } #endif } diff --git a/mesh/core/src/mesh_config_flashman_glue.c b/mesh/core/src/mesh_config_flashman_glue.c index 9ad6c09..f442823 100644 --- a/mesh/core/src/mesh_config_flashman_glue.c +++ b/mesh/core/src/mesh_config_flashman_glue.c @@ -81,7 +81,7 @@ typedef struct static mesh_config_backend_evt_cb_t m_evt_cb; static uint8_t m_allocated_page_count; -static void file_remove(mesh_config_backend_file_t * p_file); +static uint32_t file_remove(mesh_config_backend_file_t * p_file); static void file_restore(mesh_config_backend_file_t * p_file); static const uint8_t * flash_area_end_get(void) @@ -196,13 +196,13 @@ static void file_ready_listener(void * p_args) m_evt_cb(&event); } -static void file_remove(mesh_config_backend_file_t * p_file) +static uint32_t file_remove(mesh_config_backend_file_t * p_file) { flash_manager_t * p_manager = &p_file->glue_data.flash_manager; if (flash_manager_is_removing(p_manager)) { - return; + return NRF_ERROR_BUSY; } uint32_t status = flash_manager_remove(p_manager); @@ -226,6 +226,8 @@ static void file_remove(mesh_config_backend_file_t * p_file) p_file->glue_data.listener.p_args = p_file; flash_manager_mem_listener_register(&p_file->glue_data.listener); } + + return NRF_SUCCESS; } static void file_restore(mesh_config_backend_file_t * p_file) @@ -353,9 +355,9 @@ uint32_t mesh_config_backend_file_create(mesh_config_backend_file_t * p_file) return flash_manager_add(p_manager, &config); } -void mesh_config_backend_file_clean(mesh_config_backend_file_t * p_file) +uint32_t mesh_config_backend_file_clean(mesh_config_backend_file_t * p_file) { - file_remove(p_file); + return file_remove(p_file); } uint32_t mesh_config_backend_record_write(mesh_config_backend_file_t * p_file, const uint8_t * p_data, uint32_t length)
Thanks.