Skip to content

Commit cac49ac

Browse files
Balaklakanordicjm
authored andcommitted
emds: Revise rram related timing in emds
Updated estimated timing for rram storage using emds. Also updated documentation and test to a more proper indication of values for rram. Signed-off-by: Ingar Kulbrandstad <[email protected]>
1 parent 5b86006 commit cac49ac

File tree

4 files changed

+47
-38
lines changed

4 files changed

+47
-38
lines changed

doc/nrf/libraries/others/emds.rst

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,47 +7,47 @@ Emergency data storage
77
:local:
88
:depth: 2
99

10-
Overview
11-
********
12-
The emergency data storage (EMDS) library provides persistent storage functionality designed to prevent the wear and tear of the flash memory.
10+
The emergency data storage (EMDS) library provides persistent storage functionality designed to prevent the wear and tear of the flash memory or RRAM (persistent memory).
1311
Its intended use is for storing of data undergoing frequent changes during runtime.
1412

1513
Implementation
16-
==============
14+
**************
1715
The :kconfig:option:`CONFIG_EMDS` Kconfig option enables the emergency data storage.
1816

19-
The application must initialize the pre-allocated flash area by using the :c:func:`emds_init` function.
17+
The application must initialize the pre-allocated storage area by using the :c:func:`emds_init` function.
2018
The :kconfig:option:`CONFIG_EMDS_SECTOR_COUNT` option defines how many sectors should be used to store data.
2119

2220
The allocated storage space must be larger than the combined data stored by the application.
23-
Allocating a larger flash area will demand more resources, but also increase the life expectancy of the flash.
24-
The chosen size should reflect the amount of data stored, the available flash resources, and how the application calls the :c:func:`emds_store` function.
25-
In general, it should not be necessary to allocate a large flash area, since only a limited set of data should be stored to ensure swift completion of writing the flash on shutdown.
21+
Allocating a larger storage area will demand more resources, but also increase the life expectancy of the persistent memory.
22+
The chosen size should reflect the amount of data stored, the available persistent memory and how the application calls the :c:func:`emds_store` function.
23+
In general, it should not be necessary to allocate a large storage area, since only a limited set of data should be stored to ensure swift completion of writing the data on shutdown.
2624

2725
The memory location that is going to be stored must be added on initialization.
2826
All memory areas must be provided through entries containing an ID, data pointer, and data length, using the :c:func:`emds_entry_add` function and the :c:macro:`EMDS_STATIC_ENTRY_DEFINE` macro.
2927
Entries to be stored when the emergency data storage is triggered need their own unique IDs that are not changed after a reboot.
3028

31-
When all entries are added, the :c:func:`emds_load` function restores the entries into the memory areas from the flash.
29+
When all entries are added, the :c:func:`emds_load` function restores the entries into the memory areas from the persistent memory.
3230

33-
After restoring the previous data, the application must run the :c:func:`emds_prepare` function to prepare the flash area for receiving new entries.
34-
If the remaining empty flash area is smaller than the required data size, the flash area will be automatically erased to increase the available flash area.
31+
After restoring the previous data, the application must run the :c:func:`emds_prepare` function to prepare the storage area for receiving new entries.
32+
If the remaining empty storage area is smaller than the required data size, the storage area will be automatically erased to increase the available storage area.
3533

3634
The storage is done in deterministic time, so it is possible to know how long it takes to store all registered entries.
3735
However, this is chip-dependent, so it is important to measure the time.
3836
Find timing values under the "Electrical specification" section for the non-volatile memory controller in the Product Specification for the relevant SoC or the SiP you are using.
39-
For example, for the nRF9160 SiP, see the `Electrical specification of nRF9160`_ page.
37+
For example, for the nRF52840 SiP, see the `nRF52840 Product Specification`_ page.
4038

4139
The following Kconfig options can be configured:
4240

4341
* :kconfig:option:`CONFIG_EMDS_FLASH_TIME_WRITE_ONE_WORD_US`
4442
* :kconfig:option:`CONFIG_EMDS_FLASH_TIME_ENTRY_OVERHEAD_US`
4543
* :kconfig:option:`CONFIG_EMDS_FLASH_TIME_BASE_OVERHEAD_US`
4644

47-
When configuring these values, consider the time for erase when doing garbage collection in NVS.
45+
When configuring these values, consider the time for erase when doing garbage collection in NVS using flash.
4846
If partial erase is not enabled or supported, the time of a complete sector erase has to be included in the :kconfig:option:`CONFIG_EMDS_FLASH_TIME_BASE_OVERHEAD_US`.
4947
When partial erase is enabled and supported by the hardware, include the time it takes for the scheduler to trigger, which is depending on the time defined in :kconfig:option:`CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE_MS`.
5048
When changing the :kconfig:option:`CONFIG_EMDS_FLASH_TIME_BASE_OVERHEAD_US` option, it is important that the worst time is considered.
49+
When configuring these values using RRAM, you do not need to consider garbage collection in the same way as for flash, as it can be written to regardless of value.
50+
However, avoid the ERASEALL functionality, because that can increase the time before the EMDS store functions are called.
5151

