diff --git a/common.mk b/common.mk index 172fbe2..f4bfe06 100644 --- a/common.mk +++ b/common.mk @@ -210,7 +210,8 @@ $(FW_FILE): $(PROGRAM_OUT) $(FIRMWARE_DIR) $(Q) $(ESPTOOL) elf2image --version=2 $(ESPTOOL_ARGS) $< -o $(FW_FILE) flash: $(FW_FILE) - $(ESPTOOL) -p $(ESPPORT) --baud $(ESPBAUD) write_flash $(ESPTOOL_ARGS) 0x0 $(RBOOT_BIN) 0x1000 $(RBOOT_CONF) 0x2000 $(FW_FILE) + $(ESPTOOL) -p $(ESPPORT) --baud $(ESPBAUD) write_flash $(ESPTOOL_ARGS) \ + 0x0 $(RBOOT_BIN) 0x1000 $(RBOOT_CONF) 0x2000 $(FW_FILE) $(SPIFFS_ESPTOOL_ARGS) erase_flash: $(ESPTOOL) -p $(ESPPORT) --baud $(ESPBAUD) erase_flash diff --git a/examples/spiffs/Makefile b/examples/spiffs/Makefile index b342df7..b0be23f 100644 --- a/examples/spiffs/Makefile +++ b/examples/spiffs/Makefile @@ -7,3 +7,5 @@ SPIFFS_BASE_ADDR = 0x200000 SPIFFS_SIZE = 0x100000 include ../../common.mk + +$(eval $(call make_spiffs_image,files)) diff --git a/examples/spiffs/files/test.txt b/examples/spiffs/files/test.txt new file mode 100644 index 0000000..c86fb0c --- /dev/null +++ b/examples/spiffs/files/test.txt @@ -0,0 +1 @@ +This file will go to SPIFFS image. diff --git a/extras/spiffs/component.mk b/extras/spiffs/component.mk index fcd5572..cf0a5a0 100644 --- a/extras/spiffs/component.mk +++ b/extras/spiffs/component.mk @@ -14,4 +14,37 @@ spiffs_CFLAGS = $(CFLAGS) spiffs_CFLAGS += -DSPIFFS_BASE_ADDR=$(SPIFFS_BASE_ADDR) spiffs_CFLAGS += -DSPIFFS_SIZE=$(SPIFFS_SIZE) + +# Create an SPIFFS image of specified directory and flash it with +# the rest of the firmware. +# +# Argumens: +# $(1) - directory with files which go into spiffs image +# +# Example: +# $(eval $(call make_spiffs_image,files)) +define make_spiffs_image +SPIFFS_IMAGE = $(addprefix $(FIRMWARE_DIR),spiffs.bin) +MKSPIFFS_DIR = $(ROOT)/extras/spiffs/mkspiffs +MKSPIFFS = $$(MKSPIFFS_DIR)/mkspiffs + +all: $$(SPIFFS_IMAGE) + +clean: clean_spiffs_img clean_mkspiffs + +$$(SPIFFS_IMAGE): $$(MKSPIFFS) $(1) + $$< $(1) $$@ + +$$(MKSPIFFS): + $$(MAKE) -C $$(MKSPIFFS_DIR) SPIFFS_SIZE=$(SPIFFS_SIZE) + +clean_spiffs_img: + $$(Q) rm -f spiffs.img + +clean_mkspiffs: + $$(Q) $$(MAKE) -C $$(MKSPIFFS_DIR) clean + +SPIFFS_ESPTOOL_ARGS = $(SPIFFS_BASE_ADDR) $$(SPIFFS_IMAGE) +endef + $(eval $(call component_compile_rules,spiffs)) diff --git a/extras/spiffs/mkspiffs/Makefile b/extras/spiffs/mkspiffs/Makefile new file mode 100644 index 0000000..7517456 --- /dev/null +++ b/extras/spiffs/mkspiffs/Makefile @@ -0,0 +1,37 @@ +# Check if SPIFFS_SIZE defined only if not cleaning +ifneq ($(MAKECMDGOALS),clean) +ifndef SPIFFS_SIZE +define ERROR_MSG +Variable SPIFFS_SIZE is not defined. +Cannot build mkspiffs without SPIFFS_SIZE. +Please specify it in your application Makefile. + +endef +$(error $(ERROR_MSG)) +endif +endif + +SOURCES := spiffs_hydrogen.c +SOURCES += spiffs_cache.c +SOURCES += spiffs_gc.c +SOURCES += spiffs_check.c +SOURCES += spiffs_nucleus.c +SOURCES += mkspiffs.c + +OBJECTS := $(SOURCES:.c=.o) + +VPATH = ../spiffs/src + +CFLAGS += -I.. +CFLAGS += -DSPIFFS_BASE_ADDR=0 # for image base addr is start of the image +CFLAGS += -DSPIFFS_SIZE=$(SPIFFS_SIZE) + +all: mkspiffs + +mkspiffs: $(OBJECTS) + +clean: + @rm -f mkspiffs + @rm -f *.o + +.PHONY: all clean diff --git a/extras/spiffs/mkspiffs/README.md b/extras/spiffs/mkspiffs/README.md new file mode 100644 index 0000000..5f6943d --- /dev/null +++ b/extras/spiffs/mkspiffs/README.md @@ -0,0 +1,34 @@ +# mkspiffs Create spiffs image + +mkspiffs is a command line utility to create an image of SPIFFS in order +to write to flash. + +## Usage + +mkspiffs will be built automatically if you include the following line in your +makefile: + +``` +$(eval $(call make_spiffs_image,files)) +``` + +where *files* is the directory with files that should go into SPIFFS image. + +Or you can build mkspiffs manually with: + +``` +make SPIFFS_SIZE=0x100000 +``` + +mkspiffs cannot be built without specifying SPIFFS size because it uses the +same SPIFFS sources as the firmware. And for the firmware SPIFFS size is +compile time defined. + +Please note that if you change SPIFFS_SIZE you need to rebuild mkspiffs. +The easiest way is to run `make clean` for you project. + +To manually generate SPIFFS image from directory, run: + +``` +mkspiffs DIRECTORY IMAGE_NAME +``` diff --git a/extras/spiffs/mkspiffs/mkspiffs.c b/extras/spiffs/mkspiffs/mkspiffs.c new file mode 100644 index 0000000..9f231a8 --- /dev/null +++ b/extras/spiffs/mkspiffs/mkspiffs.c @@ -0,0 +1,243 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 sheinz (https://github.com/sheinz) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "spiffs_config.h" +#include "../spiffs/src/spiffs.h" + +static spiffs fs; +static void *image = 0; +static void *work_buf = 0; +static void *fds_buf = 0; +static void *cache_buf = 0; + +static void print_usage(const char *prog_name, const char *error_msg) +{ + if (error_msg) { + printf("Error: %s\n", error_msg); + } + printf("Usage: "); + printf("\t%s DIRECTORY IMAGE_NAME\n\n", prog_name); + printf("Example:\n"); + printf("\t%s ./my_files spiffs.img\n\n", prog_name); +} + +static s32_t _read_data(u32_t addr, u32_t size, u8_t *dst) +{ + memcpy(dst, (uint8_t*)image + addr, size); + return SPIFFS_OK; +} + +static s32_t _write_data(u32_t addr, u32_t size, u8_t *src) +{ + memcpy((uint8_t*)image + addr, src, size); + return SPIFFS_OK; +} + +static s32_t _erase_data(u32_t addr, u32_t size) +{ + memset((uint8_t*)image + addr, 0xFF, size); + return SPIFFS_OK; +} + +static bool init_spiffs(bool allocate_mem) +{ + spiffs_config config = {0}; + printf("Initializing SPIFFS, size=%d\n", SPIFFS_SIZE); + + config.hal_read_f = _read_data; + config.hal_write_f = _write_data; + config.hal_erase_f = _erase_data; + + int workBufSize = 2 * SPIFFS_CFG_LOG_PAGE_SZ(); + int fdsBufSize = SPIFFS_buffer_bytes_for_filedescs(&fs, 5); + int cacheBufSize = SPIFFS_buffer_bytes_for_cache(&fs, 5); + + if (allocate_mem) { + image = malloc(SPIFFS_SIZE); + work_buf = malloc(workBufSize); + fds_buf = malloc(fdsBufSize); + cache_buf = malloc(cacheBufSize); + printf("spiffs memory, work_buf_size=%d, fds_buf_size=%d, cache_buf_size=%d\n", + workBufSize, fdsBufSize, cacheBufSize); + } + + int32_t err = SPIFFS_mount(&fs, &config, work_buf, fds_buf, fdsBufSize, + cache_buf, cacheBufSize, 0); + + if (err != SPIFFS_OK) { + printf("Error spiffs mount: %d\n", err); + return false; + } + + return true; +} + +static bool format_spiffs() +{ + SPIFFS_unmount(&fs); + + if (SPIFFS_format(&fs) == SPIFFS_OK) { + printf("Format complete\n"); + } else { + printf("Failed to format SPIFFS\n"); + return false; + } + + if (!init_spiffs(false)) { + printf("Failed to mount SPIFFS\n"); + return false; + } + return true; +} + +static void spiffs_free() +{ + free(image); + image = NULL; + + free(work_buf); + work_buf = NULL; + + free(fds_buf); + fds_buf = NULL; + + free(cache_buf); + cache_buf = NULL; +} + +static bool process_file(const char *src_file, const char *dst_file) +{ + int fd; + const int buf_size = 256; + uint8_t buf[buf_size]; + int data_len; + + fd = open(src_file, O_RDONLY); + if (fd < 0) { + printf("Error openning file: %s\n", src_file); + } + + spiffs_file out_fd = SPIFFS_open(&fs, dst_file, + SPIFFS_O_CREAT | SPIFFS_O_WRONLY, 0); + while ((data_len = read(fd, buf, buf_size)) != 0) { + if (SPIFFS_write(&fs, out_fd, buf, data_len) != data_len) { + printf("Error writing to SPIFFS file\n"); + break; + } + } + SPIFFS_close(&fs, out_fd); + close(fd); + return true; +} + +static bool process_directory(const char *direcotry) +{ + DIR *dp; + struct dirent *ep; + char path[256]; + + dp = opendir(direcotry); + if (dp != NULL) { + while ((ep = readdir(dp)) != 0) { + if (!strcmp(ep->d_name, ".") || + !strcmp(ep->d_name, "..")) { + continue; + } + if (ep->d_type != DT_REG) { + continue; // not a regular file + } + sprintf(path, "%s/%s", direcotry, ep->d_name); + printf("Processing file %s\n", path); + if (!process_file(path, ep->d_name)) { + printf("Error processing file\n"); + break; + } + } + closedir(dp); + } else { + printf("Error reading direcotry: %s\n", direcotry); + } + return true; +} + +static bool write_image(const char *out_file) +{ + int fd; + int size = SPIFFS_SIZE; + uint8_t *p = (uint8_t*)image; + fd = open(out_file, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd < 0) { + printf("Error creating file %s\n", out_file); + return false; + } + + printf("Writing image to file: %s\n", out_file); + + while (size != 0) { + write(fd, p, SPIFFS_CFG_LOG_PAGE_SZ()); + p += SPIFFS_CFG_LOG_PAGE_SZ(); + size -= SPIFFS_CFG_LOG_PAGE_SZ(); + } + + close(fd); + return true; +} + +int main(int argc, char *argv[]) +{ + int result = 0; + + if (argc != 3) { + print_usage(argv[0], NULL); + return -1; + } + + if (init_spiffs(/*allocate_mem=*/true)) { + if (format_spiffs()) { + if (process_directory(argv[1])) { + if (!write_image(argv[2])) { + printf("Error writing image\n"); + } + } else { + printf("Error processing direcotry\n"); + } + } else { + printf("Error formating spiffs\n"); + } + } else { + printf("Error initialising SPIFFS\n"); + } + + spiffs_free(); + return result; +}