Skip to content

Commit

Permalink
doc: emds: document formula for time estimation
Browse files Browse the repository at this point in the history
This adds documentation of the formula used to compute the required
storage time at shutdown in the worst-case.

Signed-off-by: Ludvig Samuelsen Jordet <ludvig.jordet@nordicsemi.no>
  • Loading branch information
ludvigsj authored and rlubos committed Jun 28, 2023
1 parent 7d1739f commit f869b25
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 1 deletion.
45 changes: 45 additions & 0 deletions doc/nrf/libraries/others/emds.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 4 additions & 0 deletions doc/nrf/releases/release-notes-changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
4 changes: 3 additions & 1 deletion samples/bluetooth/mesh/light_ctrl/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions subsys/emds/emds_flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit f869b25

Please sign in to comment.