5252
The application must call the :c:func:`emds_store` function to store all entries.
5353
This can only be done once, before the :c:func:`emds_prepare` function must be called again.
@@ -64,7 +64,7 @@ The :c:func:`emds_is_ready` function can be called to check if EMDS is prepared
6464
Once the data storage has completed, a callback is called if provided in :c:func:`emds_init`.
6565
This callback notifies the application that the data storage has completed, and can be used to reboot the CPU or execute another function that is needed.
6666

67-
After completion of :c:func:`emds_store`, the :c:func:`emds_is_ready` function call will return error, since it can no longer guarantee that the data will fit into the flash area.
67+
After completion of :c:func:`emds_store`, the :c:func:`emds_is_ready` function call will return an error, because it can no longer guarantee that the data will fit into the persistent memory area.
6868

6969
The above described process is summarized in a message sequence diagram.
7070

@@ -90,7 +90,7 @@ The above described process is summarized in a message sequence diagram.
9090

9191
Requirements
9292
************
93-
To prevent frequent writes to flash memory, the EMDS library can write data to flash only when the device is shutting down.
93+
To prevent frequent writes to persistent memory, the EMDS library can write data only when the device is shutting down.
9494
EMDS restores the application data to RAM at reboot.
9595

9696
EMDS can store data within a guaranteed time, based on the amount of data being stored.
@@ -128,9 +128,9 @@ The :c:func:`emds_store_time_get` function estimates the required worst-case tim
128128
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)
129129
130130
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`.
131-
: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.
131+
: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 (4 bytes) of flash or the write-buffer size (16 bytes) of RRAM.
132132
These can be found by looking at datasheets, driver documentation, and the configuration of the application.
133-
:math:`s_\text{ate}` is the size of the allocation table entry used by the EMDS flash module, which is 8 B.
133+
:math:`s_\text{ate}` is the size of the allocation table entry used by the EMDS, which is 8 B.
134134

135135
Example of time estimation
136136
==========================
@@ -157,7 +157,7 @@ Calling the :c:func:`emds_store_time_get` function in the sample automatically c
157157

158158
Limitations
159159
***********
160-
The power-fail comparator for the nRF528xx cannot be used with EMDS, as it will prevent the NVMC from performing write operations to flash.
160+
The power-fail comparator cannot be active when EMDS is used, as it will prevent the NVMC or RRAMC from performing write operations to persistent memory.
161161

162162
Dependencies
163163
************

subsys/emds/Kconfig

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ menuconfig EMDS
99
select EXPERIMENTAL
1010
depends on PARTITION_MANAGER_ENABLED
1111
depends on FLASH_MAP
12+
depends on CRC
1213
default n
1314
help
1415
Enable Emergency Data Storage
@@ -36,16 +37,20 @@ config EMDS_THREAD_PRIORITY
3637
priority.
3738

3839
config EMDS_FLASH_TIME_WRITE_ONE_WORD_US
39-
int "Time to write one word into flash"
40-
default 210 if SOC_FLASH_NRF_RRAM
40+
int "Time to write block size into flash/rram"
41+
default 107 if SOC_SERIES_NRF54LX
42+
default 43 if SOC_SERIES_NRF53X
43+
default 43 if SOC_NRF52833
44+
default 338 if SOC_NRF52832
4145
default 41
4246
help
43-
Max time to write one word (4 bytes) in flash (in microseconds). This
44-
value is dependent on the chip used, and should be checked against the
45-
chip datasheet.
46-
For RRAM-based flash drivers, data is written in blocks of 32 bytes over
47-
buffered writing. This value is used to calculate the time to write
48-
one 32-byte block.
47+
Max time to write one block into non-volatile storage (in microseconds).
48+
The block size is dependent on non-volatile storage type and is 4
49+
bytes for flash and 16 bytes for RRAM. The value is dependent on the
50+
chip used, and should be checked against the chip's datasheet.
51+
For RRAM-based flash drivers, data is written in blocks of 16 bytes
52+
over buffered writing. This value is used to calculate the time to
53+
write one 16-byte block.
4954

5055
config EMDS_FLASH_TIME_ENTRY_OVERHEAD_US
5156
int "Time to schedule write of one entry"
@@ -55,7 +60,7 @@ config EMDS_FLASH_TIME_ENTRY_OVERHEAD_US
5560

5661
config EMDS_FLASH_TIME_BASE_OVERHEAD_US
5762
int "Time to schedule the store process"
58-
default 18200 if SETTINGS && SOC_FLASH_NRF_RRAM
63+
default 1000 if SETTINGS && SOC_FLASH_NRF_RRAM
5964
default 85000 if SETTINGS && !SOC_FLASH_NRF_PARTIAL_ERASE
6065
default 9000 if SETTINGS && SOC_FLASH_NRF_PARTIAL_ERASE
6166
default 500
@@ -68,8 +73,7 @@ config EMDS_FLASH_TIME_BASE_OVERHEAD_US
6873
worst case scenario, before starting storing entries. This value
6974
is dependent on the chip used, and should be checked against the chip
7075
datasheet.
71-
For RRAM-based flash drivers, the time is defined by the erasing block size.
72-
The default erasing block size is 4096 bytes.
76+
For RRAM-based persistent memory driver, use ERASEPROTECT and disregard the SOC_FLASH_NRF_PARTIAL_ERASE_MS parameter.
7377

7478
module = EMDS
7579
module-str = emergency data storage

tests/subsys/emds/emds_api/prj.conf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ CONFIG_ZTEST=y
99
CONFIG_FLASH=y
1010
CONFIG_FLASH_MAP=y
1111
CONFIG_PM_SINGLE_IMAGE=y
12+
CONFIG_CRC=y
1213
CONFIG_EMDS=y
1314
CONFIG_REBOOT=y
1415
CONFIG_SETTINGS=y
15-
CONFIG_NVS=y
16+
CONFIG_ZMS=y
1617
CONFIG_BT=y
17-
CONFIG_EMDS_FLASH_TIME_BASE_OVERHEAD_US=6000

tests/subsys/emds/emds_flash/src/main.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,13 @@
2121
#if defined CONFIG_SOC_FLASH_NRF_RRAM
2222
#define RRAM DT_INST(0, soc_nv_flash)
2323
#define EMDS_FLASH_BLOCK_SIZE DT_PROP(RRAM, write_block_size)
24+
#define EXPECTED_STORE_TIME_BLOCK_SIZE (400)
25+
#define EXPECTED_STORE_TIME_1024 (3000)
2426
#else
2527
#define FLASH DT_INST(0, soc_nv_flash)
2628
#define EMDS_FLASH_BLOCK_SIZE DT_PROP(FLASH, write_block_size)
29+
#define EXPECTED_STORE_TIME_BLOCK_SIZE (200)
30+
#define EXPECTED_STORE_TIME_1024 (13000)
2731
#endif
2832

2933
#define ADDR_OFFS_MASK 0x0000FFFF
@@ -631,12 +635,13 @@ ZTEST(emds_flash_tests, test_corrupted_data)
631635

632636
ZTEST(emds_flash_tests, test_write_speed)
633637
{
634-
char data_in[4] = "bee";
638+
char data_in[EMDS_FLASH_BLOCK_SIZE];
635639
uint8_t data_in_big[1024];
636640
int64_t tic;
637641
int64_t toc;
638642
uint64_t store_time_us;
639643

644+
memset(data_in, 69, sizeof(data_in));
640645
memset(data_in_big, 69, sizeof(data_in_big));
641646

642647
(void)dk_leds_init();
@@ -658,19 +663,19 @@ ZTEST(emds_flash_tests, test_write_speed)
658663
dk_set_led(0, false);
659664
toc = k_uptime_ticks();
660665
store_time_us = k_ticks_to_us_ceil64(toc - tic);
661-
printk("Storing 4 bytes took: %lldus\n", store_time_us);
662-
zassert_true(store_time_us < 300, "Storing 4 bytes took to long time");
666+
printk("Storing %d bytes took: %lldus\n", sizeof(data_in), store_time_us);
667+
zassert_true(store_time_us < EXPECTED_STORE_TIME_BLOCK_SIZE,
668+
"Storing %d bytes took to long time", sizeof(data_in));
663669

664670
dk_set_led(0, true);
665671
tic = k_uptime_ticks();
666672
emds_flash_write(&ctx, 2, data_in_big, sizeof(data_in_big));
667673
dk_set_led(0, false);
668674
toc = k_uptime_ticks();
669675
store_time_us = k_ticks_to_us_ceil64(toc - tic);
670-
printk("Storing 1024 bytes took: %lldus\n", store_time_us);
671-
#if !defined CONFIG_SOC_FLASH_NRF_RRAM /* TODO: Fix it with NCSDK-26922 */
672-
zassert_true(store_time_us < 13000, "Storing 1024 bytes took to long time");
673-
#endif
676+
printk("Storing %d bytes took: %lldus\n", sizeof(data_in_big), store_time_us);
677+
zassert_true(store_time_us < EXPECTED_STORE_TIME_1024,
678+
"Storing %d bytes took to long time", sizeof(data_in_big));
674679
}
675680

676681
ZTEST_SUITE(emds_flash_tests, NULL, fs_init, NULL, NULL, NULL);

0 commit comments

Comments
 (0)