mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-01 19:54:32 +02:00
Merge branch 'feature/linux_target' into 'master'
build system: Add Linux target Closes IDF-2145 See merge request espressif/esp-idf!10076
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
|
||||
set(srcs "src/nvs_api.cpp"
|
||||
"src/nvs_cxx_api.cpp"
|
||||
"src/nvs_item_hash_list.cpp"
|
||||
@@ -11,10 +13,39 @@ set(srcs "src/nvs_api.cpp"
|
||||
"src/nvs_partition_manager.cpp"
|
||||
"src/nvs_types.cpp")
|
||||
|
||||
if(CONFIG_NVS_ENCRYPTION)
|
||||
list(APPEND srcs "src/nvs_encrypted_partition.cpp")
|
||||
endif()
|
||||
set(public_req spi_flash)
|
||||
|
||||
set(include_dirs "include")
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
REQUIRES spi_flash mbedtls
|
||||
INCLUDE_DIRS include)
|
||||
REQUIRES "${public_req}"
|
||||
INCLUDE_DIRS "${include_dirs}")
|
||||
|
||||
# If we use the linux target, we need to redirect the crc functions to the linux
|
||||
if(${target} STREQUAL "linux")
|
||||
if(CONFIG_NVS_ENCRYPTION)
|
||||
# mbedtls isn't configured for building with linux or as mock target. It will draw in all kind of dependencies
|
||||
message(FATAL_ERROR "NVS currently doesn't support encryption if built for Linux.")
|
||||
endif()
|
||||
idf_component_get_property(spi_flash_dir spi_flash COMPONENT_DIR)
|
||||
target_include_directories(${COMPONENT_LIB} PUBLIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/mock/int"
|
||||
"${spi_flash_dir}/sim/stubs/freertos/include")
|
||||
target_sources(${COMPONENT_LIB} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/mock/int/crc.cpp")
|
||||
target_compile_options(${COMPONENT_LIB} PUBLIC "-DLINUX_TARGET")
|
||||
else()
|
||||
# TODO: this is a workaround until IDF-2085 is fixed
|
||||
idf_component_get_property(mbedtls_lib mbedtls COMPONENT_LIB)
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC ${mbedtls_lib})
|
||||
endif()
|
||||
|
||||
if(CONFIG_NVS_ENCRYPTION)
|
||||
target_sources(${COMPONENT_LIB} PRIVATE "src/nvs_encrypted_partition.cpp")
|
||||
idf_component_get_property(mbedtls_lib mbedtls COMPONENT_LIB)
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC ${mbedtls_lib})
|
||||
endif()
|
||||
|
||||
if(${target} STREQUAL "linux")
|
||||
target_compile_options(${COMPONENT_LIB} PUBLIC --coverage)
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC --coverage)
|
||||
endif()
|
||||
|
429
components/nvs_flash/host_test/fixtures/test_fixtures.hpp
Normal file
429
components/nvs_flash/host_test/fixtures/test_fixtures.hpp
Normal file
@@ -0,0 +1,429 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "nvs_partition.hpp"
|
||||
#include "nvs.h"
|
||||
#include "nvs_page.hpp"
|
||||
#include "nvs_storage.hpp"
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
#ifdef CONFIG_NVS_ENCRYPTION
|
||||
#include "nvs_encrypted_partition.hpp"
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include "Mockesp_partition.h"
|
||||
}
|
||||
|
||||
struct FixtureException : std::exception {
|
||||
FixtureException(const std::string& msg) : msg(msg) { }
|
||||
|
||||
const char *what() {
|
||||
return msg.c_str();
|
||||
}
|
||||
|
||||
std::string msg;
|
||||
};
|
||||
|
||||
class PartitionMock : public nvs::Partition {
|
||||
public:
|
||||
PartitionMock(uint32_t address, uint32_t size)
|
||||
: partition(), address(address), size(size)
|
||||
{
|
||||
assert(size);
|
||||
}
|
||||
|
||||
const char *get_partition_name() override
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
esp_err_t read_raw(size_t src_offset, void* dst, size_t size) override
|
||||
{
|
||||
return esp_partition_read_raw(&partition, src_offset, dst, size);
|
||||
}
|
||||
|
||||
esp_err_t read(size_t src_offset, void* dst, size_t size) override
|
||||
{
|
||||
return esp_partition_read(&partition, src_offset, dst, size);
|
||||
}
|
||||
|
||||
esp_err_t write_raw(size_t dst_offset, const void* src, size_t size) override
|
||||
{
|
||||
return esp_partition_write_raw(&partition, dst_offset, src, size);
|
||||
}
|
||||
|
||||
esp_err_t write(size_t dst_offset, const void* src, size_t size) override
|
||||
{
|
||||
return esp_partition_write(&partition, dst_offset, src, size);
|
||||
}
|
||||
|
||||
esp_err_t erase_range(size_t dst_offset, size_t size) override
|
||||
{
|
||||
return esp_partition_erase_range(&partition, dst_offset, size);
|
||||
}
|
||||
|
||||
uint32_t get_address() override
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
uint32_t get_size() override
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
const esp_partition_t partition;
|
||||
|
||||
private:
|
||||
uint32_t address;
|
||||
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_NVS_ENCRYPTION
|
||||
struct EncryptedPartitionFixture {
|
||||
EncryptedPartitionFixture(nvs_sec_cfg_t *cfg,
|
||||
uint32_t start_sector = 0,
|
||||
uint32_t sector_size = 1,
|
||||
const char *partition_name = NVS_DEFAULT_PART_NAME)
|
||||
: esp_partition(), emu(start_sector + sector_size),
|
||||
part(partition_name, &esp_partition) {
|
||||
esp_partition.address = start_sector * SPI_FLASH_SEC_SIZE;
|
||||
esp_partition.size = sector_size * SPI_FLASH_SEC_SIZE;
|
||||
assert(part.init(cfg) == ESP_OK);
|
||||
}
|
||||
|
||||
~EncryptedPartitionFixture() { }
|
||||
|
||||
esp_partition_t esp_partition;
|
||||
|
||||
SpiFlashEmulator emu;
|
||||
|
||||
nvs::NVSEncryptedPartition part;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct PartitionMockFixture {
|
||||
PartitionMockFixture(uint32_t start_sector = 0,
|
||||
uint32_t sector_size = 1,
|
||||
const char *partition_name = NVS_DEFAULT_PART_NAME)
|
||||
: part_mock(start_sector * SPI_FLASH_SEC_SIZE, sector_size * SPI_FLASH_SEC_SIZE) {
|
||||
std::fill_n(raw_header, sizeof(raw_header)/sizeof(raw_header[0]), UINT8_MAX);
|
||||
}
|
||||
|
||||
~PartitionMockFixture() { }
|
||||
|
||||
uint8_t raw_header[512];
|
||||
|
||||
PartitionMock part_mock;
|
||||
};
|
||||
|
||||
struct NVSPageFixture : public PartitionMockFixture {
|
||||
NVSPageFixture(uint32_t start_sector = 0,
|
||||
uint32_t sector_size = 1,
|
||||
const char *partition_name = NVS_DEFAULT_PART_NAME)
|
||||
: PartitionMockFixture(start_sector, sector_size, partition_name), page()
|
||||
{
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 32);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 512);
|
||||
}
|
||||
|
||||
if (page.load(&part_mock, start_sector) != ESP_OK) throw FixtureException("couldn't setup page");
|
||||
}
|
||||
|
||||
nvs::Page page;
|
||||
};
|
||||
|
||||
struct NVSValidPageFixture : public PartitionMockFixture {
|
||||
const static uint8_t NS_INDEX = 1;
|
||||
|
||||
// valid header
|
||||
uint8_t raw_header_valid [32];
|
||||
|
||||
// entry table with one entry
|
||||
uint8_t raw_entry_table [32];
|
||||
|
||||
uint8_t ns_entry [32];
|
||||
|
||||
uint8_t value_entry [32];
|
||||
|
||||
NVSValidPageFixture(uint32_t start_sector = 0,
|
||||
uint32_t sector_size = 1,
|
||||
const char *partition_name = NVS_DEFAULT_PART_NAME)
|
||||
: PartitionMockFixture(start_sector, sector_size, partition_name),
|
||||
raw_header_valid {0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x16, 0xdd, 0xdc},
|
||||
ns_entry {0x00, 0x01, 0x01, 0xff, 0x68, 0xc5, 0x3f, 0x0b, 't', 'e', 's', 't', '_', 'n', 's', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
value_entry {0x01, 0x01, 0x01, 0xff, 0x3d, 0xf3, 0x99, 0xe5, 't', 'e', 's', 't', '_', 'v', 'a', 'l',
|
||||
'u', 'e', '\0', '\0', '\0', '\0', '\0', '\0', 47, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
page()
|
||||
{
|
||||
std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0);
|
||||
raw_entry_table[0] = 0xfa;
|
||||
|
||||
// read page header
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header_valid, 32);
|
||||
|
||||
// read entry table
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_entry_table, 32);
|
||||
|
||||
// read next free entry's header
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 4);
|
||||
|
||||
// read namespace entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32);
|
||||
|
||||
// read normal entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(value_entry, 32);
|
||||
|
||||
// read normal entry second time during duplicated entry check
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(value_entry, 32);
|
||||
|
||||
if (page.load(&part_mock, start_sector) != ESP_OK) throw FixtureException("couldn't setup page");
|
||||
}
|
||||
|
||||
nvs::Page page;
|
||||
};
|
||||
|
||||
struct NVSValidStorageFixture : public PartitionMockFixture {
|
||||
const static uint8_t NS_INDEX = 1;
|
||||
|
||||
uint8_t ns_entry [32];
|
||||
|
||||
uint8_t empty_entry [32];
|
||||
|
||||
NVSValidStorageFixture(uint32_t start_sector = 0,
|
||||
uint32_t sector_size = 3,
|
||||
const char *partition_name = NVS_DEFAULT_PART_NAME)
|
||||
: PartitionMockFixture(start_sector, sector_size, partition_name),
|
||||
ns_entry {0x00, 0x01, 0x01, 0xff, 0x68, 0xc5, 0x3f, 0x0b, 't', 'e', 's', 't', '_', 'n', 's', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
empty_entry(),
|
||||
storage(&part_mock)
|
||||
{
|
||||
std::fill_n(empty_entry, sizeof(empty_entry)/sizeof(empty_entry[0]), 0xFF);
|
||||
|
||||
// entry table with one entry
|
||||
uint8_t raw_entry_table [32];
|
||||
|
||||
uint8_t header_full_page [] = {
|
||||
0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x16, 0xdd, 0xdc};
|
||||
|
||||
uint8_t header_second_page [] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
|
||||
uint8_t header_third_page [] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
|
||||
// entry_table with all elements deleted except the namespace entry written and the last entry free
|
||||
std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0);
|
||||
raw_entry_table[0] = 0x02;
|
||||
raw_entry_table[31] = 0xFC;
|
||||
|
||||
// read full page header
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(header_full_page, 32);
|
||||
|
||||
// read entry table
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_entry_table, 32);
|
||||
|
||||
// reading entry table checks empty entry
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(empty_entry, 32);
|
||||
|
||||
// read namespace entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32);
|
||||
|
||||
// read last two pages' headers, which trigger an automatic full read each because each page is empty
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(header_second_page, 32);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 512);
|
||||
}
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(header_third_page, 32);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 512);
|
||||
}
|
||||
|
||||
// read namespace entry in duplicated header item check of pagemanager::load
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32);
|
||||
|
||||
// storage finally actually reads namespace
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32);
|
||||
|
||||
// storage looks for blob index entries
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32);
|
||||
|
||||
// Storage::eraseOrphanDataBlobs() also wants to take it's turn...
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32);
|
||||
|
||||
if (storage.init(start_sector, sector_size) != ESP_OK) throw FixtureException("couldn't setup page");
|
||||
}
|
||||
|
||||
nvs::Storage storage;
|
||||
};
|
||||
|
||||
struct NVSValidBlobPageFixture : public PartitionMockFixture {
|
||||
const static uint8_t NS_INDEX = 1;
|
||||
const static size_t BLOB_DATA_SIZE = 32;
|
||||
|
||||
// valid header
|
||||
uint8_t raw_header_valid [32];
|
||||
|
||||
// entry table with one entry
|
||||
uint8_t raw_entry_table [32];
|
||||
|
||||
uint8_t ns_entry [32];
|
||||
|
||||
uint8_t blob_entry [32];
|
||||
uint8_t blob_data [BLOB_DATA_SIZE];
|
||||
uint8_t blob_index [32];
|
||||
|
||||
NVSValidBlobPageFixture(uint32_t start_sector = 0,
|
||||
uint32_t sector_size = 1,
|
||||
const char *partition_name = NVS_DEFAULT_PART_NAME)
|
||||
: PartitionMockFixture(start_sector, sector_size, partition_name),
|
||||
raw_header_valid {0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x16, 0xdd, 0xdc},
|
||||
ns_entry {0x00, 0x01, 0x01, 0xff, 0x68, 0xc5, 0x3f, 0x0b, 't', 'e', 's', 't', '_', 'n', 's', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
blob_entry {0x01, 0x42, 0x02, 0x00, 0xaa, 0xf3, 0x23, 0x87, 't', 'e', 's', 't', '_', 'b', 'l', 'o',
|
||||
'b', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 0x20, 0x00, 0xff, 0xff, 0xc6, 0x96, 0x86, 0xd9},
|
||||
blob_data {0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef},
|
||||
blob_index {0x01, 0x48, 0x01, 0xff, 0x42, 0x6b, 0xdf, 0x66, 't', 'e', 's', 't', '_', 'b', 'l', 'o',
|
||||
'b', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0xff, 0xff},
|
||||
page()
|
||||
{
|
||||
std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0xFF);
|
||||
raw_entry_table[0] = 0xaa;
|
||||
|
||||
// read page header
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header_valid, 32);
|
||||
|
||||
// read entry table
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_entry_table, 32);
|
||||
|
||||
// read next free entry's header
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 4);
|
||||
|
||||
// read namespace entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32);
|
||||
|
||||
// read normal blob entry + index, not the data
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(blob_entry, 32);
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(blob_index, 32);
|
||||
|
||||
// read normal entry second time during duplicated entry check
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(blob_entry, 32);
|
||||
|
||||
if (page.load(&part_mock, start_sector) != ESP_OK) throw FixtureException("couldn't setup page");
|
||||
}
|
||||
|
||||
nvs::Page page;
|
||||
};
|
||||
|
||||
struct NVSFullPageFixture : public PartitionMockFixture {
|
||||
const static uint8_t NS_INDEX = 1;
|
||||
|
||||
// valid header
|
||||
uint8_t raw_header_valid [32];
|
||||
|
||||
// entry table with one entry
|
||||
uint8_t raw_entry_table [32];
|
||||
|
||||
uint8_t ns_entry [32];
|
||||
|
||||
uint8_t value_entry [32];
|
||||
|
||||
NVSFullPageFixture(uint32_t start_sector = 0,
|
||||
uint32_t sector_size = 1,
|
||||
const char *partition_name = NVS_DEFAULT_PART_NAME,
|
||||
bool load = true)
|
||||
: PartitionMockFixture(start_sector, sector_size, partition_name),
|
||||
raw_header_valid {0xfc, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa3, 0x48, 0x9f, 0x38},
|
||||
ns_entry {0x00, 0x01, 0x01, 0xff, 0x68, 0xc5, 0x3f, 0x0b, 't', 'e', 's', 't', '_', 'n', 's', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
value_entry {0x01, 0x01, 0x01, 0xff, 0x3d, 0xf3, 0x99, 0xe5, 't', 'e', 's', 't', '_', 'v', 'a', 'l',
|
||||
'u', 'e', '\0', '\0', '\0', '\0', '\0', '\0', 47, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
page()
|
||||
{
|
||||
std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0);
|
||||
raw_entry_table[0] = 0xfa;
|
||||
|
||||
// entry_table with all elements deleted except the namespace entry written and the last entry free
|
||||
std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0);
|
||||
raw_entry_table[0] = 0x0a;
|
||||
raw_entry_table[31] = 0xFC;
|
||||
|
||||
// read page header
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header_valid, 32);
|
||||
|
||||
// read entry table
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_entry_table, 32);
|
||||
|
||||
// no next free entry check, only one entry written
|
||||
|
||||
// read namespace entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32);
|
||||
|
||||
// read normal entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(value_entry, 32);
|
||||
|
||||
// no duplicated entry check
|
||||
|
||||
if (load) {
|
||||
if (page.load(&part_mock, start_sector) != ESP_OK) throw FixtureException("couldn't setup page");
|
||||
}
|
||||
}
|
||||
|
||||
nvs::Page page;
|
||||
};
|
27
components/nvs_flash/host_test/nvs_page_test/CMakeLists.txt
Normal file
27
components/nvs_flash/host_test/nvs_page_test/CMakeLists.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
set(COMPONENTS main)
|
||||
idf_build_set_property(CONFIG_SPI_FLASH_MOCK 1)
|
||||
idf_build_set_property(COMPILE_DEFINITIONS "-DNO_DEBUG_STORAGE" APPEND)
|
||||
project(host_nvs_page_test)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/build/coverage.info"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build"
|
||||
COMMAND lcov --capture --directory . --output-file coverage.info
|
||||
COMMENT "Create coverage report"
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/build/coverage_report/"
|
||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/build/coverage.info"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build"
|
||||
COMMAND genhtml coverage.info --output-directory coverage_report/
|
||||
COMMENT "Turn coverage report into html-based visualization"
|
||||
)
|
||||
|
||||
add_custom_target(coverage
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build"
|
||||
DEPENDS "coverage_report/"
|
||||
)
|
23
components/nvs_flash/host_test/nvs_page_test/README.rst
Normal file
23
components/nvs_flash/host_test/nvs_page_test/README.rst
Normal file
@@ -0,0 +1,23 @@
|
||||
NVS Page Test for Host
|
||||
======================
|
||||
|
||||
Build
|
||||
-----
|
||||
|
||||
First, make sure that the target is set to linux.
|
||||
Run ``idf.py --preview set-target linux`` to be sure.
|
||||
Then do a normal IDF build: ``idf.py build``.
|
||||
|
||||
Run
|
||||
---
|
||||
|
||||
IDF monitor doesn't work yet for Linux.
|
||||
You have to run the app manually: ``./build/host_nvs_page_test.elf``.
|
||||
|
||||
Coverage
|
||||
---
|
||||
|
||||
To generate the coverage, run: ``idf.py coverage``.
|
||||
Afterwards, you can view the coverage by opening ``build/coverage_report/index.html`` with your browser.
|
||||
Note that you need to run the application at least once before generating the coverage information.
|
||||
If you run it multiple times, the coverage information adds up.
|
@@ -0,0 +1,10 @@
|
||||
idf_component_register(SRCS "nvs_page_test.cpp"
|
||||
INCLUDE_DIRS
|
||||
"."
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../fixtures"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../../test_nvs_host"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../../src"
|
||||
REQUIRES cmock nvs_flash spi_flash)
|
||||
|
||||
target_compile_options(${COMPONENT_LIB} PUBLIC --coverage)
|
||||
target_link_libraries(${COMPONENT_LIB} --coverage)
|
@@ -0,0 +1,934 @@
|
||||
/* Hello World Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "unity.h"
|
||||
#include "test_fixtures.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "Mockesp_partition.h"
|
||||
}
|
||||
|
||||
using namespace std;
|
||||
using namespace nvs;
|
||||
|
||||
void test_Page_load_reading_header_fails()
|
||||
{
|
||||
PartitionMock mock(0, 4096);
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_ERR_INVALID_ARG);
|
||||
Page page;
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state());
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, page.load(&mock, 0));
|
||||
}
|
||||
|
||||
void test_Page_load_reading_data_fails()
|
||||
{
|
||||
uint8_t header[64];
|
||||
std::fill_n(header, sizeof(header)/sizeof(header[0]), UINT8_MAX);
|
||||
PartitionMock mock(0, 4096);
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(header, 32);
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_FAIL);
|
||||
Page page;
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state());
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, page.load(&mock, 0));
|
||||
}
|
||||
|
||||
void test_Page_load__uninitialized_page_has_0xfe()
|
||||
{
|
||||
PartitionMockFixture fix;
|
||||
Page page;
|
||||
|
||||
fix.raw_header[511] = 0xfe;
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(fix.raw_header, 32);
|
||||
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(fix.raw_header, 512);
|
||||
|
||||
// Page::load() should return ESP_OK, but state has to be corrupt
|
||||
TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::CORRUPT, page.state());
|
||||
}
|
||||
|
||||
void test_Page_load__initialized_corrupt_header()
|
||||
{
|
||||
PartitionMockFixture fix;
|
||||
Page page;
|
||||
|
||||
uint8_t raw_header_corrupt [] = {0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x16, 0xdd, 0xdc};
|
||||
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header_corrupt, 32);
|
||||
|
||||
// Page::load() should return ESP_OK, but state has to be corrupt
|
||||
TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::CORRUPT, page.state());
|
||||
}
|
||||
|
||||
void test_Page_load_success()
|
||||
{
|
||||
PartitionMockFixture fix;
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(fix.raw_header, 32);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(fix.raw_header, 512);
|
||||
}
|
||||
Page page;
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state());
|
||||
TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0));
|
||||
TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, page.state());
|
||||
}
|
||||
|
||||
void test_Page_load_full_page()
|
||||
{
|
||||
NVSFullPageFixture fix(0, 1, NVS_DEFAULT_PART_NAME, false);
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state());
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.load(&fix.part_mock, 0));
|
||||
TEST_ASSERT_EQUAL(Page::PageState::FULL, fix.page.state());
|
||||
}
|
||||
void test_Page_load__seq_number_0()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
uint32_t seq_num;
|
||||
fix.page.getSeqNumber(seq_num);
|
||||
TEST_ASSERT_EQUAL(0, seq_num);
|
||||
}
|
||||
|
||||
void test_Page_erase__write_fail()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
esp_partition_erase_range_ExpectAndReturn(&fix.part_mock.partition, 0, 4096, ESP_FAIL);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.erase());
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_erase__success()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
esp_partition_erase_range_ExpectAndReturn(&fix.part_mock.partition, 0, 4096, ESP_OK);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.erase());
|
||||
TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_write__initialize_write_failure()
|
||||
{
|
||||
PartitionMockFixture fix;
|
||||
uint8_t write_data = 47;
|
||||
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(fix.raw_header, 32);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(fix.raw_header, 512);
|
||||
}
|
||||
esp_partition_write_raw_ExpectAnyArgsAndReturn(ESP_FAIL);
|
||||
|
||||
Page page;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0));
|
||||
TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, page.state());
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, page.writeItem(1, nvs::ItemType::U8, "test", &write_data, sizeof(write_data)));
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state());
|
||||
}
|
||||
|
||||
void test_Page_write__write_data_fails()
|
||||
{
|
||||
NVSPageFixture fix;
|
||||
uint8_t write_data = 47;
|
||||
esp_partition_write_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_write_ExpectAnyArgsAndReturn(ESP_FAIL);
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state());
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.writeItem(1, nvs::ItemType::U8, "test", &write_data, sizeof(write_data)));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state());
|
||||
}
|
||||
|
||||
void test_page_write__write_correct_entry_state()
|
||||
{
|
||||
NVSPageFixture fix;
|
||||
uint8_t write_data = 47;
|
||||
uint8_t raw_result [4];
|
||||
std::fill_n(raw_result, sizeof(raw_result)/sizeof(raw_result[0]), UINT8_MAX);
|
||||
// mark first entry as written
|
||||
raw_result[0] = 0xfe;
|
||||
|
||||
// initialize page
|
||||
esp_partition_write_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
|
||||
// write entry
|
||||
esp_partition_write_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
|
||||
// write entry state
|
||||
esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 32, raw_result, 4, 4, ESP_OK);
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state());
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.writeItem(1, nvs::ItemType::U8, "test_key", &write_data, sizeof(write_data)));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_write__write_correct_data()
|
||||
{
|
||||
NVSPageFixture fix;
|
||||
uint8_t write_data = 47;
|
||||
uint8_t raw_result [32] = {0x01, 0x01, 0x01, 0xff, 0x98, 0x6f, 0x21, 0xfd, 't', 'e', 's', 't', '_', 'k', 'e', 'y',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 47, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
|
||||
// initialize page
|
||||
esp_partition_write_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
|
||||
// write entry
|
||||
esp_partition_write_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 64, raw_result, 32, 32, ESP_OK);
|
||||
|
||||
// write entry state
|
||||
esp_partition_write_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state());
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.writeItem(1, nvs::ItemType::U8, "test_key", &write_data, sizeof(write_data)));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_readItem__read_entry_fails()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
uint8_t read_value = 0;
|
||||
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_FAIL);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.readItem(NVSValidPageFixture::NS_INDEX, "test_value", read_value));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state());
|
||||
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
}
|
||||
|
||||
void test_Page_readItem__read_corrupted_entry()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
uint8_t read_value = 0;
|
||||
|
||||
// corrupting entry
|
||||
fix.value_entry[0] = 0x0;
|
||||
|
||||
// first read the entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
// Page::eraseEntryAndSpan() reads entry again
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
// erasing entry by setting bit in entry table (0xfa -> 0xf2)
|
||||
uint8_t raw_result [4] = {0xf2, 0x00, 0x00, 0x00};
|
||||
esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 32, raw_result, 4, 4, ESP_OK);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, fix.page.readItem(NVSValidPageFixture::NS_INDEX, "test_value", read_value));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
TEST_ASSERT_EQUAL(1, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(123, fix.page.getErasedEntryCount());
|
||||
}
|
||||
|
||||
void test_Page_readItem__read_corrupted_second_read_fail()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
uint8_t read_value = 0;
|
||||
|
||||
// corrupting entry
|
||||
fix.value_entry[0] = 0x0;
|
||||
|
||||
// first read the entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
// Page::eraseEntryAndSpan() reads entry again
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_FAIL);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.readItem(NVSValidPageFixture::NS_INDEX, "test_value", read_value));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_readItem__read_corrupted_erase_fail()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
uint8_t read_value = 0;
|
||||
|
||||
// corrupting entry
|
||||
fix.value_entry[0] = 0x0;
|
||||
|
||||
// first read the entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
// Page::eraseEntryAndSpan() reads entry again
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
// erasing entry by setting bit in entry table (0xfa -> 0xf2)
|
||||
uint8_t raw_result [4] = {0xf2, 0x00, 0x00, 0x00};
|
||||
esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 32, raw_result, 4, 4, ESP_FAIL);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.readItem(NVSValidPageFixture::NS_INDEX, "test_value", read_value));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_readItem__read_entry_suceeds()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
uint8_t read_value = 0;
|
||||
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.readItem(NVSValidPageFixture::NS_INDEX, "test_value", read_value));
|
||||
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(47, read_value);
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_readItem__blob_read_data_fails()
|
||||
{
|
||||
NVSValidBlobPageFixture fix;
|
||||
TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
uint8_t chunk_start = 0;
|
||||
uint8_t read_data [32];
|
||||
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_entry, 32);
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_FAIL);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.readItem(NVSValidPageFixture::NS_INDEX,
|
||||
ItemType::BLOB_DATA,
|
||||
"test_blob",
|
||||
read_data,
|
||||
32,
|
||||
chunk_start));
|
||||
|
||||
TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_readItem__corrupt_data_erase_failure()
|
||||
{
|
||||
NVSValidBlobPageFixture fix;
|
||||
TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
uint8_t chunk_start = 0;
|
||||
uint8_t read_data [32];
|
||||
|
||||
fix.blob_data[16] = 0xdf;
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_entry, 32);
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE);
|
||||
|
||||
// Page::eraseEntryAndSpan() reads entry again
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_FAIL);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.readItem(NVSValidPageFixture::NS_INDEX,
|
||||
ItemType::BLOB_DATA,
|
||||
"test_blob",
|
||||
read_data,
|
||||
32,
|
||||
chunk_start));
|
||||
|
||||
TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_readItem__blob_corrupt_data()
|
||||
{
|
||||
NVSValidBlobPageFixture fix;
|
||||
TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
uint8_t chunk_start = 0;
|
||||
uint8_t read_data [32];
|
||||
|
||||
fix.blob_data[16] = 0xdf;
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_entry, 32);
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE);
|
||||
|
||||
// Page::eraseEntryAndSpan() reads entry again
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE);
|
||||
|
||||
// erasing entry by setting bit in entry table (0xfa -> 0xf2)
|
||||
uint8_t raw_result [4] = {0xa2, 0xff, 0xff, 0xff};
|
||||
esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 32, raw_result, 4, 4, ESP_OK);
|
||||
|
||||
esp_partition_erase_range_ExpectAndReturn(&fix.part_mock.partition, 96, 64, ESP_OK);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, fix.page.readItem(NVSValidPageFixture::NS_INDEX,
|
||||
ItemType::BLOB_DATA,
|
||||
"test_blob",
|
||||
read_data,
|
||||
32,
|
||||
chunk_start));
|
||||
|
||||
TEST_ASSERT_EQUAL(3, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(1, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_readItem__blob_read_entry_suceeds()
|
||||
{
|
||||
NVSValidBlobPageFixture fix;
|
||||
TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
uint8_t chunk_start = 0;
|
||||
uint8_t read_data [32];
|
||||
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_entry, 32);
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.readItem(NVSValidPageFixture::NS_INDEX,
|
||||
ItemType::BLOB_DATA,
|
||||
"test_blob",
|
||||
read_data,
|
||||
32,
|
||||
chunk_start));
|
||||
|
||||
TEST_ASSERT_EQUAL_MEMORY(fix.blob_data, read_data, fix.BLOB_DATA_SIZE);
|
||||
|
||||
// make sure nothing was erased, i.e. checksums matched
|
||||
TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_cmp__uninitialized()
|
||||
{
|
||||
Page page;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_INVALID_STATE, page.cmpItem(uint8_t(1) , "test", 47));
|
||||
}
|
||||
|
||||
void test_Page_cmp__item_not_found()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
// no expectations here since comparison uses the item hash list
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, fix.page.cmpItem(uint8_t(1), "different", 47));
|
||||
}
|
||||
|
||||
void test_Page_cmp__item_type_mismatch()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
// read normal entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_TYPE_MISMATCH, fix.page.cmpItem(uint8_t(1), "test_value", int(47)));
|
||||
}
|
||||
|
||||
void test_Page_cmp__item_content_mismatch()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
// read normal entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_CONTENT_DIFFERS, fix.page.cmpItem(uint8_t(1), "test_value", uint8_t(46)));
|
||||
}
|
||||
|
||||
void test_Page_cmp__item_content_match()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
// read normal entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.cmpItem(NVSValidPageFixture::NS_INDEX, "test_value", uint8_t(47)));
|
||||
}
|
||||
|
||||
void test_Page_cmpItem__blob_data_mismatch()
|
||||
{
|
||||
NVSValidBlobPageFixture fix;
|
||||
|
||||
// read blob entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_entry, 32);
|
||||
|
||||
// read blob data
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE);
|
||||
|
||||
|
||||
uint8_t blob_data_different [] =
|
||||
{0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xee};
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_CONTENT_DIFFERS,
|
||||
fix.page.cmpItem(uint8_t(1),
|
||||
ItemType::BLOB_DATA,
|
||||
"test_blob",
|
||||
blob_data_different,
|
||||
32));
|
||||
}
|
||||
|
||||
void test_Page_cmpItem__blob_data_match()
|
||||
{
|
||||
NVSValidBlobPageFixture fix;
|
||||
|
||||
// read blob entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_entry, 32);
|
||||
|
||||
// read blob data
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE);
|
||||
|
||||
|
||||
uint8_t blob_data_same [] =
|
||||
{0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef};
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK,
|
||||
fix.page.cmpItem(NVSValidPageFixture::NS_INDEX,
|
||||
ItemType::BLOB_DATA,
|
||||
"test_blob",
|
||||
blob_data_same,
|
||||
32));
|
||||
}
|
||||
|
||||
void test_Page_eraseItem__uninitialized()
|
||||
{
|
||||
Page page;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, page.eraseItem<uint8_t>(NVSValidPageFixture::NS_INDEX, "test_value"));
|
||||
}
|
||||
|
||||
void test_Page_eraseItem__key_not_found()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, fix.page.eraseItem<uint8_t>(NVSValidPageFixture::NS_INDEX, "different"));
|
||||
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_eraseItem__write_fail()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
// first read the entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
// Page::eraseEntryAndSpan() reads entry again
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
// erasing entry by setting bit in entry table (0xfa -> 0xf2)
|
||||
uint8_t raw_result [4] = {0xf2, 0x00, 0x00, 0x00};
|
||||
esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 32, raw_result, 4, 4, ESP_FAIL);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.eraseItem<uint8_t>(NVSValidPageFixture::NS_INDEX, "test_value"));
|
||||
|
||||
TEST_ASSERT_EQUAL(1, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(123, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_eraseItem__write_succeed()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
// first read the entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
// Page::eraseEntryAndSpan() reads entry again
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
// erasing entry by setting bit in entry table (0xfa -> 0xf2)
|
||||
uint8_t raw_result [4] = {0xf2, 0x00, 0x00, 0x00};
|
||||
esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 32, raw_result, 4, 4, ESP_OK);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.eraseItem<uint8_t>(NVSValidPageFixture::NS_INDEX, "test_value"));
|
||||
|
||||
TEST_ASSERT_EQUAL(1, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(123, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_findItem__uninitialized()
|
||||
{
|
||||
Page page;
|
||||
|
||||
size_t index = 0;
|
||||
Item item;
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND,
|
||||
page.findItem(NVSValidPageFixture::NS_INDEX, nvs::ItemType::U8, "test_value", index, item));
|
||||
}
|
||||
|
||||
void test_Page_find__wrong_ns()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
size_t index = 0;
|
||||
Item item;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND,
|
||||
fix.page.findItem(NVSValidPageFixture::NS_INDEX + 1, nvs::ItemType::U8, "test_value", index, item));
|
||||
}
|
||||
|
||||
void test_Page_find__wrong_type()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
size_t index = 0;
|
||||
Item item;
|
||||
|
||||
// read normal entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_TYPE_MISMATCH,
|
||||
fix.page.findItem(NVSValidPageFixture::NS_INDEX, nvs::ItemType::I8, "test_value", index, item));
|
||||
}
|
||||
|
||||
void test_Page_find__key_empty()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
size_t index = 0;
|
||||
Item item;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND,
|
||||
fix.page.findItem(NVSValidPageFixture::NS_INDEX, nvs::ItemType::U8, "", index, item));
|
||||
}
|
||||
|
||||
void test_Page_find__wrong_key()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
size_t index = 0;
|
||||
Item item;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND,
|
||||
fix.page.findItem(NVSValidPageFixture::NS_INDEX, nvs::ItemType::U8, "different", index, item));
|
||||
}
|
||||
|
||||
void test_Page_find__too_large_index()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
size_t index = 2;
|
||||
Item item;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND,
|
||||
fix.page.findItem(NVSValidPageFixture::NS_INDEX, nvs::ItemType::U8, "test_value", index, item));
|
||||
}
|
||||
|
||||
void test_Page_findItem__without_read()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND,
|
||||
fix.page.findItem(NVSValidPageFixture::NS_INDEX, nvs::ItemType::U8, "different"));
|
||||
}
|
||||
|
||||
void test_Page_markFull__wrong_state()
|
||||
{
|
||||
NVSPageFixture fix;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_INVALID_STATE, fix.page.markFull());
|
||||
TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_markFull__success()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
Page::PageState expected_state = Page::PageState::FULL;
|
||||
|
||||
esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, sizeof(fix.part_mock.partition), 0, &expected_state, sizeof(expected_state), 4, ESP_OK);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.markFull());
|
||||
TEST_ASSERT_EQUAL(Page::PageState::FULL, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_markFull__write_fail()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
Page::PageState expected_state = Page::PageState::FREEING;
|
||||
|
||||
esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, sizeof(fix.part_mock.partition), 0, &expected_state, sizeof(expected_state), 4, ESP_FAIL);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.markFreeing());
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_markFreeing__wrong_state()
|
||||
{
|
||||
NVSPageFixture fix;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_INVALID_STATE, fix.page.markFreeing());
|
||||
TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_markFreeing__success()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
Page::PageState expected_state = Page::PageState::FREEING;
|
||||
|
||||
esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, sizeof(fix.part_mock.partition), 0, &expected_state, sizeof(expected_state), 4, ESP_OK);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.markFreeing());
|
||||
TEST_ASSERT_EQUAL(Page::PageState::FREEING, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_getVarDataTailroom__uninitialized_page()
|
||||
{
|
||||
NVSPageFixture fix;
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::CHUNK_MAX_SIZE, fix.page.getVarDataTailroom());
|
||||
}
|
||||
|
||||
void test_Page_getVarDataTailroom__success()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
// blob data item, written namespace item, written normal item: 3 items
|
||||
TEST_ASSERT_EQUAL((Page::ENTRY_COUNT - 3) * Page::ENTRY_SIZE, fix.page.getVarDataTailroom());
|
||||
}
|
||||
|
||||
void test_Page_calcEntries__uninit()
|
||||
{
|
||||
NVSPageFixture fix;
|
||||
TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state());
|
||||
|
||||
nvs_stats_t nvsStats = {0, 0, 0, 0};
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.calcEntries(nvsStats));
|
||||
TEST_ASSERT_EQUAL(0, nvsStats.used_entries);
|
||||
TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.free_entries);
|
||||
TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.total_entries);
|
||||
TEST_ASSERT_EQUAL(0, nvsStats.namespace_count);
|
||||
}
|
||||
|
||||
void test_Page_calcEntries__corrupt()
|
||||
{
|
||||
PartitionMockFixture fix;
|
||||
Page page;
|
||||
|
||||
uint8_t raw_header_corrupt [] = {0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x16, 0xdd, 0xdc};
|
||||
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header_corrupt, 32);
|
||||
|
||||
// Page::load() should return ESP_OK, but state has to be corrupt
|
||||
TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::CORRUPT, page.state());
|
||||
|
||||
nvs_stats_t nvsStats = {0, 0, 0, 0};
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, page.calcEntries(nvsStats));
|
||||
TEST_ASSERT_EQUAL(0, nvsStats.used_entries);
|
||||
TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.free_entries);
|
||||
TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.total_entries);
|
||||
TEST_ASSERT_EQUAL(0, nvsStats.namespace_count);
|
||||
}
|
||||
|
||||
void test_Page_calcEntries__active_wo_blob()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
nvs_stats_t nvsStats = {0, 0, 0, 0};
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.calcEntries(nvsStats));
|
||||
TEST_ASSERT_EQUAL(2, nvsStats.used_entries);
|
||||
TEST_ASSERT_EQUAL(124, nvsStats.free_entries);
|
||||
TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.total_entries);
|
||||
TEST_ASSERT_EQUAL(0, nvsStats.namespace_count);
|
||||
}
|
||||
|
||||
void test_Page_calcEntries__active_with_blob()
|
||||
{
|
||||
NVSValidBlobPageFixture fix;
|
||||
|
||||
nvs_stats_t nvsStats = {0, 0, 0, 0};
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.calcEntries(nvsStats));
|
||||
TEST_ASSERT_EQUAL(4, nvsStats.used_entries);
|
||||
TEST_ASSERT_EQUAL(122, nvsStats.free_entries);
|
||||
TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.total_entries);
|
||||
TEST_ASSERT_EQUAL(0, nvsStats.namespace_count);
|
||||
}
|
||||
|
||||
void test_Page_calcEntries__invalid()
|
||||
{
|
||||
Page page;
|
||||
|
||||
nvs_stats_t nvsStats = {0, 0, 0, 0};
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state());
|
||||
|
||||
// total entries always get updated
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, page.calcEntries(nvsStats));
|
||||
TEST_ASSERT_EQUAL(0, nvsStats.used_entries);
|
||||
TEST_ASSERT_EQUAL(0, nvsStats.free_entries);
|
||||
TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.total_entries);
|
||||
TEST_ASSERT_EQUAL(0, nvsStats.namespace_count);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(test_Page_load_reading_header_fails);
|
||||
RUN_TEST(test_Page_load_reading_data_fails);
|
||||
RUN_TEST(test_Page_load__uninitialized_page_has_0xfe);
|
||||
RUN_TEST(test_Page_load__initialized_corrupt_header);
|
||||
RUN_TEST(test_Page_load_success);
|
||||
RUN_TEST(test_Page_load_full_page);
|
||||
RUN_TEST(test_Page_load__seq_number_0);
|
||||
RUN_TEST(test_Page_erase__write_fail);
|
||||
RUN_TEST(test_Page_erase__success);
|
||||
RUN_TEST(test_Page_write__initialize_write_failure);
|
||||
RUN_TEST(test_Page_write__write_data_fails);
|
||||
RUN_TEST(test_page_write__write_correct_entry_state);
|
||||
RUN_TEST(test_Page_write__write_correct_data);
|
||||
RUN_TEST(test_Page_readItem__read_entry_fails);
|
||||
RUN_TEST(test_Page_readItem__read_corrupted_entry);
|
||||
RUN_TEST(test_Page_readItem__read_corrupted_second_read_fail);
|
||||
RUN_TEST(test_Page_readItem__read_corrupted_erase_fail);
|
||||
RUN_TEST(test_Page_readItem__read_entry_suceeds);
|
||||
RUN_TEST(test_Page_readItem__blob_read_data_fails);
|
||||
RUN_TEST(test_Page_readItem__blob_corrupt_data);
|
||||
RUN_TEST(test_Page_readItem__blob_read_entry_suceeds);
|
||||
RUN_TEST(test_Page_cmp__uninitialized);
|
||||
RUN_TEST(test_Page_cmp__item_not_found);
|
||||
RUN_TEST(test_Page_cmp__item_type_mismatch);
|
||||
RUN_TEST(test_Page_cmp__item_content_mismatch);
|
||||
RUN_TEST(test_Page_cmp__item_content_match);
|
||||
RUN_TEST(test_Page_cmpItem__blob_data_mismatch);
|
||||
RUN_TEST(test_Page_cmpItem__blob_data_match);
|
||||
RUN_TEST(test_Page_eraseItem__uninitialized);
|
||||
RUN_TEST(test_Page_eraseItem__key_not_found);
|
||||
RUN_TEST(test_Page_eraseItem__write_fail);
|
||||
RUN_TEST(test_Page_readItem__corrupt_data_erase_failure);
|
||||
RUN_TEST(test_Page_eraseItem__write_succeed);
|
||||
RUN_TEST(test_Page_findItem__uninitialized);
|
||||
RUN_TEST(test_Page_find__wrong_ns);
|
||||
RUN_TEST(test_Page_find__wrong_type);
|
||||
RUN_TEST(test_Page_find__key_empty);
|
||||
RUN_TEST(test_Page_find__wrong_key);
|
||||
RUN_TEST(test_Page_find__too_large_index);
|
||||
RUN_TEST(test_Page_findItem__without_read);
|
||||
RUN_TEST(test_Page_markFull__wrong_state);
|
||||
RUN_TEST(test_Page_markFreeing__wrong_state);
|
||||
RUN_TEST(test_Page_markFull__success);
|
||||
RUN_TEST(test_Page_markFreeing__success);
|
||||
RUN_TEST(test_Page_markFull__write_fail);
|
||||
RUN_TEST(test_Page_getVarDataTailroom__uninitialized_page);
|
||||
RUN_TEST(test_Page_getVarDataTailroom__success);
|
||||
RUN_TEST(test_Page_calcEntries__uninit);
|
||||
RUN_TEST(test_Page_calcEntries__corrupt);
|
||||
RUN_TEST(test_Page_calcEntries__active_wo_blob);
|
||||
RUN_TEST(test_Page_calcEntries__active_with_blob);
|
||||
RUN_TEST(test_Page_calcEntries__invalid);
|
||||
UNITY_END();
|
||||
return 0;
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n
|
||||
CONFIG_IDF_TARGET="linux"
|
||||
CONFIG_CXX_EXCEPTIONS=y
|
@@ -52,7 +52,7 @@ static const unsigned int crc32_le_table[256] = {
|
||||
|
||||
|
||||
|
||||
extern "C" unsigned int crc32_le(unsigned int crc, unsigned char const * buf,unsigned int len)
|
||||
extern "C" uint32_t esp_rom_crc32_le(unsigned int crc, unsigned char const * buf,unsigned int len)
|
||||
{
|
||||
unsigned int i;
|
||||
crc = ~crc;
|
@@ -20,7 +20,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
uint32_t crc32_le(uint32_t crc, const uint8_t* buf, size_t len);
|
||||
/**
|
||||
* Mock function to replace ESP ROM function used in IDF with a Linux implementation.
|
||||
* Note: the name MUST have the prefix esp_rom_* since tools/ci/check_rom_apis.sh checks and complains otherwise.
|
||||
*/
|
||||
uint32_t esp_rom_crc32_le(uint32_t crc, const uint8_t* buf, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
@@ -35,7 +35,7 @@ public:
|
||||
|
||||
Tenum get(size_t index) const
|
||||
{
|
||||
assert(index >= 0 && index < Nitems);
|
||||
assert(index < Nitems);
|
||||
size_t wordIndex = index / ITEMS_PER_WORD;
|
||||
size_t offset = (index % ITEMS_PER_WORD) * Nbits;
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
|
||||
void set(size_t index, Tenum val)
|
||||
{
|
||||
assert(index >= 0 && index < Nitems);
|
||||
assert(index < Nitems);
|
||||
size_t wordIndex = index / ITEMS_PER_WORD;
|
||||
size_t offset = (index % ITEMS_PER_WORD) * Nbits;
|
||||
|
||||
|
@@ -22,17 +22,17 @@
|
||||
#include <functional>
|
||||
#include "nvs_handle_simple.hpp"
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#ifdef LINUX_TARGET
|
||||
#include "crc.h"
|
||||
#define ESP_LOGD(...)
|
||||
#else // LINUX_TARGET
|
||||
#include <esp32/rom/crc.h>
|
||||
|
||||
// Uncomment this line to force output from this module
|
||||
// #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
#include "esp_log.h"
|
||||
static const char* TAG = "nvs";
|
||||
#else
|
||||
#include "crc.h"
|
||||
#define ESP_LOGD(...)
|
||||
#endif
|
||||
#endif // ! LINUX_TARGET
|
||||
|
||||
class NVSHandleEntry : public intrusive_list_node<NVSHandleEntry> {
|
||||
public:
|
||||
@@ -56,9 +56,9 @@ uint32_t NVSHandleEntry::s_nvs_next_handle;
|
||||
|
||||
extern "C" void nvs_dump(const char *partName);
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#ifndef LINUX_TARGET
|
||||
SemaphoreHandle_t nvs::Lock::mSemaphore = nullptr;
|
||||
#endif
|
||||
#endif // ! LINUX_TARGET
|
||||
|
||||
using namespace std;
|
||||
using namespace nvs;
|
||||
@@ -125,7 +125,7 @@ extern "C" esp_err_t nvs_flash_init_partition_ptr(const esp_partition_t *partiti
|
||||
return init_res;
|
||||
}
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#ifndef LINUX_TARGET
|
||||
extern "C" esp_err_t nvs_flash_init_partition(const char *part_name)
|
||||
{
|
||||
Lock::init();
|
||||
@@ -204,7 +204,7 @@ extern "C" esp_err_t nvs_flash_erase(void)
|
||||
{
|
||||
return nvs_flash_erase_partition(NVS_DEFAULT_PART_NAME);
|
||||
}
|
||||
#endif // ESP_PLATFORM
|
||||
#endif // ! LINUX_TARGET
|
||||
|
||||
extern "C" esp_err_t nvs_flash_deinit_partition(const char* partition_name)
|
||||
{
|
||||
@@ -528,7 +528,7 @@ extern "C" esp_err_t nvs_get_used_entry_count(nvs_handle_t c_handle, size_t* use
|
||||
return err;
|
||||
}
|
||||
|
||||
#if (defined CONFIG_NVS_ENCRYPTION) && (defined ESP_PLATFORM)
|
||||
#if (defined CONFIG_NVS_ENCRYPTION) && (!defined LINUX_TARGET)
|
||||
|
||||
extern "C" esp_err_t nvs_flash_generate_keys(const esp_partition_t* partition, nvs_sec_cfg_t* cfg)
|
||||
{
|
||||
|
@@ -12,10 +12,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "nvs_page.hpp"
|
||||
#if defined(ESP_PLATFORM)
|
||||
#include <esp32/rom/crc.h>
|
||||
#else
|
||||
#if defined(LINUX_TARGET)
|
||||
#include "crc.h"
|
||||
#else
|
||||
#include <esp_rom_crc.h>
|
||||
#endif
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
@@ -27,7 +27,7 @@ Page::Page() : mPartition(nullptr) { }
|
||||
|
||||
uint32_t Page::Header::calculateCrc32()
|
||||
{
|
||||
return crc32_le(0xffffffff,
|
||||
return esp_rom_crc32_le(0xffffffff,
|
||||
reinterpret_cast<uint8_t*>(this) + offsetof(Header, mSeqNumber),
|
||||
offsetof(Header, mCrc32) - offsetof(Header, mSeqNumber));
|
||||
}
|
||||
@@ -137,7 +137,7 @@ esp_err_t Page::writeEntryData(const uint8_t* data, size_t size)
|
||||
|
||||
const uint8_t* buf = data;
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#if !defined LINUX_TARGET
|
||||
// TODO: check whether still necessary with esp_partition* API
|
||||
/* On the ESP32, data can come from DROM, which is not accessible by spi_flash_write
|
||||
* function. To work around this, we copy the data to heap if it came from DROM.
|
||||
@@ -153,15 +153,15 @@ esp_err_t Page::writeEntryData(const uint8_t* data, size_t size)
|
||||
}
|
||||
memcpy((void*)buf, data, size);
|
||||
}
|
||||
#endif //ESP_PLATFORM
|
||||
#endif // ! LINUX_TARGET
|
||||
|
||||
auto rc = mPartition->write(getEntryAddress(mNextFreeEntry), buf, size);
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#if !defined LINUX_TARGET
|
||||
if (buf != data) {
|
||||
free((void*)buf);
|
||||
}
|
||||
#endif //ESP_PLATFORM
|
||||
#endif // ! LINUX_TARGET
|
||||
if (rc != ESP_OK) {
|
||||
mState = PageState::INVALID;
|
||||
return rc;
|
||||
@@ -968,7 +968,7 @@ size_t Page::getVarDataTailroom() const
|
||||
} else if (mState == PageState::FULL) {
|
||||
return 0;
|
||||
}
|
||||
/* Skip one entry for header*/
|
||||
/* Skip one entry for blob data item precessing the data */
|
||||
return ((mNextFreeEntry < (ENTRY_COUNT-1)) ? ((ENTRY_COUNT - mNextFreeEntry - 1) * ENTRY_SIZE): 0);
|
||||
}
|
||||
|
||||
|
@@ -224,6 +224,9 @@ protected:
|
||||
uint16_t mUsedEntryCount = 0;
|
||||
uint16_t mErasedEntryCount = 0;
|
||||
|
||||
/**
|
||||
* This hash list stores hashes of namespace index, key, and ChunkIndex for quick lookup when searching items.
|
||||
*/
|
||||
HashList mHashList;
|
||||
|
||||
Partition *mPartition;
|
||||
|
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "string.h"
|
||||
#include <cstdlib>
|
||||
#include "nvs_partition.hpp"
|
||||
|
||||
namespace nvs {
|
||||
@@ -22,7 +22,7 @@ NVSPartition::NVSPartition(const esp_partition_t* partition)
|
||||
{
|
||||
// ensure the class is in a valid state
|
||||
if (partition == nullptr) {
|
||||
abort();
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -11,11 +11,23 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef nvs_platform_h
|
||||
#define nvs_platform_h
|
||||
#pragma once
|
||||
|
||||
#ifdef LINUX_TARGET
|
||||
namespace nvs
|
||||
{
|
||||
class Lock
|
||||
{
|
||||
public:
|
||||
Lock() { }
|
||||
~Lock() { }
|
||||
static void init() {}
|
||||
static void uninit() {}
|
||||
};
|
||||
} // namespace nvs
|
||||
|
||||
#else // LINUX_TARGET
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
@@ -63,19 +75,4 @@ public:
|
||||
};
|
||||
} // namespace nvs
|
||||
|
||||
#else // ESP_PLATFORM
|
||||
namespace nvs
|
||||
{
|
||||
class Lock
|
||||
{
|
||||
public:
|
||||
Lock() { }
|
||||
~Lock() { }
|
||||
static void init() {}
|
||||
static void uninit() {}
|
||||
};
|
||||
} // namespace nvs
|
||||
#endif // ESP_PLATFORM
|
||||
|
||||
|
||||
#endif /* nvs_platform_h */
|
||||
#endif // LINUX_TARGET
|
||||
|
@@ -14,9 +14,15 @@
|
||||
#include "nvs_storage.hpp"
|
||||
|
||||
#ifndef ESP_PLATFORM
|
||||
// We need NO_DEBUG_STORAGE here since the integration tests on the host add some debug code.
|
||||
// The unit tests, however, don't want debug code since they check the behavior via data in/output and disturb
|
||||
// the order of calling mocked functions.
|
||||
#ifndef NO_DEBUG_STORAGE
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#define DEBUG_STORAGE
|
||||
#endif
|
||||
#endif // !ESP_PLATFORM
|
||||
|
||||
namespace nvs
|
||||
{
|
||||
@@ -136,7 +142,7 @@ esp_err_t Storage::init(uint32_t baseSector, uint32_t sectorCount)
|
||||
// Purge the blob index list
|
||||
blobIdxList.clearAndFreeNodes();
|
||||
|
||||
#ifndef ESP_PLATFORM
|
||||
#ifdef DEBUG_STORAGE
|
||||
debugCheck();
|
||||
#endif
|
||||
return ESP_OK;
|
||||
@@ -183,7 +189,7 @@ esp_err_t Storage::writeMultiPageBlob(uint8_t nsIndex, const char* key, const vo
|
||||
Page& page = getCurrentPage();
|
||||
size_t tailroom = page.getVarDataTailroom();
|
||||
size_t chunkSize = 0;
|
||||
if (!chunkCount && tailroom < dataSize && tailroom < Page::CHUNK_MAX_SIZE/10) {
|
||||
if (chunkCount == 0U && ((tailroom < dataSize) || (tailroom == 0 && dataSize == 0)) && tailroom < Page::CHUNK_MAX_SIZE/10) {
|
||||
/** This is the first chunk and tailroom is too small ***/
|
||||
if (page.state() != Page::PageState::FULL) {
|
||||
err = page.markFull();
|
||||
@@ -383,7 +389,7 @@ esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#ifndef ESP_PLATFORM
|
||||
#ifdef DEBUG_STORAGE
|
||||
debugCheck();
|
||||
#endif
|
||||
return ESP_OK;
|
||||
@@ -666,7 +672,7 @@ void Storage::debugDump()
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ESP_PLATFORM
|
||||
#ifdef DEBUG_STORAGE
|
||||
void Storage::debugCheck()
|
||||
{
|
||||
std::map<std::string, Page*> keys;
|
||||
@@ -691,7 +697,7 @@ void Storage::debugCheck()
|
||||
assert(usedCount == p->getUsedEntryCount());
|
||||
}
|
||||
}
|
||||
#endif //ESP_PLATFORM
|
||||
#endif //DEBUG_STORAGE
|
||||
|
||||
esp_err_t Storage::fillStats(nvs_stats_t& nvsStats)
|
||||
{
|
||||
|
@@ -13,10 +13,10 @@
|
||||
// limitations under the License.
|
||||
#include "nvs_types.hpp"
|
||||
|
||||
#if defined(ESP_PLATFORM)
|
||||
#include <esp32/rom/crc.h>
|
||||
#else
|
||||
#if defined(LINUX_TARGET)
|
||||
#include "crc.h"
|
||||
#else
|
||||
#include <esp_rom_crc.h>
|
||||
#endif
|
||||
|
||||
namespace nvs
|
||||
@@ -25,10 +25,10 @@ uint32_t Item::calculateCrc32() const
|
||||
{
|
||||
uint32_t result = 0xffffffff;
|
||||
const uint8_t* p = reinterpret_cast<const uint8_t*>(this);
|
||||
result = crc32_le(result, p + offsetof(Item, nsIndex),
|
||||
result = esp_rom_crc32_le(result, p + offsetof(Item, nsIndex),
|
||||
offsetof(Item, crc32) - offsetof(Item, nsIndex));
|
||||
result = crc32_le(result, p + offsetof(Item, key), sizeof(key));
|
||||
result = crc32_le(result, p + offsetof(Item, data), sizeof(data));
|
||||
result = esp_rom_crc32_le(result, p + offsetof(Item, key), sizeof(key));
|
||||
result = esp_rom_crc32_le(result, p + offsetof(Item, data), sizeof(data));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -36,17 +36,17 @@ uint32_t Item::calculateCrc32WithoutValue() const
|
||||
{
|
||||
uint32_t result = 0xffffffff;
|
||||
const uint8_t* p = reinterpret_cast<const uint8_t*>(this);
|
||||
result = crc32_le(result, p + offsetof(Item, nsIndex),
|
||||
result = esp_rom_crc32_le(result, p + offsetof(Item, nsIndex),
|
||||
offsetof(Item, datatype) - offsetof(Item, nsIndex));
|
||||
result = crc32_le(result, p + offsetof(Item, key), sizeof(key));
|
||||
result = crc32_le(result, p + offsetof(Item, chunkIndex), sizeof(chunkIndex));
|
||||
result = esp_rom_crc32_le(result, p + offsetof(Item, key), sizeof(key));
|
||||
result = esp_rom_crc32_le(result, p + offsetof(Item, chunkIndex), sizeof(chunkIndex));
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t Item::calculateCrc32(const uint8_t* data, size_t size)
|
||||
{
|
||||
uint32_t result = 0xffffffff;
|
||||
result = crc32_le(result, data, size);
|
||||
result = esp_rom_crc32_le(result, data, size);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,7 @@ all: $(TEST_PROGRAM)
|
||||
|
||||
SOURCE_FILES = \
|
||||
esp_error_check_stub.cpp \
|
||||
../mock/int/crc.cpp \
|
||||
$(addprefix ../src/, \
|
||||
nvs_types.cpp \
|
||||
nvs_api.cpp \
|
||||
@@ -28,7 +29,6 @@ SOURCE_FILES = \
|
||||
test_nvs_partition.cpp \
|
||||
test_nvs_cxx_api.cpp \
|
||||
test_nvs_initialization.cpp \
|
||||
crc.cpp \
|
||||
main.cpp
|
||||
|
||||
ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang version"), 1)
|
||||
@@ -37,9 +37,9 @@ 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 ../../hal/include -I ../../xtensa/include -I ../../../tools/catch -fprofile-arcs -ftest-coverage -g2 -ggdb
|
||||
CFLAGS += -fprofile-arcs -ftest-coverage
|
||||
CXXFLAGS += -std=c++11 -Wall -Werror
|
||||
CPPFLAGS += -I../include -I../src -I../mock/int -I./ -I../../esp_common/include -I../../esp32/include -I ../../mbedtls/mbedtls/include -I ../../spi_flash/include -I ../../hal/include -I ../../xtensa/include -I ../../../tools/catch -fprofile-arcs -ftest-coverage -g2 -ggdb
|
||||
CFLAGS += -fprofile-arcs -ftest-coverage -DLINUX_TARGET
|
||||
CXXFLAGS += -std=c++11 -Wall -Werror -DLINUX_TARGET
|
||||
LDFLAGS += -lstdc++ -Wall -fprofile-arcs -ftest-coverage
|
||||
|
||||
ifeq ($(COMPILER),clang)
|
||||
|
@@ -1,3 +1,66 @@
|
||||
idf_build_get_property(spi_flash_mock CONFIG_SPI_FLASH_MOCK)
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
if(${spi_flash_mock})
|
||||
message(STATUS "building SPI FLASH MOCKS")
|
||||
|
||||
set(IDF_PATH $ENV{IDF_PATH})
|
||||
set(CMOCK_DIR "${IDF_PATH}/components/cmock/CMock")
|
||||
set(MOCK_GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/mocks")
|
||||
|
||||
file(MAKE_DIRECTORY ${MOCK_GEN_DIR})
|
||||
|
||||
set(MOCK_OUTPUT
|
||||
"${MOCK_GEN_DIR}/Mockesp_partition.c" "${MOCK_GEN_DIR}/Mockesp_partition.h"
|
||||
"${MOCK_GEN_DIR}/Mockesp_flash.c" "${MOCK_GEN_DIR}/Mockesp_flash.h"
|
||||
"${MOCK_GEN_DIR}/Mockesp_spi_flash.c" "${MOCK_GEN_DIR}/Mockesp_spi_flash.h")
|
||||
|
||||
set(MOCK_HEADERS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/esp_partition.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/esp_flash.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/esp_spi_flash.h
|
||||
)
|
||||
|
||||
set(ENV{UNITY_DIR} "$ENV{IDF_PATH}/components/cmock/CMock")
|
||||
|
||||
set(include_dirs
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||
"${MOCK_GEN_DIR}")
|
||||
|
||||
set(srcs "${MOCK_GEN_DIR}/Mockesp_partition.c"
|
||||
"${MOCK_GEN_DIR}/Mockesp_spi_flash.c"
|
||||
"${MOCK_GEN_DIR}/Mockesp_flash.c")
|
||||
|
||||
if(${target} STREQUAL "linux")
|
||||
list(APPEND include_dirs
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../spi_flash/sim/stubs/soc/include"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../spi_flash/sim/stubs/xtensa")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS ${include_dirs}
|
||||
REQUIRES cmock)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ruby_found SYMBOLIC
|
||||
COMMAND "ruby" "-v"
|
||||
COMMENT "Try to find ruby. If this fails, you need to install ruby"
|
||||
)
|
||||
|
||||
# This command builds the mocks.
|
||||
# First, environment variable UNITY_DIR is set. This is necessary to prevent unity from looking in its own submodule
|
||||
# which doesn't work in our CI yet...
|
||||
# The rest is a straight forward call to cmock.rb, consult cmock's documentation for more information.
|
||||
add_custom_command(
|
||||
OUTPUT ${MOCK_OUTPUT}
|
||||
DEPENDS ruby_found
|
||||
COMMAND ${CMAKE_COMMAND} -E env "UNITY_DIR=${IDF_PATH}/components/unity/unity"
|
||||
ruby
|
||||
${CMOCK_DIR}/lib/cmock.rb
|
||||
-o${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_config.yaml
|
||||
${MOCK_HEADERS}
|
||||
)
|
||||
|
||||
else()
|
||||
if(BOOTLOADER_BUILD)
|
||||
if(CONFIG_IDF_TARGET_ESP32)
|
||||
# ESP32 Bootloader needs SPIUnlock from this file, but doesn't
|
||||
@@ -7,6 +70,9 @@ if(BOOTLOADER_BUILD)
|
||||
set(srcs "esp32s2/spi_flash_rom_patch.c")
|
||||
elseif(CONFIG_IDF_TARGET_ESP32S3)
|
||||
set(srcs "esp32s3/spi_flash_rom_patch.c")
|
||||
else()
|
||||
# but on other platforms no source files are needed for bootloader
|
||||
set(srcs)
|
||||
endif()
|
||||
set(cache_srcs "")
|
||||
set(priv_requires bootloader_support soc)
|
||||
@@ -61,3 +127,5 @@ idf_component_register(SRCS "${srcs}"
|
||||
# Avoid cache miss by unexpected inlineing when built by -Os
|
||||
set_source_files_properties(${cache_srcs} PROPERTIES COMPILE_FLAGS
|
||||
"-fno-inline-functions -fno-inline-small-functions -fno-inline-functions-called-once")
|
||||
|
||||
endif()
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include <stddef.h>
|
||||
#include "esp_err.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_spi_flash_counters.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -419,43 +420,6 @@ extern const spi_flash_guard_funcs_t g_flash_guard_default_ops;
|
||||
*/
|
||||
extern const spi_flash_guard_funcs_t g_flash_guard_no_os_ops;
|
||||
|
||||
#if CONFIG_SPI_FLASH_ENABLE_COUNTERS
|
||||
|
||||
/**
|
||||
* Structure holding statistics for one type of operation
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t count; // number of times operation was executed
|
||||
uint32_t time; // total time taken, in microseconds
|
||||
uint32_t bytes; // total number of bytes
|
||||
} spi_flash_counter_t;
|
||||
|
||||
typedef struct {
|
||||
spi_flash_counter_t read;
|
||||
spi_flash_counter_t write;
|
||||
spi_flash_counter_t erase;
|
||||
} spi_flash_counters_t;
|
||||
|
||||
/**
|
||||
* @brief Reset SPI flash operation counters
|
||||
*/
|
||||
void spi_flash_reset_counters(void);
|
||||
|
||||
/**
|
||||
* @brief Print SPI flash operation counters
|
||||
*/
|
||||
void spi_flash_dump_counters(void);
|
||||
|
||||
/**
|
||||
* @brief Return current SPI flash operation counters
|
||||
*
|
||||
* @return pointer to the spi_flash_counters_t structure holding values
|
||||
* of the operation counters
|
||||
*/
|
||||
const spi_flash_counters_t* spi_flash_get_counters(void);
|
||||
|
||||
#endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
65
components/spi_flash/include/esp_spi_flash_counters.h
Normal file
65
components/spi_flash/include/esp_spi_flash_counters.h
Normal file
@@ -0,0 +1,65 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if CONFIG_SPI_FLASH_ENABLE_COUNTERS
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Structure holding statistics for one type of operation
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t count; // number of times operation was executed
|
||||
uint32_t time; // total time taken, in microseconds
|
||||
uint32_t bytes; // total number of bytes
|
||||
} spi_flash_counter_t;
|
||||
|
||||
typedef struct {
|
||||
spi_flash_counter_t read;
|
||||
spi_flash_counter_t write;
|
||||
spi_flash_counter_t erase;
|
||||
} spi_flash_counters_t;
|
||||
|
||||
/**
|
||||
* @brief Reset SPI flash operation counters
|
||||
*/
|
||||
void spi_flash_reset_counters(void);
|
||||
|
||||
/**
|
||||
* @brief Print SPI flash operation counters
|
||||
*/
|
||||
void spi_flash_dump_counters(void);
|
||||
|
||||
/**
|
||||
* @brief Return current SPI flash operation counters
|
||||
*
|
||||
* @return pointer to the spi_flash_counters_t structure holding values
|
||||
* of the operation counters
|
||||
*/
|
||||
const spi_flash_counters_t* spi_flash_get_counters(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS
|
7
components/spi_flash/mock/mock_config.yaml
Normal file
7
components/spi_flash/mock/mock_config.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
:cmock:
|
||||
:plugins:
|
||||
- expect
|
||||
- expect_any_args
|
||||
- return_thru_ptr
|
||||
- array
|
||||
- callback
|
149
components/spi_flash/sim/stubs/esp_common/esp_err.h
Normal file
149
components/spi_flash/sim/stubs/esp_common/esp_err.h
Normal file
@@ -0,0 +1,149 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int32_t esp_err_t;
|
||||
|
||||
/* Definitions for error constants. */
|
||||
#define ESP_OK 0 /*!< esp_err_t value indicating success (no error) */
|
||||
#define ESP_FAIL -1 /*!< Generic esp_err_t code indicating failure */
|
||||
|
||||
#define ESP_ERR_NO_MEM 0x101 /*!< Out of memory */
|
||||
#define ESP_ERR_INVALID_ARG 0x102 /*!< Invalid argument */
|
||||
#define ESP_ERR_INVALID_STATE 0x103 /*!< Invalid state */
|
||||
#define ESP_ERR_INVALID_SIZE 0x104 /*!< Invalid size */
|
||||
#define ESP_ERR_NOT_FOUND 0x105 /*!< Requested resource not found */
|
||||
#define ESP_ERR_NOT_SUPPORTED 0x106 /*!< Operation or feature not supported */
|
||||
#define ESP_ERR_TIMEOUT 0x107 /*!< Operation timed out */
|
||||
#define ESP_ERR_INVALID_RESPONSE 0x108 /*!< Received response was invalid */
|
||||
#define ESP_ERR_INVALID_CRC 0x109 /*!< CRC or checksum was invalid */
|
||||
#define ESP_ERR_INVALID_VERSION 0x10A /*!< Version was invalid */
|
||||
#define ESP_ERR_INVALID_MAC 0x10B /*!< MAC address was invalid */
|
||||
|
||||
#define ESP_ERR_WIFI_BASE 0x3000 /*!< Starting number of WiFi error codes */
|
||||
#define ESP_ERR_MESH_BASE 0x4000 /*!< Starting number of MESH error codes */
|
||||
#define ESP_ERR_FLASH_BASE 0x6000 /*!< Starting number of flash error codes */
|
||||
|
||||
/**
|
||||
* @brief Returns string for esp_err_t error codes
|
||||
*
|
||||
* This function finds the error code in a pre-generated lookup-table and
|
||||
* returns its string representation.
|
||||
*
|
||||
* The function is generated by the Python script
|
||||
* tools/gen_esp_err_to_name.py which should be run each time an esp_err_t
|
||||
* error is modified, created or removed from the IDF project.
|
||||
*
|
||||
* @param code esp_err_t error code
|
||||
* @return string error message
|
||||
*/
|
||||
const char *esp_err_to_name(esp_err_t code);
|
||||
|
||||
/**
|
||||
* @brief Returns string for esp_err_t and system error codes
|
||||
*
|
||||
* This function finds the error code in a pre-generated lookup-table of
|
||||
* esp_err_t errors and returns its string representation. If the error code
|
||||
* is not found then it is attempted to be found among system errors.
|
||||
*
|
||||
* The function is generated by the Python script
|
||||
* tools/gen_esp_err_to_name.py which should be run each time an esp_err_t
|
||||
* error is modified, created or removed from the IDF project.
|
||||
*
|
||||
* @param code esp_err_t error code
|
||||
* @param[out] buf buffer where the error message should be written
|
||||
* @param buflen Size of buffer buf. At most buflen bytes are written into the buf buffer (including the terminating null byte).
|
||||
* @return buf containing the string error message
|
||||
*/
|
||||
const char *esp_err_to_name_r(esp_err_t code, char *buf, size_t buflen);
|
||||
|
||||
/** @cond */
|
||||
void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) __attribute__((noreturn));
|
||||
|
||||
/** @cond */
|
||||
void _esp_error_check_failed_without_abort(esp_err_t rc, const char *file, int line, const char *function, const char *expression);
|
||||
|
||||
#ifndef __ASSERT_FUNC
|
||||
/* This won't happen on IDF, which defines __ASSERT_FUNC in assert.h, but it does happen when building on the host which
|
||||
uses /usr/include/assert.h or equivalent.
|
||||
*/
|
||||
#ifdef __ASSERT_FUNCTION
|
||||
#define __ASSERT_FUNC __ASSERT_FUNCTION /* used in glibc assert.h */
|
||||
#else
|
||||
#define __ASSERT_FUNC "??"
|
||||
#endif
|
||||
#endif
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* Macro which can be used to check the error code,
|
||||
* and terminate the program in case the code is not ESP_OK.
|
||||
* Prints the error code, error location, and the failed statement to serial output.
|
||||
*
|
||||
* Disabled if assertions are disabled.
|
||||
*/
|
||||
#ifdef NDEBUG
|
||||
#define ESP_ERROR_CHECK(x) do { \
|
||||
esp_err_t __err_rc = (x); \
|
||||
(void) sizeof(__err_rc); \
|
||||
} while(0)
|
||||
#elif defined(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT)
|
||||
#define ESP_ERROR_CHECK(x) do { \
|
||||
esp_err_t __err_rc = (x); \
|
||||
if (__err_rc != ESP_OK) { \
|
||||
abort(); \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
#define ESP_ERROR_CHECK(x) do { \
|
||||
esp_err_t __err_rc = (x); \
|
||||
if (__err_rc != ESP_OK) { \
|
||||
_esp_error_check_failed(__err_rc, __FILE__, __LINE__, \
|
||||
__ASSERT_FUNC, #x); \
|
||||
} \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Macro which can be used to check the error code. Prints the error code, error location, and the failed statement to
|
||||
* serial output.
|
||||
* In comparison with ESP_ERROR_CHECK(), this prints the same error message but isn't terminating the program.
|
||||
*/
|
||||
#ifdef NDEBUG
|
||||
#define ESP_ERROR_CHECK_WITHOUT_ABORT(x) ({ \
|
||||
esp_err_t __err_rc = (x); \
|
||||
__err_rc; \
|
||||
})
|
||||
#else
|
||||
#define ESP_ERROR_CHECK_WITHOUT_ABORT(x) ({ \
|
||||
esp_err_t __err_rc = (x); \
|
||||
if (__err_rc != ESP_OK) { \
|
||||
_esp_error_check_failed_without_abort(__err_rc, __FILE__, __LINE__, \
|
||||
__ASSERT_FUNC, #x); \
|
||||
} \
|
||||
__err_rc; \
|
||||
})
|
||||
#endif //NDEBUG
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
148
components/spi_flash/sim/stubs/soc/include/hal/spi_flash_types.h
Normal file
148
components/spi_flash/sim/stubs/soc/include/hal/spi_flash_types.h
Normal file
@@ -0,0 +1,148 @@
|
||||
// Copyright 2010-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Definition of a common transaction. Also holds the return value. */
|
||||
typedef struct {
|
||||
uint8_t command; ///< Command to send, always 8bits
|
||||
uint8_t mosi_len; ///< Output data length, in bytes
|
||||
uint8_t miso_len; ///< Input data length, in bytes
|
||||
uint8_t address_bitlen; ///< Length of address in bits, set to 0 if command does not need an address
|
||||
uint32_t address; ///< Address to perform operation on
|
||||
const uint8_t *mosi_data; ///< Output data to salve
|
||||
uint8_t *miso_data; ///< [out] Input data from slave, little endian
|
||||
} spi_flash_trans_t;
|
||||
|
||||
/** @brief Mode used for reading from SPI flash */
|
||||
typedef enum {
|
||||
SPI_FLASH_SLOWRD = 0, ///< Data read using single I/O, some limits on speed
|
||||
SPI_FLASH_FASTRD, ///< Data read using single I/O, no limit on speed
|
||||
SPI_FLASH_DOUT, ///< Data read using dual I/O
|
||||
SPI_FLASH_DIO, ///< Both address & data transferred using dual I/O
|
||||
SPI_FLASH_QOUT, ///< Data read using quad I/O
|
||||
SPI_FLASH_QIO, ///< Both address & data transferred using quad I/O
|
||||
|
||||
SPI_FLASH_READ_MODE_MAX, ///< The fastest io mode supported by the host is ``ESP_FLASH_READ_MODE_MAX-1``.
|
||||
} esp_flash_io_mode_t;
|
||||
|
||||
struct spi_flash_host_driver_s;
|
||||
typedef struct spi_flash_host_driver_s spi_flash_host_driver_t;
|
||||
|
||||
/** SPI Flash Host driver instance */
|
||||
typedef struct {
|
||||
const struct spi_flash_host_driver_s* driver; ///< Pointer to the implementation function table
|
||||
// Implementations can wrap this structure into their own ones, and append other data here
|
||||
} spi_flash_host_inst_t ;
|
||||
|
||||
/** Host driver configuration and context structure. */
|
||||
struct spi_flash_host_driver_s {
|
||||
/**
|
||||
* Configure the device-related register before transactions. This saves
|
||||
* some time to re-configure those registers when we send continuously
|
||||
*/
|
||||
esp_err_t (*dev_config)(spi_flash_host_inst_t *host);
|
||||
/**
|
||||
* Send an user-defined spi transaction to the device.
|
||||
*/
|
||||
esp_err_t (*common_command)(spi_flash_host_inst_t *host, spi_flash_trans_t *t);
|
||||
/**
|
||||
* Read flash ID.
|
||||
*/
|
||||
esp_err_t (*read_id)(spi_flash_host_inst_t *host, uint32_t *id);
|
||||
/**
|
||||
* Erase whole flash chip.
|
||||
*/
|
||||
void (*erase_chip)(spi_flash_host_inst_t *host);
|
||||
/**
|
||||
* Erase a specific sector by its start address.
|
||||
*/
|
||||
void (*erase_sector)(spi_flash_host_inst_t *host, uint32_t start_address);
|
||||
/**
|
||||
* Erase a specific block by its start address.
|
||||
*/
|
||||
void (*erase_block)(spi_flash_host_inst_t *host, uint32_t start_address);
|
||||
/**
|
||||
* Read the status of the flash chip.
|
||||
*/
|
||||
esp_err_t (*read_status)(spi_flash_host_inst_t *host, uint8_t *out_sr);
|
||||
/**
|
||||
* Disable write protection.
|
||||
*/
|
||||
esp_err_t (*set_write_protect)(spi_flash_host_inst_t *host, bool wp);
|
||||
/**
|
||||
* Program a page of the flash. Check ``max_write_bytes`` for the maximum allowed writing length.
|
||||
*/
|
||||
void (*program_page)(spi_flash_host_inst_t *host, const void *buffer, uint32_t address, uint32_t length);
|
||||
/** Check whether given buffer can be directly used to write */
|
||||
bool (*supports_direct_write)(spi_flash_host_inst_t *host, const void *p);
|
||||
/**
|
||||
* Slicer for write data. The `program_page` should be called iteratively with the return value
|
||||
* of this function.
|
||||
*
|
||||
* @param address Beginning flash address to write
|
||||
* @param len Length request to write
|
||||
* @param align_addr Output of the aligned address to write to
|
||||
* @param page_size Physical page size of the flash chip
|
||||
* @return Length that can be actually written in one `program_page` call
|
||||
*/
|
||||
int (*write_data_slicer)(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_addr,
|
||||
uint32_t page_size);
|
||||
/**
|
||||
* Read data from the flash. Check ``max_read_bytes`` for the maximum allowed reading length.
|
||||
*/
|
||||
esp_err_t (*read)(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len);
|
||||
/** Check whether given buffer can be directly used to read */
|
||||
bool (*supports_direct_read)(spi_flash_host_inst_t *host, const void *p);
|
||||
/**
|
||||
* Slicer for read data. The `read` should be called iteratively with the return value
|
||||
* of this function.
|
||||
*
|
||||
* @param address Beginning flash address to read
|
||||
* @param len Length request to read
|
||||
* @param align_addr Output of the aligned address to read
|
||||
* @param page_size Physical page size of the flash chip
|
||||
* @return Length that can be actually read in one `read` call
|
||||
*/
|
||||
int (*read_data_slicer)(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_addr, uint32_t page_size);
|
||||
/**
|
||||
* Check whether the host is idle to perform new operations.
|
||||
*/
|
||||
bool (*host_idle)(spi_flash_host_inst_t *host);
|
||||
/**
|
||||
* Configure the host to work at different read mode. Responsible to compensate the timing and set IO mode.
|
||||
*/
|
||||
esp_err_t (*configure_host_io_mode)(spi_flash_host_inst_t *host, uint32_t command,
|
||||
uint32_t addr_bitlen, int dummy_bitlen_base,
|
||||
esp_flash_io_mode_t io_mode);
|
||||
/**
|
||||
* Internal use, poll the HW until the last operation is done.
|
||||
*/
|
||||
void (*poll_cmd_done)(spi_flash_host_inst_t *host);
|
||||
/**
|
||||
* For some host (SPI1), they are shared with a cache. When the data is
|
||||
* modified, the cache needs to be flushed. Left NULL if not supported.
|
||||
*/
|
||||
esp_err_t (*flush_cache)(spi_flash_host_inst_t* host, uint32_t addr, uint32_t size);
|
||||
};
|
||||
///Slowest io mode supported by ESP32, currently SlowRd
|
||||
#define SPI_FLASH_READ_MODE_MIN SPI_FLASH_SLOWRD
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
95
components/spi_flash/sim/stubs/spi_flash/esp_partition.h
Normal file
95
components/spi_flash/sim/stubs/spi_flash/esp_partition.h
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef __ESP_PARTITION_H__
|
||||
#define __ESP_PARTITION_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
ESP_PARTITION_TYPE_APP = 0x00, //!< Application partition type
|
||||
ESP_PARTITION_TYPE_DATA = 0x01, //!< Data partition type
|
||||
} esp_partition_type_t;
|
||||
|
||||
typedef enum {
|
||||
ESP_PARTITION_SUBTYPE_APP_FACTORY = 0x00, //!< Factory application partition
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_MIN = 0x10, //!< Base for OTA partition subtypes
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_0 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 0, //!< OTA partition 0
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_1 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 1, //!< OTA partition 1
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_2 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 2, //!< OTA partition 2
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_3 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 3, //!< OTA partition 3
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_4 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 4, //!< OTA partition 4
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_5 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 5, //!< OTA partition 5
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_6 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 6, //!< OTA partition 6
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_7 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 7, //!< OTA partition 7
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_8 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 8, //!< OTA partition 8
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_9 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 9, //!< OTA partition 9
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_10 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 10,//!< OTA partition 10
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_11 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 11,//!< OTA partition 11
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_12 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 12,//!< OTA partition 12
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_13 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 13,//!< OTA partition 13
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_14 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 14,//!< OTA partition 14
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_15 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 15,//!< OTA partition 15
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_MAX = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 16,//!< Max subtype of OTA partition
|
||||
ESP_PARTITION_SUBTYPE_APP_TEST = 0x20, //!< Test application partition
|
||||
|
||||
ESP_PARTITION_SUBTYPE_DATA_OTA = 0x00, //!< OTA selection partition
|
||||
ESP_PARTITION_SUBTYPE_DATA_PHY = 0x01, //!< PHY init data partition
|
||||
ESP_PARTITION_SUBTYPE_DATA_NVS = 0x02, //!< NVS partition
|
||||
ESP_PARTITION_SUBTYPE_DATA_COREDUMP = 0x03, //!< COREDUMP partition
|
||||
ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS = 0x04, //!< Partition for NVS keys
|
||||
ESP_PARTITION_SUBTYPE_DATA_EFUSE_EM = 0x05, //!< Partition for emulate eFuse bits
|
||||
|
||||
ESP_PARTITION_SUBTYPE_DATA_ESPHTTPD = 0x80, //!< ESPHTTPD partition
|
||||
ESP_PARTITION_SUBTYPE_DATA_FAT = 0x81, //!< FAT partition
|
||||
ESP_PARTITION_SUBTYPE_DATA_SPIFFS = 0x82, //!< SPIFFS partition
|
||||
|
||||
ESP_PARTITION_SUBTYPE_ANY = 0xff, //!< Used to search for partitions with any subtype
|
||||
} esp_partition_subtype_t;
|
||||
|
||||
/**
|
||||
* @brief Opaque partition iterator type
|
||||
*/
|
||||
typedef struct esp_partition_iterator_opaque_* esp_partition_iterator_t;
|
||||
|
||||
/**
|
||||
* @brief partition information structure
|
||||
*
|
||||
* This is not the format in flash, that format is esp_partition_info_t.
|
||||
*
|
||||
* However, this is the format used by this API.
|
||||
*/
|
||||
typedef struct {
|
||||
void* flash_chip; /*!< SPI flash chip on which the partition resides */
|
||||
esp_partition_type_t type; /*!< partition type (app/data) */
|
||||
esp_partition_subtype_t subtype; /*!< partition subtype */
|
||||
uint32_t address; /*!< starting address of the partition in flash */
|
||||
uint32_t size; /*!< size of the partition, in bytes */
|
||||
char label[17]; /*!< partition label, zero-terminated ASCII string */
|
||||
bool encrypted; /*!< flag is set to true if partition is encrypted */
|
||||
} esp_partition_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __ESP_PARTITION_H__ */
|
149
components/spi_flash/sim/stubs/xtensa/esp_attr.h
Normal file
149
components/spi_flash/sim/stubs/xtensa/esp_attr.h
Normal file
@@ -0,0 +1,149 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef __ESP_ATTR_H__
|
||||
#define __ESP_ATTR_H__
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#define ROMFN_ATTR
|
||||
|
||||
//Normally, the linker script will put all code and rodata in flash,
|
||||
//and all variables in shared RAM. These macros can be used to redirect
|
||||
//particular functions/variables to other memory regions.
|
||||
|
||||
// Forces code into IRAM instead of flash
|
||||
#define IRAM_ATTR _SECTION_ATTR_IMPL(".iram1", __COUNTER__)
|
||||
|
||||
// Forces data into DRAM instead of flash
|
||||
#define DRAM_ATTR _SECTION_ATTR_IMPL(".dram1", __COUNTER__)
|
||||
|
||||
#ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY
|
||||
// Forces data into IRAM instead of DRAM
|
||||
#define IRAM_DATA_ATTR __attribute__((section(".iram.data")))
|
||||
|
||||
// Forces data into IRAM instead of DRAM and map it to coredump
|
||||
#define COREDUMP_IRAM_DATA_ATTR _SECTION_ATTR_IMPL(".iram.data.coredump", __COUNTER__)
|
||||
|
||||
// Forces bss into IRAM instead of DRAM
|
||||
#define IRAM_BSS_ATTR __attribute__((section(".iram.bss")))
|
||||
#else
|
||||
#define COREDUMP_IRAM_DATA_ATTR
|
||||
#define IRAM_DATA_ATTR
|
||||
|
||||
#define IRAM_BSS_ATTR
|
||||
#endif
|
||||
|
||||
// Forces data to be 4 bytes aligned
|
||||
#define WORD_ALIGNED_ATTR __attribute__((aligned(4)))
|
||||
|
||||
// Forces data to be placed to DMA-capable places
|
||||
#define DMA_ATTR WORD_ALIGNED_ATTR DRAM_ATTR
|
||||
|
||||
// Forces a function to be inlined
|
||||
#define FORCE_INLINE_ATTR static inline __attribute__((always_inline))
|
||||
|
||||
// Forces a string into DRAM instead of flash
|
||||
// Use as esp_rom_printf(DRAM_STR("Hello world!\n"));
|
||||
#define DRAM_STR(str) (__extension__({static const DRAM_ATTR char __c[] = (str); (const char *)&__c;}))
|
||||
|
||||
// Forces code into RTC fast memory. See "docs/deep-sleep-stub.rst"
|
||||
#define RTC_IRAM_ATTR _SECTION_ATTR_IMPL(".rtc.text", __COUNTER__)
|
||||
|
||||
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||
// Forces bss variable into external memory. "
|
||||
#define EXT_RAM_ATTR _SECTION_ATTR_IMPL(".ext_ram.bss", __COUNTER__)
|
||||
#else
|
||||
#define EXT_RAM_ATTR
|
||||
#endif
|
||||
|
||||
// Forces data into RTC slow memory. See "docs/deep-sleep-stub.rst"
|
||||
// Any variable marked with this attribute will keep its value
|
||||
// during a deep sleep / wake cycle.
|
||||
#define RTC_DATA_ATTR _SECTION_ATTR_IMPL(".rtc.data", __COUNTER__)
|
||||
|
||||
// Forces read-only data into RTC memory. See "docs/deep-sleep-stub.rst"
|
||||
#define RTC_RODATA_ATTR _SECTION_ATTR_IMPL(".rtc.rodata", __COUNTER__)
|
||||
|
||||
// Allows to place data into RTC_SLOW memory.
|
||||
#define RTC_SLOW_ATTR _SECTION_ATTR_IMPL(".rtc.force_slow", __COUNTER__)
|
||||
|
||||
// Allows to place data into RTC_FAST memory.
|
||||
#define RTC_FAST_ATTR _SECTION_ATTR_IMPL(".rtc.force_fast", __COUNTER__)
|
||||
|
||||
// Forces data into noinit section to avoid initialization after restart.
|
||||
#define __NOINIT_ATTR _SECTION_ATTR_IMPL(".noinit", __COUNTER__)
|
||||
|
||||
// Forces data into RTC slow memory of .noinit section.
|
||||
// Any variable marked with this attribute will keep its value
|
||||
// after restart or during a deep sleep / wake cycle.
|
||||
#define RTC_NOINIT_ATTR _SECTION_ATTR_IMPL(".rtc_noinit", __COUNTER__)
|
||||
|
||||
// Forces code into DRAM instead of flash and map it to coredump
|
||||
#define COREDUMP_DRAM_ATTR _SECTION_ATTR_IMPL(".dram1.coredump", __COUNTER__)
|
||||
|
||||
// Forces data into RTC memory and map it to coredump
|
||||
#define COREDUMP_RTC_DATA_ATTR _SECTION_ATTR_IMPL(".rtc.coredump", __COUNTER__)
|
||||
|
||||
// Allows to place data into RTC_FAST memory and map it to coredump
|
||||
#define COREDUMP_RTC_FAST_ATTR _SECTION_ATTR_IMPL(".rtc.fast.coredump", __COUNTER__)
|
||||
|
||||
// Forces to not inline function
|
||||
#define NOINLINE_ATTR __attribute__((noinline))
|
||||
|
||||
// This allows using enum as flags in C++
|
||||
// Format: FLAG_ATTR(flag_enum_t)
|
||||
#ifdef __cplusplus
|
||||
|
||||
// Inline is required here to avoid multiple definition error in linker
|
||||
#define FLAG_ATTR_IMPL(TYPE, INT_TYPE) \
|
||||
FORCE_INLINE_ATTR constexpr TYPE operator~ (TYPE a) { return (TYPE)~(INT_TYPE)a; } \
|
||||
FORCE_INLINE_ATTR constexpr TYPE operator| (TYPE a, TYPE b) { return (TYPE)((INT_TYPE)a | (INT_TYPE)b); } \
|
||||
FORCE_INLINE_ATTR constexpr TYPE operator& (TYPE a, TYPE b) { return (TYPE)((INT_TYPE)a & (INT_TYPE)b); } \
|
||||
FORCE_INLINE_ATTR constexpr TYPE operator^ (TYPE a, TYPE b) { return (TYPE)((INT_TYPE)a ^ (INT_TYPE)b); } \
|
||||
FORCE_INLINE_ATTR constexpr TYPE operator>> (TYPE a, int b) { return (TYPE)((INT_TYPE)a >> b); } \
|
||||
FORCE_INLINE_ATTR constexpr TYPE operator<< (TYPE a, int b) { return (TYPE)((INT_TYPE)a << b); } \
|
||||
FORCE_INLINE_ATTR TYPE& operator|=(TYPE& a, TYPE b) { a = a | b; return a; } \
|
||||
FORCE_INLINE_ATTR TYPE& operator&=(TYPE& a, TYPE b) { a = a & b; return a; } \
|
||||
FORCE_INLINE_ATTR TYPE& operator^=(TYPE& a, TYPE b) { a = a ^ b; return a; } \
|
||||
FORCE_INLINE_ATTR TYPE& operator>>=(TYPE& a, int b) { a >>= b; return a; } \
|
||||
FORCE_INLINE_ATTR TYPE& operator<<=(TYPE& a, int b) { a <<= b; return a; }
|
||||
|
||||
#define FLAG_ATTR_U32(TYPE) FLAG_ATTR_IMPL(TYPE, uint32_t)
|
||||
#define FLAG_ATTR FLAG_ATTR_U32
|
||||
|
||||
#else
|
||||
#define FLAG_ATTR(TYPE)
|
||||
#endif
|
||||
|
||||
// Implementation for a unique custom section
|
||||
//
|
||||
// This prevents gcc producing "x causes a section type conflict with y"
|
||||
// errors if two variables in the same source file have different linkage (maybe const & non-const) but are placed in the same custom section
|
||||
//
|
||||
// Using unique sections also means --gc-sections can remove unused
|
||||
// data with a custom section type set
|
||||
#define _SECTION_ATTR_IMPL(SECTION, COUNTER) __attribute__((section(SECTION "." _COUNTER_STRINGIFY(COUNTER))))
|
||||
|
||||
#define _COUNTER_STRINGIFY(COUNTER) #COUNTER
|
||||
|
||||
/* Use IDF_DEPRECATED attribute to mark anything deprecated from use in
|
||||
ESP-IDF's own source code, but not deprecated for external users.
|
||||
*/
|
||||
#ifdef IDF_CI_BUILD
|
||||
#define IDF_DEPRECATED(REASON) __attribute__((deprecated(REASON)))
|
||||
#else
|
||||
#define IDF_DEPRECATED(REASON)
|
||||
#endif
|
||||
|
||||
#endif /* __ESP_ATTR_H__ */
|
@@ -1,6 +1,9 @@
|
||||
set(srcs
|
||||
"unity/src/unity.c"
|
||||
"unity_port_esp32.c")
|
||||
"unity/src/unity.c")
|
||||
|
||||
set(includes
|
||||
"include"
|
||||
"unity/src")
|
||||
|
||||
if(CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL)
|
||||
list(APPEND COMPONENT_PRIV_INCLUDEDIRS "include/priv")
|
||||
@@ -12,13 +15,24 @@ endif()
|
||||
|
||||
if(CONFIG_UNITY_ENABLE_FIXTURE)
|
||||
list(APPEND srcs "unity/extras/fixture/src/unity_fixture.c")
|
||||
list(APPEND includes "unity/extras/fixture/src")
|
||||
endif()
|
||||
|
||||
if(${IDF_TARGET} STREQUAL "linux")
|
||||
message(STATUS "adding linux stuff...")
|
||||
idf_component_get_property(spi_flash_dir spi_flash COMPONENT_DIR)
|
||||
list(APPEND includes "${spi_flash_dir}/sim/stubs/esp_common")
|
||||
else()
|
||||
list(APPEND srcs "unity_port_esp32.c")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "include" "unity/src" "unity/extras/fixture/src")
|
||||
INCLUDE_DIRS ${includes})
|
||||
|
||||
if(NOT ${IDF_TARGET} STREQUAL "linux")
|
||||
target_compile_definitions(${COMPONENT_LIB} PUBLIC
|
||||
-DUNITY_INCLUDE_CONFIG_H
|
||||
)
|
||||
endif()
|
||||
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-unused-const-variable)
|
||||
|
@@ -0,0 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
set(COMPONENTS main)
|
||||
project(linux_host_app)
|
8
examples/build_system/cmake/linux_host_app/README.md
Normal file
8
examples/build_system/cmake/linux_host_app/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
| Supported Targets | Linux |
|
||||
| ----------------- | ----- |
|
||||
|
||||
# Build
|
||||
`idf.py build` (sdkconfig.defaults sets the linux target by default)
|
||||
|
||||
# Run
|
||||
`build/linux_host_app.elf`
|
@@ -0,0 +1 @@
|
||||
idf_component_register(SRCS "linux_host_app.cpp")
|
@@ -0,0 +1,20 @@
|
||||
/* Hello World Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include "stdio.h"
|
||||
|
||||
void app_main() {
|
||||
printf("Hello, Host!\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
app_main();
|
||||
return 0;
|
||||
}
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_IDF_TARGET="linux"
|
||||
CONFIG_CXX_EXCEPTIONS=y
|
@@ -151,12 +151,16 @@ function(__build_init idf_path)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
if(NOT target STREQUAL "linux")
|
||||
# Set components required by all other components in the build
|
||||
#
|
||||
# - lwip is here so that #include <sys/socket.h> works without any special provisions
|
||||
# - esp_hw_support is here for backward compatibility
|
||||
set(requires_common cxx newlib freertos esp_hw_support heap log lwip soc hal esp_rom esp_common esp_system)
|
||||
idf_build_set_property(__COMPONENT_REQUIRES_COMMON "${requires_common}")
|
||||
endif()
|
||||
|
||||
__build_get_idf_git_revision()
|
||||
__kconfig_init()
|
||||
@@ -397,7 +401,13 @@ macro(idf_build_process target)
|
||||
# Check for required Python modules
|
||||
__build_check_python()
|
||||
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
|
||||
if(NOT target STREQUAL "linux")
|
||||
idf_build_set_property(__COMPONENT_REQUIRES_COMMON ${target} APPEND)
|
||||
else()
|
||||
idf_build_set_property(__COMPONENT_REQUIRES_COMMON "")
|
||||
endif()
|
||||
|
||||
# Perform early expansion of component CMakeLists.txt in CMake scripting mode.
|
||||
# It is here we retrieve the public and private requirements of each component.
|
||||
|
@@ -463,7 +463,9 @@ function(idf_component_register)
|
||||
idf_build_get_property(compile_definitions COMPILE_DEFINITIONS GENERATOR_EXPRESSION)
|
||||
add_compile_options("${compile_definitions}")
|
||||
|
||||
if(common_reqs) # check whether common_reqs exists, this may be the case in minimalistic host unit test builds
|
||||
list(REMOVE_ITEM common_reqs ${component_lib})
|
||||
endif()
|
||||
link_libraries(${common_reqs})
|
||||
|
||||
idf_build_get_property(config_dir CONFIG_DIR)
|
||||
@@ -475,7 +477,7 @@ function(idf_component_register)
|
||||
__component_add_include_dirs(${component_lib} "${__INCLUDE_DIRS}" PUBLIC)
|
||||
__component_add_include_dirs(${component_lib} "${__PRIV_INCLUDE_DIRS}" PRIVATE)
|
||||
__component_add_include_dirs(${component_lib} "${config_dir}" PUBLIC)
|
||||
set_target_properties(${component_lib} PROPERTIES OUTPUT_NAME ${COMPONENT_NAME})
|
||||
set_target_properties(${component_lib} PROPERTIES OUTPUT_NAME ${COMPONENT_NAME} LINKER_LANGUAGE C)
|
||||
__ldgen_add_component(${component_lib})
|
||||
else()
|
||||
add_library(${component_lib} INTERFACE)
|
||||
|
@@ -9,6 +9,8 @@ function(__add_dfu_targets)
|
||||
set(dfu_pid "2")
|
||||
elseif("${target}" STREQUAL "esp32s3")
|
||||
set(dfu_pid "4")
|
||||
elseif("${target}" STREQUAL "linux")
|
||||
return()
|
||||
else()
|
||||
message(FATAL_ERROR "DFU PID unknown for ${target}")
|
||||
endif()
|
||||
|
8
tools/cmake/toolchain-linux.cmake
Normal file
8
tools/cmake/toolchain-linux.cmake
Normal file
@@ -0,0 +1,8 @@
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
|
||||
set(CMAKE_C_COMPILER gcc)
|
||||
set(CMAKE_CXX_COMPILER g++)
|
||||
set(CMAKE_ASM_COMPILER gcc)
|
||||
|
||||
set(CMAKE_C_FLAGS "-Wno-frame-address" CACHE STRING "C Compiler Base Flags")
|
||||
set(CMAKE_CXX_FLAGS "-Wno-frame-address" CACHE STRING "C++ Compiler Base Flags")
|
@@ -289,12 +289,13 @@ class BuildSystem:
|
||||
Objects of these classes aren't instantiated, instead the class (type object) is used.
|
||||
"""
|
||||
NAME = "undefined"
|
||||
SUPPORTED_TARGETS_REGEX = re.compile(r'Supported [Tt]argets((?:[\s|]+(?:ESP[0-9A-Z\-]+))+)')
|
||||
SUPPORTED_TARGETS_REGEX = re.compile(r'Supported [Tt]argets((?:[ |]+(?:[0-9a-zA-Z\-]+))+)')
|
||||
|
||||
FORMAL_TO_USUAL = {
|
||||
'ESP32': 'esp32',
|
||||
'ESP32-S2': 'esp32s2',
|
||||
'ESP32-S3': 'esp32s3',
|
||||
'Linux': 'linux',
|
||||
}
|
||||
|
||||
@classmethod
|
||||
|
@@ -46,7 +46,9 @@ ignore_files = [os.path.join('components', 'mdns', 'test_afl_fuzz_host', 'esp32_
|
||||
]
|
||||
|
||||
# add directories here which should not be parsed, this is a tuple since it will be used with *.startswith()
|
||||
ignore_dirs = (os.path.join('examples'), os.path.join('components', 'cmock', 'CMock', 'test'))
|
||||
ignore_dirs = (os.path.join('examples'),
|
||||
os.path.join('components', 'cmock', 'CMock', 'test'),
|
||||
os.path.join('components', 'spi_flash', 'sim'))
|
||||
|
||||
# macros from here have higher priorities in case of collisions
|
||||
priority_headers = [os.path.join('components', 'esp_common', 'include', 'esp_err.h')]
|
||||
|
@@ -38,4 +38,4 @@ GENERATORS = collections.OrderedDict([
|
||||
|
||||
SUPPORTED_TARGETS = ["esp32", "esp32s2"]
|
||||
|
||||
PREVIEW_TARGETS = ["esp32s3"]
|
||||
PREVIEW_TARGETS = ["esp32s3", "linux"]
|
||||
|
Reference in New Issue
Block a user