mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-09 23:54:33 +02:00
Merge branch 'feature/nvs_test_erase_cycles' into 'master'
nvs: add a test for sector erase cycles See merge request espressif/esp-idf!7948
This commit is contained in:
@@ -28,18 +28,30 @@ SOURCE_FILES = \
|
|||||||
crc.cpp \
|
crc.cpp \
|
||||||
main.cpp
|
main.cpp
|
||||||
|
|
||||||
|
ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang version"), 1)
|
||||||
|
COMPILER := clang
|
||||||
|
else
|
||||||
|
COMPILER := gcc
|
||||||
|
endif
|
||||||
|
|
||||||
CPPFLAGS += -I../include -I../src -I./ -I../../esp_common/include -I../../esp32/include -I ../../mbedtls/mbedtls/include -I ../../spi_flash/include -I ../../soc/include -I ../../xtensa/include -I ../../../tools/catch -fprofile-arcs -ftest-coverage
|
CPPFLAGS += -I../include -I../src -I./ -I../../esp_common/include -I../../esp32/include -I ../../mbedtls/mbedtls/include -I ../../spi_flash/include -I ../../soc/include -I ../../xtensa/include -I ../../../tools/catch -fprofile-arcs -ftest-coverage
|
||||||
CFLAGS += -fprofile-arcs -ftest-coverage
|
CFLAGS += -fprofile-arcs -ftest-coverage
|
||||||
CXXFLAGS += -std=c++11 -Wall -Werror
|
CXXFLAGS += -std=c++11 -Wall -Werror
|
||||||
LDFLAGS += -lstdc++ -Wall -fprofile-arcs -ftest-coverage
|
LDFLAGS += -lstdc++ -Wall -fprofile-arcs -ftest-coverage
|
||||||
|
|
||||||
|
ifeq ($(COMPILER),clang)
|
||||||
|
CFLAGS += -fsanitize=address
|
||||||
|
CXXFLAGS += -fsanitize=address
|
||||||
|
LDFLAGS += -fsanitize=address
|
||||||
|
endif
|
||||||
|
|
||||||
OBJ_FILES = $(SOURCE_FILES:.cpp=.o)
|
OBJ_FILES = $(SOURCE_FILES:.cpp=.o)
|
||||||
|
|
||||||
COVERAGE_FILES = $(OBJ_FILES:.o=.gc*)
|
COVERAGE_FILES = $(OBJ_FILES:.o=.gc*)
|
||||||
|
|
||||||
$(OBJ_FILES): %.o: %.cpp
|
$(OBJ_FILES): %.o: %.cpp
|
||||||
|
|
||||||
$(TEST_PROGRAM): $(OBJ_FILES)
|
$(TEST_PROGRAM): $(OBJ_FILES) clean-coverage
|
||||||
$(MAKE) -C ../../mbedtls/mbedtls/ lib
|
$(MAKE) -C ../../mbedtls/mbedtls/ lib
|
||||||
g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) ../../mbedtls/mbedtls/library/libmbedcrypto.a
|
g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) ../../mbedtls/mbedtls/library/libmbedcrypto.a
|
||||||
|
|
||||||
@@ -62,12 +74,14 @@ coverage_report: coverage.info
|
|||||||
genhtml coverage.info --output-directory coverage_report
|
genhtml coverage.info --output-directory coverage_report
|
||||||
@echo "Coverage report is in coverage_report/index.html"
|
@echo "Coverage report is in coverage_report/index.html"
|
||||||
|
|
||||||
clean:
|
clean-coverage:
|
||||||
$(MAKE) -C ../../mbedtls/mbedtls/ clean
|
|
||||||
rm -f $(OBJ_FILES) $(TEST_PROGRAM)
|
|
||||||
rm -f $(COVERAGE_FILES) *.gcov
|
rm -f $(COVERAGE_FILES) *.gcov
|
||||||
rm -rf coverage_report/
|
rm -rf coverage_report/
|
||||||
rm -f coverage.info
|
rm -f coverage.info
|
||||||
|
|
||||||
|
clean: clean-coverage
|
||||||
|
$(MAKE) -C ../../mbedtls/mbedtls/ clean
|
||||||
|
rm -f $(OBJ_FILES) $(TEST_PROGRAM)
|
||||||
rm -f ../nvs_partition_generator/partition_single_page.bin
|
rm -f ../nvs_partition_generator/partition_single_page.bin
|
||||||
rm -f ../nvs_partition_generator/partition_multipage_blob.bin
|
rm -f ../nvs_partition_generator/partition_multipage_blob.bin
|
||||||
rm -f ../nvs_partition_generator/partition_encrypted.bin
|
rm -f ../nvs_partition_generator/partition_encrypted.bin
|
||||||
@@ -80,4 +94,4 @@ clean:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
.PHONY: clean all test long-test
|
.PHONY: clean clean-coverage all test long-test
|
||||||
|
@@ -71,10 +71,11 @@ static size_t blockEraseTime = 37142;
|
|||||||
|
|
||||||
static size_t timeInterp(uint32_t bytes, size_t* lut)
|
static size_t timeInterp(uint32_t bytes, size_t* lut)
|
||||||
{
|
{
|
||||||
|
const int lut_size = sizeof(readTimes)/sizeof(readTimes[0]);
|
||||||
int lz = __builtin_clz(bytes / 4);
|
int lz = __builtin_clz(bytes / 4);
|
||||||
int log_size = 32 - lz;
|
int log_size = 32 - lz;
|
||||||
size_t x2 = 1 << (log_size + 2);
|
size_t x2 = 1 << (log_size + 2);
|
||||||
size_t y2 = lut[log_size];
|
size_t y2 = lut[std::min(log_size, lut_size - 1)];
|
||||||
size_t x1 = 1 << (log_size + 1);
|
size_t x1 = 1 << (log_size + 1);
|
||||||
size_t y1 = lut[log_size - 1];
|
size_t y1 = lut[log_size - 1];
|
||||||
return (bytes - x1) * (y2 - y1) / (x2 - x1) + y1;
|
return (bytes - x1) * (y2 - y1) / (x2 - x1) + y1;
|
||||||
|
@@ -36,6 +36,7 @@ public:
|
|||||||
SpiFlashEmulator(size_t sectorCount) : mUpperSectorBound(sectorCount)
|
SpiFlashEmulator(size_t sectorCount) : mUpperSectorBound(sectorCount)
|
||||||
{
|
{
|
||||||
mData.resize(sectorCount * SPI_FLASH_SEC_SIZE / 4, 0xffffffff);
|
mData.resize(sectorCount * SPI_FLASH_SEC_SIZE / 4, 0xffffffff);
|
||||||
|
mEraseCnt.resize(sectorCount);
|
||||||
spi_flash_emulator_set(this);
|
spi_flash_emulator_set(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,6 +125,7 @@ public:
|
|||||||
std::fill_n(begin(mData) + offset, SPI_FLASH_SEC_SIZE / 4, 0xffffffff);
|
std::fill_n(begin(mData) + offset, SPI_FLASH_SEC_SIZE / 4, 0xffffffff);
|
||||||
|
|
||||||
++mEraseOps;
|
++mEraseOps;
|
||||||
|
mEraseCnt[sectorNumber]++;
|
||||||
mTotalTime += getEraseOpTime();
|
mTotalTime += getEraseOpTime();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -217,6 +219,10 @@ public:
|
|||||||
mFailCountdown = count;
|
mFailCountdown = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t getSectorEraseCount(uint32_t sector) const {
|
||||||
|
return mEraseCnt[sector];
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static size_t getReadOpTime(uint32_t bytes);
|
static size_t getReadOpTime(uint32_t bytes);
|
||||||
static size_t getWriteOpTime(uint32_t bytes);
|
static size_t getWriteOpTime(uint32_t bytes);
|
||||||
@@ -224,6 +230,7 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
std::vector<uint32_t> mData;
|
std::vector<uint32_t> mData;
|
||||||
|
std::vector<uint32_t> mEraseCnt;
|
||||||
|
|
||||||
mutable size_t mReadOps = 0;
|
mutable size_t mReadOps = 0;
|
||||||
mutable size_t mWriteOps = 0;
|
mutable size_t mWriteOps = 0;
|
||||||
|
@@ -258,7 +258,7 @@ TEST_CASE("Page validates blob size", "[nvs]")
|
|||||||
Page page;
|
Page page;
|
||||||
TEST_ESP_OK(page.load(0));
|
TEST_ESP_OK(page.load(0));
|
||||||
|
|
||||||
char buf[2048] = { 0 };
|
char buf[4096] = { 0 };
|
||||||
// There are two potential errors here:
|
// There are two potential errors here:
|
||||||
// - not enough space in the page (because one value has been written already)
|
// - not enough space in the page (because one value has been written already)
|
||||||
// - value is too long
|
// - value is too long
|
||||||
@@ -527,6 +527,35 @@ TEST_CASE("can modify an item on a page which will be erased", "[nvs]")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("erase operations are distributed among sectors", "[nvs]")
|
||||||
|
{
|
||||||
|
const size_t sectors = 6;
|
||||||
|
SpiFlashEmulator emu(sectors);
|
||||||
|
Storage storage;
|
||||||
|
CHECK(storage.init(0, sectors) == ESP_OK);
|
||||||
|
|
||||||
|
/* Fill some part of storage with static values */
|
||||||
|
const size_t static_sectors = 2;
|
||||||
|
for (size_t i = 0; i < static_sectors * Page::ENTRY_COUNT; ++i) {
|
||||||
|
char name[Item::MAX_KEY_LENGTH];
|
||||||
|
snprintf(name, sizeof(name), "static%d", (int) i);
|
||||||
|
REQUIRE(storage.writeItem(1, name, i) == ESP_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now perform many write operations */
|
||||||
|
const size_t write_ops = 2000;
|
||||||
|
for (size_t i = 0; i < write_ops; ++i) {
|
||||||
|
REQUIRE(storage.writeItem(1, "value", i) == ESP_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that erase counts are distributed between the remaining sectors */
|
||||||
|
const size_t max_erase_cnt = write_ops / Page::ENTRY_COUNT / (sectors - static_sectors) + 1;
|
||||||
|
for (size_t i = 0; i < sectors; ++i) {
|
||||||
|
auto erase_cnt = emu.getSectorEraseCount(i);
|
||||||
|
INFO("Sector " << i << " erased " << erase_cnt);
|
||||||
|
CHECK(erase_cnt <= max_erase_cnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("can erase items", "[nvs]")
|
TEST_CASE("can erase items", "[nvs]")
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user