diff --git a/doc/nrf/libraries/others/emds.rst b/doc/nrf/libraries/others/emds.rst index e990409e923d..0b419d7d445b 100644 --- a/doc/nrf/libraries/others/emds.rst +++ b/doc/nrf/libraries/others/emds.rst @@ -107,6 +107,51 @@ To initialize the emergency data storage, complete the following steps: #. Call :c:func:`emds_prepare`. #. Create interrupt or other functionality that will call :c:func:`emds_store`. +.. _emds_readme_application_integration: + +Application integration +*********************** + +When using EMDS in an application, you need to know the worst case scenario for how long power is required to be available. +This knowledge makes it possible for you to make good design choices ensuring enough backup power to reach this time requirement. + +The easiest way of computing an estimate of the time required to store all entries, in a worst case scenario, is to call the :c:func:`emds_store_time_get` function. +This function returns a worst-case storage time estimate in microseconds (µs) for a given application. +For this to work, Kconfig options :kconfig:option:`CONFIG_EMDS_FLASH_TIME_BASE_OVERHEAD_US`, :kconfig:option:`CONFIG_EMDS_FLASH_TIME_ENTRY_OVERHEAD_US` and :kconfig:option:`CONFIG_EMDS_FLASH_TIME_WRITE_ONE_WORD_US` need to be set as described in the `Implementation`_ section. +The :c:func:`emds_store_time_get` function estimates the required worst-case time to store :math:`n` entries using the following formula: + +.. math:: + + t_\text{store} = t_\text{base} + \sum_{i = 1}^n \left(t_\text{entry} + t_\text{word}\left(\left\lceil\frac{s_\text{ate}}{s_\text{block}}\right\rceil + \left\lceil\frac{s_i}{s_\text{block}}\right\rceil \right)\right) + +where :math:`t_\text{base}` is the value specified by :kconfig:option:`CONFIG_EMDS_FLASH_TIME_BASE_OVERHEAD_US`, :math:`t_\text{entry}` is the value specified by :kconfig:option:`CONFIG_EMDS_FLASH_TIME_ENTRY_OVERHEAD_US` and :math:`t_\text{word}` is the value specified by :kconfig:option:`CONFIG_EMDS_FLASH_TIME_WRITE_ONE_WORD_US`. +:math:`s_i` is the size of the :math:`i`\ th entry in bytes and :math:`s_\text{block}` is the number of bytes in one word of flash. +These can be found by looking at datasheets, driver documentation, and the configuration of the application. +:math:`s_\text{ate}` is the size of the allocation table entry used by the EMDS flash module, which is 8 B. + +Example of time estimation +========================== + +Using the formula from the previous section, you can estimate the time required to store all entries for the :ref:`bluetooth_mesh_light_lc` sample running on the nRF52840. +The following values can be inserted into the formula: + +* Set :math:`t_\text{base}` = 9000 µs. + This is the worst case overhead when a store is triggered in the middle of an erase on nRF52840 with :kconfig:option:`CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE` enabled in the sample by default, and should be adjusted when using other configurations. +* Set :math:`t_\text{entry}` = 300 µs and :math:`t_\text{word}` = 41 µs. *Note: These values are valid only for this specific chip and configuration, and should be computed for the specific configuration whenever using EMDS.* +* The sample uses two entries, one for the RPL with 255 entries (:math:`s_i` = 2040 B) and one for the lightness state (:math:`s_i` = 3 B). +* The flash write block size :math:`s_\text{block}` in this case is 4 B, and the ATE size :math:`s_\text{ate}` is 8 B. + +This gives the following formula to compute estimated storage time: + +.. math:: + \begin{aligned} + t_\text{store} = 9000\text{ µs} &+ \left( 300\text{ µs} + 41\text{ µs} \times \left( \left\lceil\frac{8\text{ B}}{4\text{ B}}\right\rceil + \left\lceil\frac{2040\text{ B}}{4\text{ B}}\right\rceil \right) \right) \\ + &+ \left( 300\text{ µs} + 41\text{ µs} \times \left( \left\lceil\frac{8\text{ B}}{4\text{ B}}\right\rceil + \left\lceil\frac{3\text{ B}}{4\text{ B}}\right\rceil \right) \right) \\ + &= 30715\text{ µs} + \end{aligned} + +Calling the :c:func:`emds_store_time_get` function in the sample automatically computes the result of the formula and returns 30715. + Limitations *********** The power-fail comparator for the nRF528xx cannot be used with EMDS, as it will prevent the NVMC from performing write operations to flash. diff --git a/doc/nrf/releases/release-notes-changelog.rst b/doc/nrf/releases/release-notes-changelog.rst index 53070430af8d..ccf695192f2c 100644 --- a/doc/nrf/releases/release-notes-changelog.rst +++ b/doc/nrf/releases/release-notes-changelog.rst @@ -543,3 +543,7 @@ Added: * A page on :ref:`ug_wireless_coexistence` in :ref:`protocols`. * Pages on :ref:`thread_device_types` and :ref:`thread_sed_ssed` to the :ref:`ug_thread` documentation. * A new section :ref:`ug_pmic`, containing :ref:`ug_npm1300_features` and :ref:`ug_npm1300_gs`. + +Updated: + +* The :ref:`emds_readme` library documentation with :ref:`emds_readme_application_integration` section about the formula used to compute the required storage time at shutdown in a worst case scenario. diff --git a/samples/bluetooth/mesh/light_ctrl/README.rst b/samples/bluetooth/mesh/light_ctrl/README.rst index 68b8d7680e1b..83f1eb6993cf 100644 --- a/samples/bluetooth/mesh/light_ctrl/README.rst +++ b/samples/bluetooth/mesh/light_ctrl/README.rst @@ -171,8 +171,10 @@ FEM support Emergency data storage ====================== -To build this sample with support for emergency data storage, set ``OVERLAY_CONFIG`` to :file:`overlay-emds.conf`. +To build this sample with support for emergency data storage (EMDS), set ``OVERLAY_CONFIG`` to :file:`overlay-emds.conf`. This will save replay protection list (RPL) data and some of the :ref:`bt_mesh_lightness_srv_readme` data to the emergency data storage instead of to the :ref:`settings_api`. +When using EMDS, certain considerations need to be taken regarding hardware choices in your application design. +See :ref:`emds_readme_application_integration` in the EMDS documentation for more information. See :ref:`cmake_options` for instructions on how to add this option. For more information about using configuration overlay files, see :ref:`zephyr:important-build-vars` in the Zephyr documentation. diff --git a/subsys/emds/emds_flash.c b/subsys/emds/emds_flash.c index 7079d93b4d7b..0e768a38e59c 100644 --- a/subsys/emds/emds_flash.c +++ b/subsys/emds/emds_flash.c @@ -426,6 +426,7 @@ int emds_flash_init(struct emds_fs *fs) k_mutex_lock(&fs->emds_lock, K_FOREVER); fs->ate_size = align_size(fs, sizeof(struct emds_ate)); + __ASSERT(fs->ate_size == 8, "ATE size not aligned with documented value"); rc = ate_last_recover(fs); k_mutex_unlock(&fs->emds_lock); if (rc) {