mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/host_side_storage_components' into 'master'
Runnable FS components on host See merge request idf/esp-idf!2431
This commit is contained in:
commit
40596fa55a
@ -285,6 +285,26 @@ test_wl_on_host:
|
||||
- cd components/wear_levelling/test_wl_host
|
||||
- make test
|
||||
|
||||
test_fatfs_on_host:
|
||||
stage: test
|
||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
|
||||
tags:
|
||||
- wl_host_test
|
||||
dependencies: []
|
||||
script:
|
||||
- cd components/fatfs/test_fatfs_host/
|
||||
- make test
|
||||
|
||||
test_spiffs_on_host:
|
||||
stage: test
|
||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
|
||||
tags:
|
||||
- wl_host_test
|
||||
dependencies: []
|
||||
script:
|
||||
- cd components/spiffs/test_spiffs_host/
|
||||
- make test
|
||||
|
||||
test_multi_heap_on_host:
|
||||
stage: test
|
||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
|
||||
|
103
components/fatfs/test_fatfs_host/Makefile
Normal file
103
components/fatfs/test_fatfs_host/Makefile
Normal file
@ -0,0 +1,103 @@
|
||||
COMPONENT=fatfs
|
||||
|
||||
TEST_PROGRAM=test_$(COMPONENT)
|
||||
|
||||
#Expose as a library
|
||||
COMPONENT_LIB=lib$(COMPONENT).a
|
||||
|
||||
#Use wear levelling and flash simulation
|
||||
WEAR_LEVELLING=wear_levelling
|
||||
WEAR_LEVELLING_DIR=../../$(WEAR_LEVELLING)
|
||||
WEAR_LEVELLING_HOST_DIR=$(WEAR_LEVELLING_DIR)/test_wl_host
|
||||
WEAR_LEVELLING_LIB=lib$(WEAR_LEVELLING).a
|
||||
|
||||
SPI_FLASH=spi_flash
|
||||
SPI_FLASH_DIR=../../$(SPI_FLASH)
|
||||
SPI_FLASH_SIM_DIR=$(SPI_FLASH_DIR)/sim
|
||||
SPI_FLASH_LIB=lib$(SPI_FLASH).a
|
||||
|
||||
all: $(TEST_PROGRAM)
|
||||
|
||||
SOURCE_FILES = \
|
||||
$(addprefix ../src/, \
|
||||
diskio.c \
|
||||
ff.c \
|
||||
ffsystem.c \
|
||||
ffunicode.c \
|
||||
diskio_spiflash.c \
|
||||
) \
|
||||
$(addprefix ./stubs/, log/log.c)
|
||||
|
||||
TEST_SOURCE_FILES = \
|
||||
test_fatfs.cpp \
|
||||
main.cpp \
|
||||
test_utils.c
|
||||
|
||||
INCLUDE_FLAGS = $(addprefix -I,\
|
||||
../src \
|
||||
. \
|
||||
$(addprefix ./stubs/, \
|
||||
driver/include \
|
||||
freertos/include \
|
||||
sdmmc/include \
|
||||
log/include \
|
||||
) \
|
||||
$(SPI_FLASH_DIR)/include \
|
||||
$(WEAR_LEVELLING_DIR)/include \
|
||||
../../esp32/include \
|
||||
../../../tools/catch \
|
||||
)
|
||||
|
||||
GCOV ?= gcov
|
||||
|
||||
CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL -g -m32
|
||||
CFLAGS += -fprofile-arcs -ftest-coverage
|
||||
CXXFLAGS += -std=c++11 -Wall -Werror -fprofile-arcs -ftest-coverage
|
||||
LDFLAGS += -lstdc++ -fprofile-arcs -ftest-coverage
|
||||
|
||||
OBJ_FILES = $(filter %.o, $(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o))
|
||||
TEST_OBJ_FILES = $(filter %.o, $(TEST_SOURCE_FILES:.cpp=.o) $(TEST_SOURCE_FILES:.c=.o))
|
||||
|
||||
$(WEAR_LEVELLING_HOST_DIR)/$(WEAR_LEVELLING_LIB): force
|
||||
$(MAKE) -C $(WEAR_LEVELLING_HOST_DIR) lib
|
||||
|
||||
$(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB): force
|
||||
$(MAKE) -C $(SPI_FLASH_SIM_DIR) lib
|
||||
|
||||
force:
|
||||
|
||||
$(COMPONENT_LIB): $(OBJ_FILES)
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
lib: $(COMPONENT_LIB)
|
||||
|
||||
partition_table.bin: partition_table.csv
|
||||
python ../../partition_table/gen_esp32part.py --verify $< $@
|
||||
|
||||
$(TEST_PROGRAM): lib $(TEST_OBJ_FILES) $(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB) $(WEAR_LEVELLING_HOST_DIR)/$(WEAR_LEVELLING_LIB) partition_table.bin
|
||||
g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(TEST_OBJ_FILES) -L$(abspath .) -l:$(COMPONENT_LIB) -L$(SPI_FLASH_SIM_DIR) -l:$(SPI_FLASH_LIB) -L$(WEAR_LEVELLING_HOST_DIR) -l:$(WEAR_LEVELLING_LIB) -g -m32
|
||||
|
||||
test: $(TEST_PROGRAM)
|
||||
./$(TEST_PROGRAM)
|
||||
|
||||
COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(TEST_OBJ_FILES:.o=.gc*)
|
||||
|
||||
$(COVERAGE_FILES): test
|
||||
|
||||
coverage.info: $(COVERAGE_FILES)
|
||||
find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} +
|
||||
lcov --capture --directory ../ --no-external --output-file coverage.info --gcov-tool $(GCOV)
|
||||
|
||||
coverage_report: coverage.info
|
||||
genhtml coverage.info --output-directory coverage_report
|
||||
@echo "Coverage report is in coverage_report/index.html"
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ_FILES) $(TEST_OBJ_FILES) $(TEST_PROGRAM) $(COMPONENT_LIB) partition_table.bin
|
||||
$(MAKE) -C $(WEAR_LEVELLING_HOST_DIR) clean
|
||||
$(MAKE) -C $(SPI_FLASH_SIM_DIR) clean
|
||||
rm -f $(COVERAGE_FILES) *.gcov
|
||||
rm -rf coverage_report/
|
||||
rm -f coverage.info
|
||||
|
||||
.PHONY: clean all test lib
|
2
components/fatfs/test_fatfs_host/main.cpp
Normal file
2
components/fatfs/test_fatfs_host/main.cpp
Normal file
@ -0,0 +1,2 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
6
components/fatfs/test_fatfs_host/partition_table.csv
Normal file
6
components/fatfs/test_fatfs_host/partition_table.csv
Normal file
@ -0,0 +1,6 @@
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
|
||||
nvs, data, nvs, 0x9000, 0x6000,
|
||||
phy_init, data, phy, 0xf000, 0x1000,
|
||||
factory, app, factory, 0x10000, 1M,
|
||||
storage, data, fat, , 1M,
|
|
3
components/fatfs/test_fatfs_host/sdkconfig.h
Normal file
3
components/fatfs/test_fatfs_host/sdkconfig.h
Normal file
@ -0,0 +1,3 @@
|
||||
# pragma once
|
||||
|
||||
#define CONFIG_WL_SECTOR_SIZE 4096
|
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "sdmmc_types.h"
|
||||
|
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int sdmmc_card_t;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "projdefs.h"
|
||||
#include "semphr.h"
|
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define pdTRUE 1
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define vSemaphoreDelete( xSemaphore )
|
||||
#define xSemaphoreCreateMutex() ((void*)(1))
|
||||
#define xSemaphoreGive( xSemaphore )
|
||||
#define xSemaphoreTake( xSemaphore, xBlockTime ) pdTRUE
|
||||
|
||||
typedef void* SemaphoreHandle_t;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
45
components/fatfs/test_fatfs_host/stubs/log/include/esp_log.h
Normal file
45
components/fatfs/test_fatfs_host/stubs/log/include/esp_log.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" { // Make sure we have C-declarations in C++ programs
|
||||
#endif
|
||||
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
|
||||
typedef enum {
|
||||
ESP_LOG_NONE, /*!< No log output */
|
||||
ESP_LOG_ERROR, /*!< Critical errors, software module can not recover on its own */
|
||||
ESP_LOG_WARN, /*!< Error conditions from which recovery measures have been taken */
|
||||
ESP_LOG_INFO, /*!< Information messages which describe normal flow of events */
|
||||
ESP_LOG_DEBUG, /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */
|
||||
ESP_LOG_VERBOSE /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */
|
||||
} esp_log_level_t;
|
||||
|
||||
#define LOG_COLOR_E
|
||||
#define LOG_COLOR_W
|
||||
#define LOG_COLOR_I
|
||||
#define LOG_COLOR_D
|
||||
#define LOG_COLOR_V
|
||||
#define LOG_RESET_COLOR
|
||||
|
||||
uint32_t esp_log_timestamp(void);
|
||||
void esp_log_write(esp_log_level_t level, const char* tag, const char* format, ...) __attribute__ ((format (printf, 3, 4)));
|
||||
|
||||
#define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%d) %s: " format LOG_RESET_COLOR "\n"
|
||||
|
||||
#define ESP_LOGE( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_ERROR) { esp_log_write(ESP_LOG_ERROR, tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
|
||||
|
||||
#define ESP_LOGV( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_VERBOSE) { esp_log_write(ESP_LOG_VERBOSE, tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
|
||||
|
||||
#define ESP_LOGD( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { esp_log_write(ESP_LOG_DEBUG, tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
|
||||
|
||||
#define ESP_LOGW( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_WARN) { esp_log_write(ESP_LOG_WARN, tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
@ -1,4 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
void esp_log_write(esp_log_level_t level,
|
||||
@ -14,4 +17,4 @@ void esp_log_write(esp_log_level_t level,
|
||||
uint32_t esp_log_timestamp()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "esp_err.h"
|
93
components/fatfs/test_fatfs_host/test_fatfs.cpp
Normal file
93
components/fatfs/test_fatfs_host/test_fatfs.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ff.h"
|
||||
#include "esp_partition.h"
|
||||
#include "wear_levelling.h"
|
||||
#include "diskio.h"
|
||||
#include "diskio_spiflash.h"
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
extern "C" void init_spi_flash(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin);
|
||||
|
||||
TEST_CASE("create volume, open file, write and read back data", "[fatfs]")
|
||||
{
|
||||
init_spi_flash(0x00400000, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partition_table.bin");
|
||||
|
||||
FRESULT fr_result;
|
||||
BYTE pdrv;
|
||||
FATFS fs;
|
||||
FIL file;
|
||||
UINT bw;
|
||||
|
||||
esp_err_t esp_result;
|
||||
|
||||
const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, "storage");
|
||||
|
||||
// Mount wear-levelled partition
|
||||
wl_handle_t wl_handle;
|
||||
esp_result = wl_mount(partition, &wl_handle);
|
||||
REQUIRE(esp_result == ESP_OK);
|
||||
|
||||
// Get a physical drive
|
||||
esp_result = ff_diskio_get_drive(&pdrv);
|
||||
REQUIRE(esp_result == ESP_OK);
|
||||
|
||||
// Register physical drive as wear-levelled partition
|
||||
esp_result = ff_diskio_register_wl_partition(pdrv, wl_handle);
|
||||
|
||||
// Create FAT volume on the entire disk
|
||||
DWORD part_list[] = {100, 0, 0, 0};
|
||||
BYTE work_area[FF_MAX_SS];
|
||||
|
||||
fr_result = f_fdisk(pdrv, part_list, work_area);
|
||||
REQUIRE(fr_result == FR_OK);
|
||||
fr_result = f_mkfs("", FM_ANY, 0, work_area, sizeof(work_area)); // Use default volume
|
||||
|
||||
// Mount the volume
|
||||
fr_result = f_mount(&fs, "", 0);
|
||||
REQUIRE(fr_result == FR_OK);
|
||||
|
||||
// Open, write and read data
|
||||
fr_result = f_open(&file, "test.txt", FA_OPEN_ALWAYS | FA_READ | FA_WRITE);
|
||||
REQUIRE(fr_result == FR_OK);
|
||||
|
||||
// Generate data
|
||||
uint32_t data_size = 100000;
|
||||
|
||||
char *data = (char*) malloc(data_size);
|
||||
char *read = (char*) malloc(data_size);
|
||||
|
||||
for(uint32_t i = 0; i < data_size; i += sizeof(i))
|
||||
{
|
||||
*((uint32_t*)(data + i)) = i;
|
||||
}
|
||||
|
||||
// Write generated data
|
||||
fr_result = f_write(&file, data, data_size, &bw);
|
||||
REQUIRE(fr_result == FR_OK);
|
||||
REQUIRE(bw == data_size);
|
||||
|
||||
// Move to beginning of file
|
||||
fr_result = f_lseek(&file, 0);
|
||||
REQUIRE(fr_result == FR_OK);
|
||||
|
||||
// Read written data
|
||||
fr_result = f_read(&file, read, data_size, &bw);
|
||||
REQUIRE(fr_result == FR_OK);
|
||||
REQUIRE(bw == data_size);
|
||||
|
||||
REQUIRE(memcmp(data, read, data_size) == 0);
|
||||
|
||||
// Close file
|
||||
fr_result = f_close(&file);
|
||||
REQUIRE(fr_result == FR_OK);
|
||||
|
||||
// Unmount default volume
|
||||
fr_result = f_mount(0, "", 0);
|
||||
REQUIRE(fr_result == FR_OK);
|
||||
|
||||
free(read);
|
||||
free(data);
|
||||
}
|
7
components/fatfs/test_fatfs_host/test_utils.c
Normal file
7
components/fatfs/test_fatfs_host/test_utils.c
Normal file
@ -0,0 +1,7 @@
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_partition.h"
|
||||
|
||||
void init_spi_flash(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin)
|
||||
{
|
||||
spi_flash_init(chip_size, block_size, sector_size, page_size, partition_bin);
|
||||
}
|
67
components/spi_flash/sim/Makefile
Normal file
67
components/spi_flash/sim/Makefile
Normal file
@ -0,0 +1,67 @@
|
||||
COMPONENT=spi_flash
|
||||
COMPONENT_LIB=lib$(COMPONENT).a
|
||||
|
||||
all: lib
|
||||
|
||||
SOURCE_FILES = \
|
||||
../partition.c \
|
||||
../flash_ops.c \
|
||||
SpiFlash.cpp \
|
||||
flash_mock_util.c \
|
||||
flash_mock.cpp \
|
||||
$(addprefix stubs/, \
|
||||
newlib/lock.c \
|
||||
app_update/esp_ota_eps.c \
|
||||
)
|
||||
|
||||
INCLUDE_FLAGS = $(addprefix -I,\
|
||||
. \
|
||||
../include \
|
||||
../../esp32/include/ \
|
||||
$(addprefix stubs/, \
|
||||
newlib/include \
|
||||
log/include \
|
||||
freertos/include \
|
||||
) \
|
||||
$(addprefix ../../../components/, \
|
||||
soc/esp32/include \
|
||||
esp32/include \
|
||||
bootloader_support/include \
|
||||
app_update/include \
|
||||
) \
|
||||
../../../tools/catch \
|
||||
)
|
||||
|
||||
GCOV ?= gcov
|
||||
|
||||
CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL -g -m32
|
||||
CFLAGS += -fprofile-arcs -ftest-coverage
|
||||
CXXFLAGS += -std=c++11 -Wall -Werror -fprofile-arcs -ftest-coverage
|
||||
LDFLAGS += -lstdc++ -fprofile-arcs -ftest-coverage
|
||||
|
||||
OBJ_FILES = $(filter %.o, $(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o))
|
||||
|
||||
$(COMPONENT_LIB): $(OBJ_FILES)
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
lib: $(COMPONENT_LIB)
|
||||
|
||||
COVERAGE_FILES = $(OBJ_FILES:.o=.gc*)
|
||||
|
||||
$(COVERAGE_FILES): lib
|
||||
|
||||
coverage.info: $(COVERAGE_FILES)
|
||||
find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} +
|
||||
lcov --capture --directory ../ --no-external --output-file coverage.info --gcov-tool $(GCOV)
|
||||
|
||||
coverage_report: coverage.info
|
||||
genhtml coverage.info --output-directory coverage_report
|
||||
@echo "Coverage report is in coverage_report/index.html"
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ_FILES) $(COMPONENT_LIB)
|
||||
rm -f $(COVERAGE_FILES) *.gcov
|
||||
rm -rf coverage_report/
|
||||
rm -f coverage.info
|
||||
|
||||
.PHONY: clean lib all
|
126
components/spi_flash/sim/SpiFlash.cpp
Normal file
126
components/spi_flash/sim/SpiFlash.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
// Copyright 2015-2017 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 "SpiFlash.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "esp_flash_data_types.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
SpiFlash::SpiFlash()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SpiFlash::~SpiFlash()
|
||||
{
|
||||
deinit();
|
||||
}
|
||||
|
||||
void SpiFlash::init(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partitions_bin)
|
||||
{
|
||||
// De-initialize first
|
||||
deinit();
|
||||
|
||||
this->chip_size = chip_size;
|
||||
this->block_size = block_size;
|
||||
this->sector_size = sector_size;
|
||||
this->page_size = page_size;
|
||||
|
||||
this->memory = (uint8_t *) malloc(this->chip_size);
|
||||
memset(this->memory, 0xFF, this->chip_size);
|
||||
|
||||
ifstream ifd(partitions_bin, ios::binary | ios::ate);
|
||||
int size = ifd.tellg();
|
||||
|
||||
ifd.seekg(0, ios::beg);
|
||||
vector<char> buffer;
|
||||
|
||||
buffer.resize(size);
|
||||
|
||||
ifd.read(buffer.data(), size);
|
||||
|
||||
memcpy(&this->memory[ESP_PARTITION_TABLE_ADDR], buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
void SpiFlash::deinit()
|
||||
{
|
||||
if(inited)
|
||||
{
|
||||
free(this->memory);
|
||||
}
|
||||
}
|
||||
|
||||
size_t SpiFlash::get_chip_size()
|
||||
{
|
||||
return this->chip_size;
|
||||
}
|
||||
|
||||
size_t SpiFlash::get_sector_size()
|
||||
{
|
||||
return this->sector_size;
|
||||
}
|
||||
|
||||
esp_rom_spiflash_result_t SpiFlash::erase_block(uint32_t block)
|
||||
{
|
||||
memset(&this->memory[block * this->block_size], 0xFF, this->block_size);
|
||||
return ESP_ROM_SPIFLASH_RESULT_OK;
|
||||
}
|
||||
|
||||
esp_rom_spiflash_result_t SpiFlash::erase_sector(size_t sector)
|
||||
{
|
||||
memset(&this->memory[sector * this->sector_size], 0xFF, this->sector_size);
|
||||
return ESP_ROM_SPIFLASH_RESULT_OK;
|
||||
}
|
||||
|
||||
esp_rom_spiflash_result_t SpiFlash::erase_page(uint32_t page)
|
||||
{
|
||||
memset(&this->memory[page * this->page_size], 0xFF, this->page_size);
|
||||
return ESP_ROM_SPIFLASH_RESULT_OK;
|
||||
}
|
||||
|
||||
esp_rom_spiflash_result_t SpiFlash::write(size_t dest_addr, const void *src, size_t size)
|
||||
{
|
||||
// Emulate inability to set programmed bits without erasing
|
||||
for(uint32_t ctr = 0; ctr < size; ctr++)
|
||||
{
|
||||
uint8_t data = ((uint8_t*)src)[ctr];
|
||||
uint8_t written = this->memory[dest_addr + ctr];
|
||||
|
||||
data &= written;
|
||||
|
||||
this->memory[dest_addr + ctr] = data;
|
||||
}
|
||||
|
||||
return ESP_ROM_SPIFLASH_RESULT_OK;
|
||||
}
|
||||
|
||||
esp_rom_spiflash_result_t SpiFlash::read(size_t src_addr, void *dest, size_t size)
|
||||
{
|
||||
memcpy(dest, &this->memory[src_addr], size);
|
||||
return ESP_ROM_SPIFLASH_RESULT_OK;
|
||||
}
|
||||
|
||||
uint8_t* SpiFlash::get_memory_ptr(uint32_t src_address)
|
||||
{
|
||||
return &this->memory[src_address];
|
||||
}
|
62
components/spi_flash/sim/SpiFlash.h
Normal file
62
components/spi_flash/sim/SpiFlash.h
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright 2015-2017 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 _SpiFlash_H_
|
||||
#define _SpiFlash_H_
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "rom/spi_flash.h"
|
||||
|
||||
/**
|
||||
* @brief This class is used to emulate flash devices.
|
||||
*
|
||||
*/
|
||||
class SpiFlash
|
||||
{
|
||||
|
||||
public:
|
||||
SpiFlash();
|
||||
~SpiFlash();
|
||||
|
||||
void init(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partitions_bin);
|
||||
|
||||
esp_rom_spiflash_result_t erase_block(uint32_t block);
|
||||
esp_rom_spiflash_result_t erase_sector(uint32_t sector);
|
||||
esp_rom_spiflash_result_t erase_page(uint32_t page);
|
||||
|
||||
esp_rom_spiflash_result_t write(size_t dest_addr, const void *src, size_t size);
|
||||
esp_rom_spiflash_result_t read(size_t src_addr, void *dest, size_t size);
|
||||
|
||||
size_t get_chip_size();
|
||||
size_t get_sector_size();
|
||||
|
||||
uint8_t* get_memory_ptr(uint32_t src_address);
|
||||
|
||||
private:
|
||||
bool inited = false;
|
||||
|
||||
size_t chip_size;
|
||||
size_t block_size;
|
||||
size_t sector_size;
|
||||
size_t page_size;
|
||||
|
||||
uint8_t* memory;
|
||||
|
||||
void* partitions;
|
||||
uint8_t partitions_num;
|
||||
|
||||
void deinit();
|
||||
};
|
||||
|
||||
#endif // _SpiFlash_H_
|
65
components/spi_flash/sim/flash_mock.cpp
Normal file
65
components/spi_flash/sim/flash_mock.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
#include "SpiFlash.h"
|
||||
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_partition.h"
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "rom/spi_flash.h"
|
||||
|
||||
static SpiFlash spiflash = SpiFlash();
|
||||
|
||||
esp_rom_spiflash_chip_t g_rom_flashchip;
|
||||
|
||||
extern "C" void _spi_flash_init(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partitions_bin)
|
||||
{
|
||||
spiflash.init(chip_size, block_size, sector_size, page_size, partitions_bin);
|
||||
|
||||
g_rom_flashchip.chip_size = chip_size;
|
||||
g_rom_flashchip.block_size = block_size;
|
||||
g_rom_flashchip.sector_size = sector_size;
|
||||
g_rom_flashchip.page_size = page_size;
|
||||
}
|
||||
|
||||
esp_err_t spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_memory_t memory,
|
||||
const void** out_ptr, spi_flash_mmap_handle_t* out_handle)
|
||||
{
|
||||
*out_handle = 0;
|
||||
*out_ptr = (void*)spiflash.get_memory_ptr(src_addr);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void spi_flash_munmap(spi_flash_mmap_handle_t handle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
esp_rom_spiflash_result_t esp_rom_spiflash_read(uint32_t target, uint32_t *dest, int32_t len)
|
||||
{
|
||||
return spiflash.read(target, dest, len);
|
||||
}
|
||||
|
||||
esp_rom_spiflash_result_t esp_rom_spiflash_erase_block(uint32_t block)
|
||||
{
|
||||
return spiflash.erase_block(block);
|
||||
}
|
||||
|
||||
esp_rom_spiflash_result_t esp_rom_spiflash_erase_sector(uint32_t sector)
|
||||
{
|
||||
return spiflash.erase_sector(sector);
|
||||
}
|
||||
|
||||
esp_rom_spiflash_result_t esp_rom_spiflash_erase_page(uint32_t page)
|
||||
{
|
||||
return spiflash.erase_page(page);
|
||||
}
|
||||
|
||||
esp_rom_spiflash_result_t esp_rom_spiflash_write(uint32_t target, const uint32_t *src, int32_t len)
|
||||
{
|
||||
return spiflash.write(target, src, len);
|
||||
}
|
||||
|
||||
esp_rom_spiflash_result_t esp_rom_spiflash_write_encrypted(uint32_t flash_addr, uint32_t *data, uint32_t len)
|
||||
{
|
||||
return spiflash.write(flash_addr, data, len);
|
||||
}
|
57
components/spi_flash/sim/flash_mock_util.c
Normal file
57
components/spi_flash/sim/flash_mock_util.c
Normal file
@ -0,0 +1,57 @@
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_partition.h"
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "rom/spi_flash.h"
|
||||
|
||||
extern void _spi_flash_init(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin);
|
||||
|
||||
void spi_flash_init(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin)
|
||||
{
|
||||
_spi_flash_init(chip_size, block_size, sector_size, page_size, partition_bin);
|
||||
}
|
||||
|
||||
void spi_flash_mark_modified_region(size_t start_addr, size_t length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
esp_rom_spiflash_result_t esp_rom_spiflash_unlock()
|
||||
{
|
||||
return ESP_ROM_SPIFLASH_RESULT_OK;
|
||||
}
|
||||
|
||||
void spi_flash_init_lock()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void spi_flash_op_lock()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void spi_flash_op_unlock()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void spi_flash_disable_interrupts_caches_and_other_cpu()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void spi_flash_enable_interrupts_caches_and_other_cpu()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void spi_flash_disable_interrupts_caches_and_other_cpu_no_os()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void spi_flash_enable_interrupts_caches_no_os()
|
||||
{
|
||||
return;
|
||||
}
|
2
components/spi_flash/sim/sdkconfig.h
Normal file
2
components/spi_flash/sim/sdkconfig.h
Normal file
@ -0,0 +1,2 @@
|
||||
#pragma once
|
||||
|
13
components/spi_flash/sim/stubs/app_update/esp_ota_eps.c
Normal file
13
components/spi_flash/sim/stubs/app_update/esp_ota_eps.c
Normal file
@ -0,0 +1,13 @@
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_partition.h"
|
||||
|
||||
const esp_partition_t* esp_ota_get_running_partition(void)
|
||||
{
|
||||
// Return first instance of an app partition
|
||||
const esp_partition_t* partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP,
|
||||
ESP_PARTITION_SUBTYPE_ANY,
|
||||
NULL);
|
||||
assert(partition != NULL);
|
||||
|
||||
return partition;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "projdefs.h"
|
||||
#include "semphr.h"
|
||||
|
||||
// Avoid redefinition compile error. Put here since this is included
|
||||
// in flash_ops.c.
|
||||
#define spi_flash_init() overriden_spi_flash_init()
|
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define pdTRUE 1
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define vSemaphoreDelete( xSemaphore )
|
||||
#define xSemaphoreCreateMutex() ((void*)(1))
|
||||
#define xSemaphoreGive( xSemaphore )
|
||||
#define xSemaphoreTake( xSemaphore, xBlockTime ) pdTRUE
|
||||
|
||||
typedef void* SemaphoreHandle_t;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
@ -0,0 +1 @@
|
||||
#pragma once
|
48
components/spi_flash/sim/stubs/log/include/esp_log.h
Normal file
48
components/spi_flash/sim/stubs/log/include/esp_log.h
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
|
||||
typedef enum {
|
||||
ESP_LOG_NONE, /*!< No log output */
|
||||
ESP_LOG_ERROR, /*!< Critical errors, software module can not recover on its own */
|
||||
ESP_LOG_WARN, /*!< Error conditions from which recovery measures have been taken */
|
||||
ESP_LOG_INFO, /*!< Information messages which describe normal flow of events */
|
||||
ESP_LOG_DEBUG, /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */
|
||||
ESP_LOG_VERBOSE /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */
|
||||
} esp_log_level_t;
|
||||
|
||||
#define LOG_COLOR_E
|
||||
#define LOG_COLOR_W
|
||||
#define LOG_COLOR_I
|
||||
#define LOG_COLOR_D
|
||||
#define LOG_COLOR_V
|
||||
#define LOG_RESET_COLOR
|
||||
|
||||
uint32_t esp_log_timestamp(void);
|
||||
void esp_log_write(esp_log_level_t level, const char* tag, const char* format, ...) __attribute__ ((format (printf, 3, 4)));
|
||||
|
||||
#define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%d) %s: " format LOG_RESET_COLOR "\n"
|
||||
|
||||
#define ESP_LOGE( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_ERROR) { esp_log_write(ESP_LOG_ERROR, tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
|
||||
|
||||
#define ESP_LOGV( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_VERBOSE) { esp_log_write(ESP_LOG_VERBOSE, tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
|
||||
|
||||
#define ESP_LOGD( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { esp_log_write(ESP_LOG_DEBUG, tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
|
||||
|
||||
#define ESP_LOGW( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_WARN) { esp_log_write(ESP_LOG_WARN, tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
|
||||
|
||||
// Assume that flash encryption is not enabled. Put here since in partition.c
|
||||
// esp_log.h is included later than esp_flash_encrypt.h.
|
||||
#define esp_flash_encryption_enabled() false
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
22
components/spi_flash/sim/stubs/log/log.c
Normal file
22
components/spi_flash/sim/stubs/log/log.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
void esp_log_write(esp_log_level_t level,
|
||||
const char *tag,
|
||||
const char *format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
vprintf(format, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
|
||||
uint32_t esp_log_timestamp()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
17
components/spi_flash/sim/stubs/newlib/include/sys/lock.h
Normal file
17
components/spi_flash/sim/stubs/newlib/include/sys/lock.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int _lock_t;
|
||||
|
||||
void _lock_acquire(_lock_t *lock);
|
||||
void _lock_close(_lock_t *lock);
|
||||
void _lock_init(_lock_t *lock);
|
||||
void _lock_release(_lock_t *lock);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
21
components/spi_flash/sim/stubs/newlib/lock.c
Normal file
21
components/spi_flash/sim/stubs/newlib/lock.c
Normal file
@ -0,0 +1,21 @@
|
||||
#include "sys/lock.h"
|
||||
|
||||
void _lock_acquire(_lock_t *lock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void _lock_close(_lock_t *lock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void _lock_init(_lock_t *lock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void _lock_release(_lock_t *lock)
|
||||
{
|
||||
return;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
COMPONENT_ADD_INCLUDEDIRS := include
|
||||
COMPONENT_PRIV_INCLUDEDIRS := spiffs/src
|
||||
COMPONENT_PRIV_INCLUDEDIRS := . spiffs/src
|
||||
COMPONENT_SRCDIRS := . spiffs/src
|
||||
|
||||
COMPONENT_SUBMODULES := spiffs
|
||||
|
@ -30,29 +30,12 @@
|
||||
#include "esp_vfs.h"
|
||||
#include "esp_err.h"
|
||||
#include "rom/spi_flash.h"
|
||||
|
||||
static const char * TAG = "SPIFFS";
|
||||
#include "spiffs_api.h"
|
||||
|
||||
#ifdef CONFIG_SPIFFS_USE_MTIME
|
||||
_Static_assert(CONFIG_SPIFFS_META_LENGTH >= sizeof(time_t),
|
||||
"SPIFFS_META_LENGTH size should be >= sizeof(time_t)");
|
||||
#endif //CONFIG_SPIFFS_USE_MTIME
|
||||
/**
|
||||
* @brief SPIFFS definition structure
|
||||
*/
|
||||
typedef struct {
|
||||
spiffs *fs; /*!< Handle to the underlying SPIFFS */
|
||||
SemaphoreHandle_t lock; /*!< FS lock */
|
||||
const esp_partition_t* partition; /*!< The partition on which SPIFFS is located */
|
||||
char base_path[ESP_VFS_PATH_MAX+1]; /*!< Mount point */
|
||||
bool by_label; /*!< Partition was mounted by label */
|
||||
spiffs_config cfg; /*!< SPIFFS Mount configuration */
|
||||
uint8_t *work; /*!< Work Buffer */
|
||||
uint8_t *fds; /*!< File Descriptor Buffer */
|
||||
uint32_t fds_sz; /*!< File Descriptor Buffer Length */
|
||||
uint8_t *cache; /*!< Cache Buffer */
|
||||
uint32_t cache_sz; /*!< Cache Buffer Length */
|
||||
} esp_spiffs_t;
|
||||
|
||||
/**
|
||||
* @brief SPIFFS DIR structure
|
||||
@ -89,77 +72,6 @@ static time_t vfs_spiffs_get_mtime(const spiffs_stat* s);
|
||||
|
||||
static esp_spiffs_t * _efs[CONFIG_SPIFFS_MAX_PARTITIONS];
|
||||
|
||||
void spiffs_api_lock(spiffs *fs)
|
||||
{
|
||||
xSemaphoreTake(((esp_spiffs_t *)(fs->user_data))->lock, portMAX_DELAY);
|
||||
}
|
||||
|
||||
void spiffs_api_unlock(spiffs *fs)
|
||||
{
|
||||
xSemaphoreGive(((esp_spiffs_t *)(fs->user_data))->lock);
|
||||
}
|
||||
|
||||
static s32_t spiffs_api_read(spiffs *fs, uint32_t addr, uint32_t size, uint8_t *dst)
|
||||
{
|
||||
esp_err_t err = esp_partition_read(((esp_spiffs_t *)(fs->user_data))->partition,
|
||||
addr, dst, size);
|
||||
if (err) {
|
||||
ESP_LOGE(TAG, "failed to read addr %08x, size %08x, err %d", addr, size, err);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static s32_t spiffs_api_write(spiffs *fs, uint32_t addr, uint32_t size, uint8_t *src)
|
||||
{
|
||||
esp_err_t err = esp_partition_write(((esp_spiffs_t *)(fs->user_data))->partition,
|
||||
addr, src, size);
|
||||
if (err) {
|
||||
ESP_LOGE(TAG, "failed to write addr %08x, size %08x, err %d", addr, size, err);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static s32_t spiffs_api_erase(spiffs *fs, uint32_t addr, uint32_t size)
|
||||
{
|
||||
esp_err_t err = esp_partition_erase_range(((esp_spiffs_t *)(fs->user_data))->partition,
|
||||
addr, size);
|
||||
if (err) {
|
||||
ESP_LOGE(TAG, "failed to erase addr %08x, size %08x, err %d", addr, size, err);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void spiffs_api_check(spiffs *fs, spiffs_check_type type,
|
||||
spiffs_check_report report, uint32_t arg1, uint32_t arg2)
|
||||
{
|
||||
static const char * spiffs_check_type_str[3] = {
|
||||
"LOOKUP",
|
||||
"INDEX",
|
||||
"PAGE"
|
||||
};
|
||||
|
||||
static const char * spiffs_check_report_str[7] = {
|
||||
"PROGRESS",
|
||||
"ERROR",
|
||||
"FIX INDEX",
|
||||
"FIX LOOKUP",
|
||||
"DELETE ORPHANED INDEX",
|
||||
"DELETE PAGE",
|
||||
"DELETE BAD FILE"
|
||||
};
|
||||
|
||||
if (report != SPIFFS_CHECK_PROGRESS) {
|
||||
ESP_LOGE(TAG, "CHECK: type:%s, report:%s, %x:%x", spiffs_check_type_str[type],
|
||||
spiffs_check_report_str[report], arg1, arg2);
|
||||
} else {
|
||||
ESP_LOGV(TAG, "CHECK PROGRESS: report:%s, %x:%x",
|
||||
spiffs_check_report_str[report], arg1, arg2);
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_spiffs_free(esp_spiffs_t ** efs)
|
||||
{
|
||||
esp_spiffs_t * e = *efs;
|
||||
@ -232,7 +144,7 @@ static esp_err_t esp_spiffs_init(const esp_vfs_spiffs_conf_t* conf)
|
||||
|
||||
esp_partition_subtype_t subtype = conf->partition_label ?
|
||||
ESP_PARTITION_SUBTYPE_ANY : ESP_PARTITION_SUBTYPE_DATA_SPIFFS;
|
||||
const esp_partition_t* partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,
|
||||
const esp_partition_t* partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,
|
||||
subtype, conf->partition_label);
|
||||
if (!partition) {
|
||||
ESP_LOGE(TAG, "spiffs partition could not be found");
|
||||
@ -310,7 +222,7 @@ static esp_err_t esp_spiffs_init(const esp_vfs_spiffs_conf_t* conf)
|
||||
efs->fs->user_data = (void *)efs;
|
||||
efs->partition = partition;
|
||||
|
||||
s32_t res = SPIFFS_mount(efs->fs, &efs->cfg, efs->work, efs->fds, efs->fds_sz,
|
||||
s32_t res = SPIFFS_mount(efs->fs, &efs->cfg, efs->work, efs->fds, efs->fds_sz,
|
||||
efs->cache, efs->cache_sz, spiffs_api_check);
|
||||
|
||||
if (conf->format_if_mount_failed && res != SPIFFS_OK) {
|
||||
@ -323,7 +235,7 @@ static esp_err_t esp_spiffs_init(const esp_vfs_spiffs_conf_t* conf)
|
||||
esp_spiffs_free(&efs);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
res = SPIFFS_mount(efs->fs, &efs->cfg, efs->work, efs->fds, efs->fds_sz,
|
||||
res = SPIFFS_mount(efs->fs, &efs->cfg, efs->work, efs->fds, efs->fds_sz,
|
||||
efs->cache, efs->cache_sz, spiffs_api_check);
|
||||
}
|
||||
if (res != SPIFFS_OK) {
|
||||
@ -710,7 +622,7 @@ static struct dirent* vfs_spiffs_readdir(void* ctx, DIR* pdir)
|
||||
return out_dirent;
|
||||
}
|
||||
|
||||
static int vfs_spiffs_readdir_r(void* ctx, DIR* pdir, struct dirent* entry,
|
||||
static int vfs_spiffs_readdir_r(void* ctx, DIR* pdir, struct dirent* entry,
|
||||
struct dirent** out_dirent)
|
||||
{
|
||||
assert(pdir);
|
||||
|
93
components/spiffs/spiffs_api.c
Normal file
93
components/spiffs/spiffs_api.c
Normal file
@ -0,0 +1,93 @@
|
||||
// Copyright 2015-2017 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 "freertos/FreeRTOS.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_partition.h"
|
||||
#include "esp_spiffs.h"
|
||||
#include "esp_vfs.h"
|
||||
#include "spiffs_api.h"
|
||||
|
||||
const char* TAG = "SPIFFS";
|
||||
|
||||
void spiffs_api_lock(spiffs *fs)
|
||||
{
|
||||
xSemaphoreTake(((esp_spiffs_t *)(fs->user_data))->lock, portMAX_DELAY);
|
||||
}
|
||||
|
||||
void spiffs_api_unlock(spiffs *fs)
|
||||
{
|
||||
xSemaphoreGive(((esp_spiffs_t *)(fs->user_data))->lock);
|
||||
}
|
||||
|
||||
s32_t spiffs_api_read(spiffs *fs, uint32_t addr, uint32_t size, uint8_t *dst)
|
||||
{
|
||||
esp_err_t err = esp_partition_read(((esp_spiffs_t *)(fs->user_data))->partition,
|
||||
addr, dst, size);
|
||||
if (err) {
|
||||
ESP_LOGE(TAG, "failed to read addr %08x, size %08x, err %d", addr, size, err);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32_t spiffs_api_write(spiffs *fs, uint32_t addr, uint32_t size, uint8_t *src)
|
||||
{
|
||||
esp_err_t err = esp_partition_write(((esp_spiffs_t *)(fs->user_data))->partition,
|
||||
addr, src, size);
|
||||
if (err) {
|
||||
ESP_LOGE(TAG, "failed to write addr %08x, size %08x, err %d", addr, size, err);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32_t spiffs_api_erase(spiffs *fs, uint32_t addr, uint32_t size)
|
||||
{
|
||||
esp_err_t err = esp_partition_erase_range(((esp_spiffs_t *)(fs->user_data))->partition,
|
||||
addr, size);
|
||||
if (err) {
|
||||
ESP_LOGE(TAG, "failed to erase addr %08x, size %08x, err %d", addr, size, err);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void spiffs_api_check(spiffs *fs, spiffs_check_type type,
|
||||
spiffs_check_report report, uint32_t arg1, uint32_t arg2)
|
||||
{
|
||||
static const char * spiffs_check_type_str[3] = {
|
||||
"LOOKUP",
|
||||
"INDEX",
|
||||
"PAGE"
|
||||
};
|
||||
|
||||
static const char * spiffs_check_report_str[7] = {
|
||||
"PROGRESS",
|
||||
"ERROR",
|
||||
"FIX INDEX",
|
||||
"FIX LOOKUP",
|
||||
"DELETE ORPHANED INDEX",
|
||||
"DELETE PAGE",
|
||||
"DELETE BAD FILE"
|
||||
};
|
||||
|
||||
if (report != SPIFFS_CHECK_PROGRESS) {
|
||||
ESP_LOGE(TAG, "CHECK: type:%s, report:%s, %x:%x", spiffs_check_type_str[type],
|
||||
spiffs_check_report_str[report], arg1, arg2);
|
||||
} else {
|
||||
ESP_LOGV(TAG, "CHECK PROGRESS: report:%s, %x:%x",
|
||||
spiffs_check_report_str[report], arg1, arg2);
|
||||
}
|
||||
}
|
59
components/spiffs/spiffs_api.h
Normal file
59
components/spiffs/spiffs_api.h
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2015-2017 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 <stddef.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "spiffs.h"
|
||||
#include "esp_vfs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const char* TAG;
|
||||
|
||||
/**
|
||||
* @brief SPIFFS definition structure
|
||||
*/
|
||||
typedef struct {
|
||||
spiffs *fs; /*!< Handle to the underlying SPIFFS */
|
||||
SemaphoreHandle_t lock; /*!< FS lock */
|
||||
const esp_partition_t* partition; /*!< The partition on which SPIFFS is located */
|
||||
char base_path[ESP_VFS_PATH_MAX+1]; /*!< Mount point */
|
||||
bool by_label; /*!< Partition was mounted by label */
|
||||
spiffs_config cfg; /*!< SPIFFS Mount configuration */
|
||||
uint8_t *work; /*!< Work Buffer */
|
||||
uint8_t *fds; /*!< File Descriptor Buffer */
|
||||
uint32_t fds_sz; /*!< File Descriptor Buffer Length */
|
||||
uint8_t *cache; /*!< Cache Buffer */
|
||||
uint32_t cache_sz; /*!< Cache Buffer Length */
|
||||
} esp_spiffs_t;
|
||||
|
||||
s32_t spiffs_api_read(spiffs *fs, uint32_t addr, uint32_t size, uint8_t *dst);
|
||||
|
||||
s32_t spiffs_api_write(spiffs *fs, uint32_t addr, uint32_t size, uint8_t *src);
|
||||
|
||||
s32_t spiffs_api_erase(spiffs *fs, uint32_t addr, uint32_t size);
|
||||
|
||||
void spiffs_api_check(spiffs *fs, spiffs_check_type type,
|
||||
spiffs_check_report report, uint32_t arg1, uint32_t arg2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
97
components/spiffs/test_spiffs_host/Makefile
Normal file
97
components/spiffs/test_spiffs_host/Makefile
Normal file
@ -0,0 +1,97 @@
|
||||
COMPONENT=spiffs
|
||||
|
||||
TEST_PROGRAM=test_$(COMPONENT)
|
||||
|
||||
#Expose as a library
|
||||
COMPONENT_LIB=lib$(COMPONENT).a
|
||||
|
||||
SPI_FLASH=spi_flash
|
||||
SPI_FLASH_DIR=../../$(SPI_FLASH)
|
||||
SPI_FLASH_SIM_DIR=$(SPI_FLASH_DIR)/sim
|
||||
SPI_FLASH_LIB=lib$(SPI_FLASH).a
|
||||
|
||||
all: $(TEST_PROGRAM)
|
||||
|
||||
SOURCE_FILES = \
|
||||
../spiffs_api.c \
|
||||
$(addprefix ../spiffs/src/, \
|
||||
spiffs_cache.c \
|
||||
spiffs_check.c \
|
||||
spiffs_gc.c \
|
||||
spiffs_hydrogen.c \
|
||||
spiffs_nucleus.c \
|
||||
) \
|
||||
$(addprefix ./stubs/, \
|
||||
log/log.c \
|
||||
)
|
||||
|
||||
TEST_SOURCE_FILES = \
|
||||
test_spiffs.cpp \
|
||||
main.cpp \
|
||||
test_utils.c
|
||||
|
||||
INCLUDE_FLAGS = $(addprefix -I,\
|
||||
. \
|
||||
.. \
|
||||
../spiffs/src \
|
||||
../include \
|
||||
$(addprefix ./stubs/, \
|
||||
log/include \
|
||||
freertos/include \
|
||||
newlib/include \
|
||||
vfs/include \
|
||||
) \
|
||||
../../esp32/include \
|
||||
$(SPI_FLASH_DIR)/include \
|
||||
../../../tools/catch \
|
||||
)
|
||||
|
||||
GCOV ?= gcov
|
||||
|
||||
CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL -g -m32
|
||||
CFLAGS += -fprofile-arcs -ftest-coverage
|
||||
CXXFLAGS += -std=c++11 -Wall -Werror -fprofile-arcs -ftest-coverage
|
||||
LDFLAGS += -lstdc++ -fprofile-arcs -ftest-coverage
|
||||
|
||||
OBJ_FILES = $(filter %.o, $(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o))
|
||||
TEST_OBJ_FILES = $(filter %.o, $(TEST_SOURCE_FILES:.cpp=.o) $(TEST_SOURCE_FILES:.c=.o))
|
||||
|
||||
$(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB): force
|
||||
$(MAKE) -C $(SPI_FLASH_SIM_DIR) lib
|
||||
|
||||
force:
|
||||
|
||||
$(COMPONENT_LIB): $(OBJ_FILES)
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
lib: $(COMPONENT_LIB)
|
||||
|
||||
partitions_table.bin: partitions_table.csv
|
||||
python ../../partition_table/gen_esp32part.py --verify $< $@
|
||||
|
||||
$(TEST_PROGRAM): lib $(TEST_OBJ_FILES) $(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB) partitions_table.bin
|
||||
g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(TEST_OBJ_FILES) -L$(abspath .) -l:$(COMPONENT_LIB) -L$(SPI_FLASH_SIM_DIR) -l:$(SPI_FLASH_LIB) -g -m32
|
||||
|
||||
test: $(TEST_PROGRAM)
|
||||
./$(TEST_PROGRAM)
|
||||
|
||||
COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(TEST_OBJ_FILES:.o=.gc*)
|
||||
|
||||
$(COVERAGE_FILES): test
|
||||
|
||||
coverage.info: $(COVERAGE_FILES)
|
||||
find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} +
|
||||
lcov --capture --directory ../ --no-external --output-file coverage.info --gcov-tool $(GCOV)
|
||||
|
||||
coverage_report: coverage.info
|
||||
genhtml coverage.info --output-directory coverage_report
|
||||
@echo "Coverage report is in coverage_report/index.html"
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ_FILES) $(TEST_OBJ_FILES) $(TEST_PROGRAM) $(COMPONENT_LIB) partitions_table.bin
|
||||
$(MAKE) -C $(SPI_FLASH_SIM_DIR) clean
|
||||
rm -f $(COVERAGE_FILES) *.gcov
|
||||
rm -rf coverage_report/
|
||||
rm -f coverage.info
|
||||
|
||||
.PHONY: clean all test lib
|
3
components/spiffs/test_spiffs_host/main.cpp
Normal file
3
components/spiffs/test_spiffs_host/main.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
|
6
components/spiffs/test_spiffs_host/partitions_table.csv
Normal file
6
components/spiffs/test_spiffs_host/partitions_table.csv
Normal file
@ -0,0 +1,6 @@
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
|
||||
nvs, data, nvs, 0x9000, 0x6000,
|
||||
phy_init, data, phy, 0xf000, 0x1000,
|
||||
factory, app, factory, 0x10000, 1M,
|
||||
storage, data, spiffs, , 2M,
|
|
14
components/spiffs/test_spiffs_host/sdkconfig.h
Normal file
14
components/spiffs/test_spiffs_host/sdkconfig.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1
|
||||
#define CONFIG_SPIFFS_MAX_PARTITIONS 3
|
||||
#define CONFIG_SPIFFS_OBJ_NAME_LEN 32
|
||||
#define CONFIG_SPIFFS_PAGE_SIZE 256
|
||||
#define CONFIG_SPIFFS_GC_MAX_RUNS 10
|
||||
#define CONFIG_SPIFFS_CACHE_WR 1
|
||||
#define CONFIG_SPIFFS_CACHE 1
|
||||
#define CONFIG_SPIFFS_META_LENGTH 4
|
||||
#define CONFIG_SPIFFS_USE_MAGIC 1
|
||||
#define CONFIG_SPIFFS_PAGE_CHECK 1
|
||||
#define CONFIG_SPIFFS_USE_MTIME 1
|
||||
#define CONFIG_WL_SECTOR_SIZE 4096
|
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "projdefs.h"
|
||||
#include "semphr.h"
|
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define pdTRUE 1
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define vSemaphoreDelete( xSemaphore )
|
||||
#define xSemaphoreCreateMutex() ((void*)(1))
|
||||
#define xSemaphoreGive( xSemaphore )
|
||||
#define xSemaphoreTake( xSemaphore, xBlockTime ) pdTRUE
|
||||
|
||||
typedef void* SemaphoreHandle_t;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
@ -0,0 +1 @@
|
||||
#pragma once
|
@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#define strlcpy(a, b, c)
|
||||
#define strlcat(a, b, c)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
|
||||
typedef enum {
|
||||
ESP_LOG_NONE, /*!< No log output */
|
||||
ESP_LOG_ERROR, /*!< Critical errors, software module can not recover on its own */
|
||||
ESP_LOG_WARN, /*!< Error conditions from which recovery measures have been taken */
|
||||
ESP_LOG_INFO, /*!< Information messages which describe normal flow of events */
|
||||
ESP_LOG_DEBUG, /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */
|
||||
ESP_LOG_VERBOSE /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */
|
||||
} esp_log_level_t;
|
||||
|
||||
#define LOG_COLOR_E
|
||||
#define LOG_COLOR_W
|
||||
#define LOG_COLOR_I
|
||||
#define LOG_COLOR_D
|
||||
#define LOG_COLOR_V
|
||||
#define LOG_RESET_COLOR
|
||||
|
||||
#undef _Static_assert
|
||||
#define _Static_assert(cond, message)
|
||||
|
||||
uint32_t esp_log_timestamp(void);
|
||||
void esp_log_write(esp_log_level_t level, const char* tag, const char* format, ...) __attribute__ ((format (printf, 3, 4)));
|
||||
|
||||
#define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%d) %s: " format LOG_RESET_COLOR "\n"
|
||||
|
||||
#define ESP_LOGE( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_ERROR) { esp_log_write(ESP_LOG_ERROR, tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
|
||||
|
||||
#define ESP_LOGV( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_VERBOSE) { esp_log_write(ESP_LOG_VERBOSE, tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
|
||||
|
||||
#define ESP_LOGD( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { esp_log_write(ESP_LOG_DEBUG, tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
|
||||
|
||||
#define ESP_LOGW( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_WARN) { esp_log_write(ESP_LOG_WARN, tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
22
components/spiffs/test_spiffs_host/stubs/log/log.c
Normal file
22
components/spiffs/test_spiffs_host/stubs/log/log.c
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
void esp_log_write(esp_log_level_t level,
|
||||
const char *tag,
|
||||
const char *format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
vprintf(format, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
|
||||
uint32_t esp_log_timestamp()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <time.h>
|
||||
|
||||
typedef int _lock_t;
|
||||
|
||||
void _lock_acquire(_lock_t *lock);
|
||||
void _lock_close(_lock_t *lock);
|
||||
void _lock_init(_lock_t *lock);
|
||||
void _lock_release(_lock_t *lock);
|
21
components/spiffs/test_spiffs_host/stubs/newlib/lock.c
Normal file
21
components/spiffs/test_spiffs_host/stubs/newlib/lock.c
Normal file
@ -0,0 +1,21 @@
|
||||
#include "sys/lock.h"
|
||||
|
||||
void _lock_acquire(_lock_t *lock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void _lock_close(_lock_t *lock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void _lock_init(_lock_t *lock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void _lock_release(_lock_t *lock)
|
||||
{
|
||||
return;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#define ESP_VFS_FLAG_CONTEXT_PTR 1
|
||||
#define ESP_VFS_PATH_MAX 15
|
107
components/spiffs/test_spiffs_host/test_spiffs.cpp
Normal file
107
components/spiffs/test_spiffs_host/test_spiffs.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_partition.h"
|
||||
#include "spiffs.h"
|
||||
#include "spiffs_nucleus.h"
|
||||
#include "spiffs_api.h"
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
extern "C" void init_spi_flash(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin);
|
||||
|
||||
TEST_CASE("format disk, open file, write and read file", "[spiffs]")
|
||||
{
|
||||
init_spi_flash(0x00400000, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partitions_table.bin");
|
||||
|
||||
spiffs fs;
|
||||
spiffs_config cfg;
|
||||
|
||||
const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, "storage");
|
||||
|
||||
// Configure objects needed by SPIFFS
|
||||
esp_spiffs_t esp_user_data;
|
||||
esp_user_data.partition = partition;
|
||||
fs.user_data = (void*)&esp_user_data;
|
||||
|
||||
cfg.hal_erase_f = spiffs_api_erase;
|
||||
cfg.hal_read_f = spiffs_api_read;
|
||||
cfg.hal_write_f = spiffs_api_write;
|
||||
cfg.log_block_size = CONFIG_WL_SECTOR_SIZE;
|
||||
cfg.log_page_size = CONFIG_SPIFFS_PAGE_SIZE;
|
||||
cfg.phys_addr = 0;
|
||||
cfg.phys_erase_block = CONFIG_WL_SECTOR_SIZE;
|
||||
cfg.phys_size = partition->size;
|
||||
|
||||
uint32_t max_files = 5;
|
||||
|
||||
uint32_t fds_sz = max_files * sizeof(spiffs_fd);
|
||||
uint32_t work_sz = cfg.log_page_size * 2;
|
||||
uint32_t cache_sz = sizeof(spiffs_cache) + max_files * (sizeof(spiffs_cache_page)
|
||||
+ cfg.log_page_size);
|
||||
|
||||
uint8_t *work = (uint8_t*) malloc(work_sz);
|
||||
uint8_t *fds = (uint8_t*) malloc(fds_sz);
|
||||
uint8_t *cache = (uint8_t*) malloc(cache_sz);
|
||||
|
||||
s32_t spiffs_res;
|
||||
|
||||
// Special mounting procedure: mount, format, mount as per
|
||||
// https://github.com/pellepl/spiffs/wiki/Using-spiffs
|
||||
spiffs_res = SPIFFS_mount(&fs, &cfg, work, fds, fds_sz,
|
||||
cache, cache_sz, spiffs_api_check);
|
||||
REQUIRE(spiffs_res == SPIFFS_ERR_NOT_A_FS);
|
||||
|
||||
spiffs_res = SPIFFS_format(&fs);
|
||||
REQUIRE(spiffs_res >= SPIFFS_OK);
|
||||
|
||||
spiffs_res = SPIFFS_mount(&fs, &cfg, work, fds, fds_sz,
|
||||
cache, cache_sz, spiffs_api_check);
|
||||
REQUIRE(spiffs_res >= SPIFFS_OK);
|
||||
|
||||
// Open test file
|
||||
spiffs_res = SPIFFS_open(&fs, "test.txt", SPIFFS_O_CREAT | SPIFFS_O_RDWR, 0);
|
||||
REQUIRE(spiffs_res >= SPIFFS_OK);
|
||||
|
||||
// Generate data
|
||||
spiffs_file file = spiffs_res;
|
||||
|
||||
uint32_t data_size = 100000;
|
||||
|
||||
char *data = (char*) malloc(data_size);
|
||||
char *read = (char*) malloc(data_size);
|
||||
|
||||
for(uint32_t i = 0; i < data_size; i += sizeof(i))
|
||||
{
|
||||
*((uint32_t*)(data + i)) = i;
|
||||
}
|
||||
|
||||
s32_t bw;
|
||||
|
||||
// Write data to file
|
||||
spiffs_res = SPIFFS_write(&fs, file, (void*)data, data_size);
|
||||
REQUIRE(spiffs_res >= SPIFFS_OK);
|
||||
REQUIRE(spiffs_res == data_size);
|
||||
|
||||
// Set the file object pointer to the beginning
|
||||
spiffs_res = SPIFFS_lseek(&fs, file, 0, SPIFFS_SEEK_SET);
|
||||
REQUIRE(spiffs_res >= SPIFFS_OK);
|
||||
|
||||
// Read the file
|
||||
spiffs_res = SPIFFS_read(&fs, file, (void*)read, data_size);
|
||||
REQUIRE(spiffs_res >= SPIFFS_OK);
|
||||
REQUIRE(spiffs_res == data_size);
|
||||
|
||||
// Close the test file
|
||||
spiffs_res = SPIFFS_close(&fs, file);
|
||||
REQUIRE(spiffs_res >= SPIFFS_OK);
|
||||
|
||||
REQUIRE(memcmp(data, read, data_size) == 0);
|
||||
|
||||
// Unmount
|
||||
SPIFFS_unmount(&fs);
|
||||
|
||||
free(read);
|
||||
free(data);
|
||||
}
|
7
components/spiffs/test_spiffs_host/test_utils.c
Normal file
7
components/spiffs/test_spiffs_host/test_utils.c
Normal file
@ -0,0 +1,7 @@
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_partition.h"
|
||||
|
||||
void init_spi_flash(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin)
|
||||
{
|
||||
spi_flash_init(chip_size, block_size, sector_size, page_size, partition_bin);
|
||||
}
|
@ -31,6 +31,7 @@ esp_err_t Partition::erase_sector(size_t sector)
|
||||
result = erase_range(sector * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE);
|
||||
return result;
|
||||
}
|
||||
|
||||
esp_err_t Partition::erase_range(size_t start_address, size_t size)
|
||||
{
|
||||
esp_err_t result = esp_partition_erase_range(this->partition, start_address, size);
|
||||
@ -48,6 +49,7 @@ esp_err_t Partition::write(size_t dest_addr, const void *src, size_t size)
|
||||
result = esp_partition_write(this->partition, dest_addr, src, size);
|
||||
return result;
|
||||
}
|
||||
|
||||
esp_err_t Partition::read(size_t src_addr, void *dest, size_t size)
|
||||
{
|
||||
esp_err_t result = ESP_OK;
|
||||
|
@ -10,10 +10,9 @@ The WLC Files
|
||||
^^^^^^^^^^^^^^^
|
||||
The WLC consist of few components that are implemented in different files. The list and brief description of these components written below.
|
||||
|
||||
- Flash_Access - memory access interface. Used to access the memory. A classes WL_Flash, Partition, SPI_Flash, Flash_Emulator are implements this interface.
|
||||
- Flash_Access - memory access interface. Used to access the memory. A classes WL_Flash, Partition, SPI_Flash are implements this interface.
|
||||
- SPI_Flash - class implements the Flash_Access interface to provide access to the flash memory.
|
||||
- Partition - class implements the Flash_Access interface to provide access to the partition.
|
||||
- Flash_Emulator - class implements the Flash_Access interface to provide test functionality for WLC testing.
|
||||
- WL_Flash - the main class that implements wear levelling functionality.
|
||||
- WL_State - contains state structure of the WLC.
|
||||
- WL_Config - contains structure to configure the WLC component at startup.
|
||||
|
@ -1,129 +0,0 @@
|
||||
// Copyright 2015-2017 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 "Flash_Emulator.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
Flash_Emulator::Flash_Emulator(size_t size, size_t sector_sise, size_t min_size)
|
||||
{
|
||||
this->reset_count = 0x7fffffff;
|
||||
this->size = size;
|
||||
this->sector_sise = sector_sise;
|
||||
this->min_size = min_size;
|
||||
this->buff = (uint8_t *)malloc(this->size);
|
||||
this->access_count = new uint32_t[this->size / this->sector_sise];
|
||||
memset(this->access_count, 0, this->size / this->sector_sise * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
size_t Flash_Emulator::chip_size()
|
||||
{
|
||||
return this->size;
|
||||
}
|
||||
size_t Flash_Emulator::sector_size()
|
||||
{
|
||||
return this->sector_sise;
|
||||
}
|
||||
|
||||
esp_err_t Flash_Emulator::erase_sector(size_t sector)
|
||||
{
|
||||
esp_err_t result = ESP_OK;
|
||||
if ((this->reset_count != 0x7fffffff) && (this->reset_count != 0)) {
|
||||
this->reset_count--;
|
||||
}
|
||||
if (this->reset_count <= 0) {
|
||||
result = ESP_FAIL;
|
||||
return result;
|
||||
}
|
||||
memset(&this->buff[sector * this->sector_sise], -1, this->sector_sise);
|
||||
this->access_count[sector]++;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t Flash_Emulator::get_access_minmax()
|
||||
{
|
||||
uint32_t min = INT32_MAX;
|
||||
uint32_t max = 0;
|
||||
for (size_t i = 0; i < (this->size / this->sector_sise) - 2; i++) {
|
||||
if (this->access_count[i] < min) {
|
||||
min = this->access_count[i];
|
||||
}
|
||||
if (this->access_count[i] > max) {
|
||||
max = this->access_count[i];
|
||||
}
|
||||
}
|
||||
return max - min;
|
||||
}
|
||||
|
||||
esp_err_t Flash_Emulator::erase_range(size_t start_address, size_t size)
|
||||
{
|
||||
esp_err_t result = ESP_OK;
|
||||
uint32_t start_sector = start_address / this->sector_sise;
|
||||
uint32_t count = (size + this->sector_sise - 1) / this->sector_sise;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
result |= this->erase_sector(start_sector + i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
esp_err_t Flash_Emulator::write(size_t dest_addr, const void *src, size_t size)
|
||||
{
|
||||
esp_err_t result = ESP_OK;
|
||||
if ((size % this->min_size) != 0) {
|
||||
result = ESP_ERR_INVALID_SIZE;
|
||||
return result;
|
||||
}
|
||||
if ((dest_addr % this->min_size) != 0) {
|
||||
result = ESP_ERR_INVALID_SIZE;
|
||||
return result;
|
||||
}
|
||||
if ((this->reset_count != 0x7fffffff) && (this->reset_count != 0)) {
|
||||
this->reset_count--;
|
||||
}
|
||||
if (this->reset_count <= 0) {
|
||||
result = ESP_FAIL;
|
||||
return result;
|
||||
}
|
||||
memcpy(&this->buff[dest_addr], src, size);
|
||||
return result;
|
||||
}
|
||||
|
||||
esp_err_t Flash_Emulator::read(size_t src_addr, void *dest, size_t size)
|
||||
{
|
||||
esp_err_t result = ESP_OK;
|
||||
if (this->reset_count <= 0) {
|
||||
result = ESP_FAIL;
|
||||
return result;
|
||||
}
|
||||
memcpy(dest, &this->buff[src_addr], size);
|
||||
return result;
|
||||
}
|
||||
|
||||
Flash_Emulator::~Flash_Emulator()
|
||||
{
|
||||
free(this->buff);
|
||||
delete this->access_count;
|
||||
}
|
||||
|
||||
void Flash_Emulator::SetResetCount(uint32_t count)
|
||||
{
|
||||
this->reset_count = count;
|
||||
}
|
||||
|
||||
void Flash_Emulator::SetResetSector(size_t sector)
|
||||
{
|
||||
this->reset_sector = sector;
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
// Copyright 2015-2017 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 _Flash_Emulator_H_
|
||||
#define _Flash_Emulator_H_
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "Flash_Access.h"
|
||||
/**
|
||||
* @brief This class is used to emulate flash devices. Class implements Flash_Access interface
|
||||
*
|
||||
*/
|
||||
class Flash_Emulator : public Flash_Access
|
||||
{
|
||||
|
||||
public:
|
||||
Flash_Emulator(size_t size, size_t sector_sise, size_t min_size);
|
||||
|
||||
virtual size_t chip_size();
|
||||
|
||||
virtual esp_err_t erase_sector(size_t sector);
|
||||
virtual esp_err_t erase_range(size_t start_address, size_t size);
|
||||
|
||||
virtual esp_err_t write(size_t dest_addr, const void *src, size_t size);
|
||||
virtual esp_err_t read(size_t src_addr, void *dest, size_t size);
|
||||
|
||||
virtual size_t sector_size();
|
||||
|
||||
virtual ~Flash_Emulator();
|
||||
|
||||
uint32_t get_access_minmax();
|
||||
public:
|
||||
size_t size;
|
||||
size_t sector_sise;
|
||||
size_t min_size;
|
||||
uint8_t *buff;
|
||||
|
||||
uint32_t *access_count;
|
||||
|
||||
public:
|
||||
uint32_t reset_count;
|
||||
size_t reset_sector;
|
||||
void SetResetCount(uint32_t count);
|
||||
void SetResetSector(size_t sector);
|
||||
|
||||
};
|
||||
|
||||
#endif // _Flash_Emulator_H_
|
@ -1,55 +1,85 @@
|
||||
TEST_PROGRAM=test_wl
|
||||
COMPONENT=wear_levelling
|
||||
|
||||
TEST_PROGRAM=test_$(COMPONENT)
|
||||
|
||||
# Expose as a library for FS components that require wear_levelling
|
||||
COMPONENT_LIB=lib$(COMPONENT).a
|
||||
|
||||
# Use simulated block device
|
||||
SPI_FLASH=spi_flash
|
||||
SPI_FLASH_DIR=../../$(SPI_FLASH)
|
||||
SPI_FLASH_SIM_DIR=$(SPI_FLASH_DIR)/sim
|
||||
SPI_FLASH_LIB=lib$(SPI_FLASH).a
|
||||
|
||||
all: $(TEST_PROGRAM)
|
||||
|
||||
SOURCE_FILES = \
|
||||
esp_error_check_stub.cpp \
|
||||
$(addprefix ../, \
|
||||
crc32.cpp \
|
||||
WL_Flash.cpp \
|
||||
../nvs_flash/test_nvs_host/crc.cpp\
|
||||
wear_levelling.cpp \
|
||||
crc32.cpp \
|
||||
WL_Flash.cpp \
|
||||
Partition.cpp \
|
||||
) \
|
||||
Flash_Emulator.cpp \
|
||||
wl_tests_host.cpp \
|
||||
TestPowerDown.cpp \
|
||||
esp_log_stub.cpp \
|
||||
main.cpp
|
||||
$(addprefix stubs/, \
|
||||
newlib/lock.c \
|
||||
log/log.c \
|
||||
esp32/crc.cpp \
|
||||
)
|
||||
|
||||
TEST_SOURCE_FILES = \
|
||||
test_wl.cpp \
|
||||
main.cpp \
|
||||
test_utils.c
|
||||
|
||||
INCLUDE_FLAGS = $(addprefix -I,\
|
||||
. \
|
||||
../ \
|
||||
../include \
|
||||
../private_include \
|
||||
$(addprefix stubs/, \
|
||||
newlib/include \
|
||||
log/include \
|
||||
) \
|
||||
$(SPI_FLASH_DIR)/include \
|
||||
../../esp32/include \
|
||||
../../soc/esp32/include \
|
||||
../../log/include \
|
||||
../../spi_flash/include \
|
||||
../../nvs_flash/test_nvs_host \
|
||||
../../../tools/catch \
|
||||
)
|
||||
)
|
||||
|
||||
GCOV ?= gcov
|
||||
|
||||
CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL
|
||||
CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL -g -m32
|
||||
CFLAGS += -fprofile-arcs -ftest-coverage
|
||||
CXXFLAGS += -std=c++11 -Wall -Werror -fprofile-arcs -ftest-coverage
|
||||
LDFLAGS += -lstdc++ -fprofile-arcs -ftest-coverage
|
||||
|
||||
OBJ_FILES = $(SOURCE_FILES:.cpp=.o)
|
||||
OBJ_FILES = $(filter %.o, $(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o))
|
||||
TEST_OBJ_FILES = $(filter %.o, $(TEST_SOURCE_FILES:.cpp=.o) $(TEST_SOURCE_FILES:.c=.o))
|
||||
|
||||
COVERAGE_FILES = $(OBJ_FILES:.o=.gc*)
|
||||
$(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB): force
|
||||
$(MAKE) -C $(SPI_FLASH_SIM_DIR) lib
|
||||
|
||||
$(OBJ_FILES): %.o: %.cpp
|
||||
$(COMPONENT_LIB): $(OBJ_FILES)
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
$(TEST_PROGRAM): $(OBJ_FILES)
|
||||
g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES)
|
||||
force:
|
||||
|
||||
$(OUTPUT_DIR):
|
||||
mkdir -p $(OUTPUT_DIR)
|
||||
lib: $(COMPONENT_LIB)
|
||||
|
||||
partition_table.bin: partition_table.csv
|
||||
python ../../../components/partition_table/gen_esp32part.py --verify $< $@
|
||||
|
||||
$(TEST_PROGRAM): lib $(TEST_OBJ_FILES) $(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB) partition_table.bin
|
||||
g++ $(LDFLAGS) -o $@ $(TEST_OBJ_FILES) -L$(abspath .) -l:$(COMPONENT_LIB) -L$(SPI_FLASH_SIM_DIR) -l:$(SPI_FLASH_LIB) -g -m32
|
||||
|
||||
test: $(TEST_PROGRAM)
|
||||
./$(TEST_PROGRAM)
|
||||
|
||||
$(COVERAGE_FILES): $(TEST_PROGRAM) test
|
||||
$(OUTPUT_DIR):
|
||||
mkdir -p $(OUTPUT_DIR)
|
||||
|
||||
COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(TEST_OBJ_FILES:.o=.gc*)
|
||||
|
||||
$(COVERAGE_FILES): test
|
||||
|
||||
coverage.info: $(COVERAGE_FILES)
|
||||
find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} +
|
||||
@ -60,9 +90,10 @@ coverage_report: coverage.info
|
||||
@echo "Coverage report is in coverage_report/index.html"
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ_FILES) $(TEST_PROGRAM)
|
||||
$(MAKE) -C $(SPI_FLASH_SIM_DIR) clean
|
||||
rm -f $(OBJ_FILES) $(TEST_OBJ_FILES) $(TEST_PROGRAM) $(COMPONENT_LIB) partition_table.bin
|
||||
rm -f $(COVERAGE_FILES) *.gcov
|
||||
rm -rf coverage_report/
|
||||
rm -f coverage.info
|
||||
|
||||
.PHONY: clean all test
|
||||
.PHONY: clean all test lib
|
||||
|
@ -1,110 +0,0 @@
|
||||
// Copyright 2015-2017 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 "WL_Config.h"
|
||||
#include "WL_Flash.h"
|
||||
#include "Flash_Emulator.h"
|
||||
#ifdef _MSC_VER
|
||||
#define CHECK(m)
|
||||
#else
|
||||
#include "catch.hpp"
|
||||
#endif
|
||||
|
||||
extern Flash_Access *s_flash;
|
||||
|
||||
bool test_power_down(WL_Flash *wl_flash, Flash_Emulator *emul, uint32_t used_sectors_count)
|
||||
{
|
||||
REQUIRE(wl_flash->init() == ESP_OK);
|
||||
s_flash = wl_flash;
|
||||
|
||||
uint32_t add_const = 0;
|
||||
int32_t sectors_count = s_flash->chip_size() / s_flash->sector_size();
|
||||
esp_err_t err = ESP_OK;
|
||||
uint32_t *sector_data = new uint32_t[s_flash->sector_size() / sizeof(uint32_t)];
|
||||
|
||||
for (int32_t i = 0; i < sectors_count; i++) {
|
||||
REQUIRE(s_flash->erase_sector(i) == ESP_OK);
|
||||
for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) {
|
||||
uint32_t temp_data = i * s_flash->sector_size() + add_const + m;
|
||||
sector_data[m] = temp_data;
|
||||
}
|
||||
REQUIRE(s_flash->write(i * s_flash->sector_size(), sector_data, s_flash->sector_size()) == ESP_OK);
|
||||
}
|
||||
for (int32_t i = 0; i < sectors_count; i++) {
|
||||
err |= s_flash->read(i * s_flash->sector_size(), sector_data, s_flash->sector_size());
|
||||
for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) {
|
||||
uint32_t temp_data = i * s_flash->sector_size() + add_const + m;
|
||||
REQUIRE(temp_data == sector_data[m]);
|
||||
if (temp_data != sector_data[m]) {
|
||||
printf("Error - read: %08x, expected %08x\n", sector_data[m], temp_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t max_count = 100;
|
||||
int32_t max_check_count = used_sectors_count;
|
||||
printf("used_sectors_count=%d\n", used_sectors_count);
|
||||
for (int32_t k = 0; k < max_check_count; k++) {
|
||||
|
||||
emul->SetResetCount(max_count);
|
||||
int32_t err_sector = -1;
|
||||
for (int32_t i = 0; i < sectors_count; i++) {
|
||||
err = ESP_OK;
|
||||
err = s_flash->erase_sector(i);
|
||||
if (err != ESP_OK) {
|
||||
err_sector = i;
|
||||
break;
|
||||
}
|
||||
for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) {
|
||||
uint32_t temp_data = i * s_flash->sector_size() + add_const + m;
|
||||
sector_data[m] = temp_data;
|
||||
}
|
||||
err = s_flash->write(i * s_flash->sector_size(), sector_data, s_flash->sector_size());
|
||||
if (err != ESP_OK) {
|
||||
err_sector = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (err_sector >= 0) {
|
||||
max_count++;
|
||||
} else {
|
||||
max_count = 0;
|
||||
}
|
||||
emul->SetResetCount(INT32_MAX);
|
||||
REQUIRE(wl_flash->init() == ESP_OK);
|
||||
for (int32_t i = 0; i < sectors_count; i++) {
|
||||
if (i != err_sector) {
|
||||
err |= s_flash->read(i * s_flash->sector_size(), sector_data, s_flash->sector_size());
|
||||
for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) {
|
||||
uint32_t temp_data = i * s_flash->sector_size() + add_const + m;
|
||||
REQUIRE(temp_data == sector_data[m]);
|
||||
if (temp_data != sector_data[m]) {
|
||||
printf("Error - read: %08x, expected %08x, m=%i, sector=%i\n", sector_data[m], temp_data, m, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (err_sector != -1) {
|
||||
err |= s_flash->erase_sector(err_sector);
|
||||
for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) {
|
||||
uint32_t temp_data = err_sector * s_flash->sector_size() + add_const + m;
|
||||
sector_data[m] = temp_data;
|
||||
}
|
||||
err |= s_flash->write(err_sector * s_flash->sector_size(), sector_data, s_flash->sector_size());
|
||||
}
|
||||
printf("[%3.f%%] err_sector=%i\n", (float)k / ((float)max_check_count) * 100.0f, err_sector);
|
||||
}
|
||||
delete[] sector_data;
|
||||
return true;
|
||||
}
|
@ -1,2 +1,2 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
#include "catch.hpp"
|
@ -0,0 +1,6 @@
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
|
||||
nvs, data, nvs, 0x9000, 0x6000,
|
||||
phy_init, data, phy, 0xf000, 0x1000,
|
||||
factory, app, factory, 0x10000, 1M,
|
||||
storage, data, fat, , 1M,
|
|
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#define CONFIG_WL_SECTOR_SIZE 4096
|
64
components/wear_levelling/test_wl_host/stubs/esp32/crc.cpp
Normal file
64
components/wear_levelling/test_wl_host/stubs/esp32/crc.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
// 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 <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
static const unsigned int crc32_le_table[256] = {
|
||||
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
|
||||
0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
|
||||
0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
|
||||
0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
|
||||
0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
|
||||
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
|
||||
0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
|
||||
0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
|
||||
0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
|
||||
0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
|
||||
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
|
||||
0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
|
||||
0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
|
||||
0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
|
||||
0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
|
||||
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
|
||||
|
||||
0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
|
||||
0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
|
||||
0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
|
||||
0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
|
||||
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
|
||||
0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
|
||||
0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
|
||||
0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
|
||||
0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
|
||||
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
|
||||
0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
|
||||
0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
|
||||
0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
|
||||
0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
|
||||
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
|
||||
0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
|
||||
};
|
||||
|
||||
|
||||
|
||||
extern "C" unsigned int crc32_le(unsigned int crc, unsigned char const * buf,unsigned int len)
|
||||
{
|
||||
unsigned int i;
|
||||
crc = ~crc;
|
||||
for(i=0;i<len;i++){
|
||||
crc = crc32_le_table[(crc^buf[i])&0xff]^(crc>>8);
|
||||
}
|
||||
return ~crc;
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
|
||||
typedef enum {
|
||||
ESP_LOG_NONE, /*!< No log output */
|
||||
ESP_LOG_ERROR, /*!< Critical errors, software module can not recover on its own */
|
||||
ESP_LOG_WARN, /*!< Error conditions from which recovery measures have been taken */
|
||||
ESP_LOG_INFO, /*!< Information messages which describe normal flow of events */
|
||||
ESP_LOG_DEBUG, /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */
|
||||
ESP_LOG_VERBOSE /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */
|
||||
} esp_log_level_t;
|
||||
|
||||
#define LOG_COLOR_E
|
||||
#define LOG_COLOR_W
|
||||
#define LOG_COLOR_I
|
||||
#define LOG_COLOR_D
|
||||
#define LOG_COLOR_V
|
||||
#define LOG_RESET_COLOR
|
||||
|
||||
uint32_t esp_log_timestamp(void);
|
||||
void esp_log_write(esp_log_level_t level, const char* tag, const char* format, ...) __attribute__ ((format (printf, 3, 4)));
|
||||
|
||||
#define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%d) %s: " format LOG_RESET_COLOR "\n"
|
||||
|
||||
#define ESP_LOGE( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_ERROR) { esp_log_write(ESP_LOG_ERROR, tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
|
||||
|
||||
#define ESP_LOGV( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_VERBOSE) { esp_log_write(ESP_LOG_VERBOSE, tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
|
||||
|
||||
#define ESP_LOGD( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { esp_log_write(ESP_LOG_DEBUG, tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
|
||||
|
||||
#define ESP_LOGW( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_WARN) { esp_log_write(ESP_LOG_WARN, tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
21
components/wear_levelling/test_wl_host/stubs/log/log.c
Normal file
21
components/wear_levelling/test_wl_host/stubs/log/log.c
Normal file
@ -0,0 +1,21 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
void esp_log_write(esp_log_level_t level,
|
||||
const char *tag,
|
||||
const char *format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
vprintf(format, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
|
||||
uint32_t esp_log_timestamp()
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int _lock_t;
|
||||
|
||||
void _lock_acquire(_lock_t *lock);
|
||||
void _lock_close(_lock_t *lock);
|
||||
void _lock_init(_lock_t *lock);
|
||||
void _lock_release(_lock_t *lock);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
21
components/wear_levelling/test_wl_host/stubs/newlib/lock.c
Normal file
21
components/wear_levelling/test_wl_host/stubs/newlib/lock.c
Normal file
@ -0,0 +1,21 @@
|
||||
#include "sys/lock.h"
|
||||
|
||||
void _lock_acquire(_lock_t *lock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void _lock_close(_lock_t *lock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void _lock_init(_lock_t *lock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void _lock_release(_lock_t *lock)
|
||||
{
|
||||
return;
|
||||
}
|
7
components/wear_levelling/test_wl_host/test_utils.c
Normal file
7
components/wear_levelling/test_wl_host/test_utils.c
Normal file
@ -0,0 +1,7 @@
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_partition.h"
|
||||
|
||||
void init_spi_flash(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin)
|
||||
{
|
||||
spi_flash_init(chip_size, block_size, sector_size, page_size, partition_bin);
|
||||
}
|
87
components/wear_levelling/test_wl_host/test_wl.cpp
Normal file
87
components/wear_levelling/test_wl_host/test_wl.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_partition.h"
|
||||
#include "wear_levelling.h"
|
||||
#include "WL_Flash.h"
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
extern "C" void init_spi_flash(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin);
|
||||
|
||||
TEST_CASE("write and read back data", "[wear_levelling]")
|
||||
{
|
||||
init_spi_flash(0x00400000, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partition_table.bin");
|
||||
|
||||
esp_err_t result;
|
||||
wl_handle_t wl_handle;
|
||||
|
||||
int flash_handle;
|
||||
const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, "storage");
|
||||
|
||||
// Mount wear-levelled partition
|
||||
result = wl_mount(partition, &wl_handle);
|
||||
REQUIRE(result == ESP_OK);
|
||||
|
||||
// Get the sector size
|
||||
uint32_t sector_size = wl_sector_size(wl_handle);
|
||||
REQUIRE(sector_size == CONFIG_WL_SECTOR_SIZE);
|
||||
|
||||
uint8_t* data = (uint8_t*) malloc(partition->size);
|
||||
uint8_t* read = (uint8_t*) malloc(partition->size);
|
||||
|
||||
uint32_t sectors = partition->size / sector_size;
|
||||
|
||||
// Generate data
|
||||
for(uint32_t sector = 0; sector < sectors; sector++)
|
||||
{
|
||||
uint32_t sector_address = sector * sector_size;
|
||||
|
||||
for(uint32_t i = 0; i < sector_size / sizeof(i); i++)
|
||||
{
|
||||
((uint32_t*) data)[i] = sector_address + i;
|
||||
}
|
||||
}
|
||||
|
||||
// Write data
|
||||
result = wl_write(wl_handle, 0, data, partition->size);
|
||||
REQUIRE(result == ESP_OK);
|
||||
|
||||
// Read data
|
||||
result = wl_read(wl_handle, 0, read, partition->size);
|
||||
REQUIRE(result == ESP_OK);
|
||||
|
||||
// Verify that written and read data match
|
||||
REQUIRE(memcmp(data, read, partition->size));
|
||||
|
||||
// Erase some ranges
|
||||
result = wl_erase_range(wl_handle, 0, sector_size);
|
||||
REQUIRE(result == ESP_OK);
|
||||
result = wl_erase_range(wl_handle, 12288, sector_size * 2);
|
||||
REQUIRE(result == ESP_OK);
|
||||
result = wl_erase_range(wl_handle, 28672, sector_size * 3);
|
||||
REQUIRE(result == ESP_OK);
|
||||
|
||||
// Expected data after erasure
|
||||
memset(data + 0, 0xFF, sector_size);
|
||||
memset(data + 12288, 0xFF, sector_size * 2);
|
||||
memset(data + 28672, 0xFF, sector_size * 3);
|
||||
|
||||
// Read again, with erased ranges
|
||||
result = wl_read(wl_handle, 0, read, partition->size);
|
||||
REQUIRE(result == ESP_OK);
|
||||
|
||||
// Verify that written and read data match
|
||||
REQUIRE(memcmp(data, read, partition->size));
|
||||
|
||||
// Unmount
|
||||
result = wl_unmount(wl_handle);
|
||||
REQUIRE(result == ESP_OK);
|
||||
|
||||
free(data);
|
||||
free(read);
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
// Copyright 2015-2017 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 <string.h>
|
||||
#include "WL_Config.h"
|
||||
#include "WL_Flash.h"
|
||||
#include "Flash_Emulator.h"
|
||||
#include "catch.hpp"
|
||||
|
||||
#define FLASH_SECTOR_SIZE 512
|
||||
#define FLASH_USED_SECTOR (1024 - 3)
|
||||
#define FLASH_ACCESS_SIZE (FLASH_SECTOR_SIZE*(FLASH_USED_SECTOR + 1 + 2))
|
||||
#define FLASH_START_ADDR 0x1000
|
||||
#define FLASH_PAGE_SIZE FLASH_SECTOR_SIZE*1
|
||||
#define FLASH_UPDATERATE 3
|
||||
#define FLASH_TEMP_SIZE FLASH_SECTOR_SIZE
|
||||
#define FLASH_WR_BLOCK_SIZE 16
|
||||
|
||||
static const char *TAG = "wl_test_host";
|
||||
Flash_Access *s_flash;
|
||||
|
||||
extern bool test_power_down(WL_Flash *wl_flash, Flash_Emulator *emul, uint32_t used_sectors_count);
|
||||
|
||||
#define TEST_COUNT_MAX 100
|
||||
|
||||
TEST_CASE("flash starts with all bytes == 0xff", "[spi_flash_emu]")
|
||||
{
|
||||
wl_config_t *wl = new wl_config_t();
|
||||
|
||||
wl->full_mem_size = FLASH_ACCESS_SIZE;
|
||||
wl->start_addr = FLASH_START_ADDR;
|
||||
wl->sector_size = FLASH_SECTOR_SIZE;
|
||||
wl->page_size = FLASH_PAGE_SIZE;
|
||||
wl->updaterate = FLASH_UPDATERATE;
|
||||
wl->temp_buff_size = FLASH_TEMP_SIZE;
|
||||
wl->wr_size = FLASH_WR_BLOCK_SIZE;
|
||||
|
||||
WL_Flash *wl_flash = new WL_Flash();
|
||||
Flash_Emulator *emul = new Flash_Emulator(FLASH_ACCESS_SIZE + FLASH_START_ADDR, FLASH_SECTOR_SIZE, FLASH_WR_BLOCK_SIZE);
|
||||
CHECK(wl_flash->config(wl, emul) == ESP_OK);
|
||||
|
||||
test_power_down(wl_flash, emul, TEST_COUNT_MAX);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user