Skip to content

Commit 6f01212

Browse files
committed
Merge pull request #294 from ficeto/esp8266
Esp8266 SPIFFS Tool
2 parents 01b3457 + fd7c5d5 commit 6f01212

14 files changed

+288
-22
lines changed

build/shared/tools/ESP8266FS/make.sh

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/sh
2+
ALIBDIR="/Users/ficeto/Documents/Arduino"
3+
mkdir -p bin && \
4+
javac -target 1.8 -cp "../../arduino-core.jar:../../pde.jar" -d bin src/ESP8266FS.java && \
5+
cd bin && \
6+
mkdir -p $ALIBDIR/tools && \
7+
rm -rf $ALIBDIR/tools/ESP8266FS && \
8+
mkdir -p $ALIBDIR/tools/ESP8266FS/tool && \
9+
zip -r $ALIBDIR/tools/ESP8266FS/tool/esp8266fs.jar * && \
10+
cd ..
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2+
3+
/*
4+
Tool to put the contents of the sketch's "data" subfolder
5+
into an SPIFFS partition image and upload it to an ESP8266 MCU
6+
7+
Copyright (c) 2015 Hristo Gochkov (ficeto at ficeto dot com)
8+
9+
This program is free software; you can redistribute it and/or modify
10+
it under the terms of the GNU General Public License as published by
11+
the Free Software Foundation; either version 2 of the License, or
12+
(at your option) any later version.
13+
14+
This program is distributed in the hope that it will be useful,
15+
but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
GNU General Public License for more details.
18+
19+
You should have received a copy of the GNU General Public License
20+
along with this program; if not, write to the Free Software Foundation,
21+
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22+
*/
23+
24+
package com.esp8266.mkspiffs;
25+
26+
import java.io.File;
27+
import java.io.BufferedReader;
28+
import java.io.InputStreamReader;
29+
30+
import java.text.SimpleDateFormat;
31+
import java.util.Date;
32+
33+
import javax.swing.JOptionPane;
34+
35+
import processing.app.PreferencesData;
36+
import processing.app.Editor;
37+
import processing.app.Base;
38+
import processing.app.Platform;
39+
import processing.app.Sketch;
40+
import processing.app.tools.Tool;
41+
import processing.app.helpers.ProcessUtils;
42+
import processing.app.debug.TargetPlatform;
43+
44+
45+
/**
46+
* Example Tools menu entry.
47+
*/
48+
public class ESP8266FS implements Tool {
49+
Editor editor;
50+
51+
52+
public void init(Editor editor) {
53+
this.editor = editor;
54+
}
55+
56+
57+
public String getMenuTitle() {
58+
return "ESP8266 Sketch Data Upload";
59+
}
60+
61+
private int listenOnProcess(String[] arguments){
62+
try {
63+
final Process p = ProcessUtils.exec(arguments);
64+
Thread thread = new Thread() {
65+
public void run() {
66+
try {
67+
String line;
68+
BufferedReader input = new BufferedReader (new InputStreamReader(p.getInputStream()));
69+
while ((line = input.readLine()) != null) System.out.println(line);
70+
input.close();
71+
} catch (Exception e){}
72+
}
73+
};
74+
thread.start();
75+
int res = p.waitFor();
76+
thread.join();
77+
return res;
78+
} catch (Exception e){
79+
return -1;
80+
}
81+
}
82+
83+
private void sysExec(final String[] arguments){
84+
Thread thread = new Thread() {
85+
public void run() {
86+
try {
87+
if(listenOnProcess(arguments) != 0){
88+
editor.statusError("SPIFFS Upload failed!");
89+
} else {
90+
editor.statusNotice("SPIFFS Image Uploaded");
91+
}
92+
} catch (Exception e){
93+
editor.statusError("SPIFFS Upload failed!");
94+
}
95+
}
96+
};
97+
thread.start();
98+
}
99+
100+
101+
private long getIntPref(String name){
102+
String data = Base.getBoardPreferences().get(name);
103+
if(data == null || data.contentEquals("")) return 0;
104+
if(data.startsWith("0x")) return Long.parseLong(data.substring(2), 16);
105+
else return Integer.parseInt(data);
106+
}
107+
108+
private void createAndUpload(){
109+
if(!PreferencesData.get("target_platform").contentEquals("esp8266")){
110+
System.err.println();
111+
editor.statusError("SPIFFS Not Supported on "+PreferencesData.get("target_platform"));
112+
return;
113+
}
114+
115+
if(!Base.getBoardPreferences().containsKey("build.spiffs_start") || !Base.getBoardPreferences().containsKey("build.spiffs_end")){
116+
System.err.println();
117+
editor.statusError("SPIFFS Not Defined for "+Base.getBoardPreferences().get("name"));
118+
return;
119+
}
120+
long spiStart, spiEnd, spiPage, spiBlock;
121+
try {
122+
spiStart = getIntPref("build.spiffs_start");
123+
spiEnd = getIntPref("build.spiffs_end");
124+
spiPage = getIntPref("build.spiffs_pagesize");
125+
if(spiPage == 0) spiPage = 256;
126+
spiBlock = getIntPref("build.spiffs_blocksize");
127+
if(spiBlock == 0) spiBlock = 4096;
128+
} catch(Exception e){
129+
editor.statusError(e);
130+
return;
131+
}
132+
133+
TargetPlatform platform = Base.getTargetPlatform();
134+
135+
File esptool;
136+
if(!PreferencesData.get("runtime.os").contentEquals("windows")) esptool = new File(platform.getFolder()+"/tools", "esptool");
137+
else esptool = new File(platform.getFolder()+"/tools", "esptool.exe");
138+
if(!esptool.exists()){
139+
System.err.println();
140+
editor.statusError("SPIFFS Error: esptool not found!");
141+
return;
142+
}
143+
144+
File tool;
145+
if(!PreferencesData.get("runtime.os").contentEquals("windows")) tool = new File(platform.getFolder()+"/tools", "mkspiffs");
146+
else tool = new File(platform.getFolder()+"/tools", "mkspiffs.exe");
147+
if(!tool.exists()){
148+
System.err.println();
149+
editor.statusError("SPIFFS Error: mkspiffs not found!");
150+
return;
151+
}
152+
153+
int fileCount = 0;
154+
File dataFolder = editor.getSketch().prepareDataFolder();
155+
if(dataFolder.exists() && dataFolder.isDirectory()){
156+
File[] files = dataFolder.listFiles();
157+
if(files.length > 0){
158+
for(File file : files){
159+
if(!file.isDirectory() && file.isFile() && !file.getName().startsWith(".")) fileCount++;
160+
}
161+
}
162+
}
163+
164+
String dataPath = dataFolder.getAbsolutePath();
165+
String toolPath = tool.getAbsolutePath();
166+
String esptoolPath = esptool.getAbsolutePath();
167+
String sketchName = editor.getSketch().getName();
168+
String buildPath = Base.getBuildFolder().getAbsolutePath();
169+
String imagePath = buildPath+"/"+sketchName+".spiffs.bin";
170+
String serialPort = PreferencesData.get("serial.port");
171+
String resetMethod = Base.getBoardPreferences().get("upload.resetmethod");
172+
String uploadSpeed = Base.getBoardPreferences().get("upload.speed");
173+
String uploadAddress = Base.getBoardPreferences().get("build.spiffs_start");
174+
175+
Object[] options = { "Yes", "No" };
176+
String title = "SPIFFS Create";
177+
String message = "No files have been found in your data folder!\nAre you sure you want to create an empty SPIFFS image?";
178+
179+
if(fileCount == 0 && JOptionPane.showOptionDialog(editor, message, title, JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[1]) != JOptionPane.YES_OPTION){
180+
System.err.println();
181+
editor.statusError("SPIFFS Warning: mkspiffs canceled!");
182+
return;
183+
}
184+
185+
editor.statusNotice("SPIFFS Creating Image...");
186+
System.out.println("[SPIFFS] data : "+dataPath);
187+
System.out.println("[SPIFFS] size : "+((spiEnd - spiStart)/1024));
188+
System.out.println("[SPIFFS] page : "+spiPage);
189+
System.out.println("[SPIFFS] block : "+spiBlock);
190+
191+
try {
192+
if(listenOnProcess(new String[]{toolPath, "-c", dataPath, "-p", spiPage+"", "-b", spiBlock+"", "-s", (spiEnd - spiStart)+"", imagePath}) != 0){
193+
System.err.println();
194+
editor.statusError("SPIFFS Create Failed!");
195+
return;
196+
}
197+
} catch (Exception e){
198+
editor.statusError(e);
199+
editor.statusError("SPIFFS Create Failed!");
200+
return;
201+
}
202+
203+
editor.statusNotice("SPIFFS Uploading Image...");
204+
System.out.println("[SPIFFS] upload : "+imagePath);
205+
System.out.println("[SPIFFS] reset : "+resetMethod);
206+
System.out.println("[SPIFFS] port : "+serialPort);
207+
System.out.println("[SPIFFS] speed : "+uploadSpeed);
208+
System.out.println("[SPIFFS] address: "+uploadAddress);
209+
System.out.println();
210+
211+
sysExec(new String[]{esptoolPath, "-cd", resetMethod, "-cb", uploadSpeed, "-cp", serialPort, "-ca", uploadAddress, "-cf", imagePath});
212+
}
213+
214+
public void run() {
215+
createAndUpload();
216+
}
217+
}

hardware/esp8266com/esp8266/boards.txt

+27-10
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ generic.build.flash_freq=40
2525
generic.build.flash_ld=eagle.flash.512k.ld
2626
generic.build.spiffs_start=0x6B000
2727
generic.build.spiffs_end=0x7B000
28+
generic.build.spiffs_pagesize=256
29+
generic.build.spiffs_blocksize=4096
2830

2931
generic.menu.CpuFrequency.80=80 MHz
3032
generic.menu.CpuFrequency.80.build.f_cpu=80000000L
@@ -55,46 +57,57 @@ generic.menu.FlashSize.512K.build.flash_size=512K
5557
generic.menu.FlashSize.512K.build.flash_ld=eagle.flash.512k.ld
5658
generic.menu.FlashSize.512K.build.spiffs_start=0x6B000
5759
generic.menu.FlashSize.512K.build.spiffs_end=0x7B000
60+
generic.menu.FlashSize.512K.build.spiffs_blocksize=4096
5861
generic.menu.FlashSize.1M512=1M (512K SPIFFS)
5962
generic.menu.FlashSize.1M512.build.flash_size=1M
6063
generic.menu.FlashSize.1M512.build.flash_ld=eagle.flash.1m512.ld
6164
generic.menu.FlashSize.1M512.build.spiffs_start=0x6B000
6265
generic.menu.FlashSize.1M512.build.spiffs_end=0xFB000
66+
generic.menu.FlashSize.1M512.build.spiffs_blocksize=8192
6367
generic.menu.FlashSize.1M256=1M (256K SPIFFS)
6468
generic.menu.FlashSize.1M256.build.flash_size=1M
6569
generic.menu.FlashSize.1M256.build.flash_ld=eagle.flash.1m256.ld
6670
generic.menu.FlashSize.1M256.build.spiffs_start=0xAB000
6771
generic.menu.FlashSize.1M256.build.spiffs_end=0xFB000
72+
generic.menu.FlashSize.1M256.build.spiffs_blocksize=4096
6873
generic.menu.FlashSize.1M128=1M (128K SPIFFS)
6974
generic.menu.FlashSize.1M128.build.flash_size=1M
7075
generic.menu.FlashSize.1M128.build.flash_ld=eagle.flash.1m128.ld
7176
generic.menu.FlashSize.1M128.build.spiffs_start=0xCB000
7277
generic.menu.FlashSize.1M128.build.spiffs_end=0xFB000
78+
generic.menu.FlashSize.1M128.build.spiffs_blocksize=4096
7379
generic.menu.FlashSize.1M64=1M (64K SPIFFS)
7480
generic.menu.FlashSize.1M64.build.flash_size=1M
7581
generic.menu.FlashSize.1M64.build.flash_ld=eagle.flash.1m64.ld
7682
generic.menu.FlashSize.1M64.build.spiffs_start=0xEB000
7783
generic.menu.FlashSize.1M64.build.spiffs_end=0xFB000
84+
generic.menu.FlashSize.1M64.build.spiffs_blocksize=4096
7885
generic.menu.FlashSize.2M=2M (1M SPIFFS)
7986
generic.menu.FlashSize.2M.build.flash_size=2M
8087
generic.menu.FlashSize.2M.build.flash_ld=eagle.flash.2m.ld
8188
generic.menu.FlashSize.2M.build.spiffs_start=0x100000
8289
generic.menu.FlashSize.2M.build.spiffs_end=0x1FB000
90+
generic.menu.FlashSize.2M.build.spiffs_blocksize=8192
8391
generic.menu.FlashSize.4M=4M (3M SPIFFS)
8492
generic.menu.FlashSize.4M.build.flash_size=4M
8593
generic.menu.FlashSize.4M.build.flash_ld=eagle.flash.4m.ld
8694
generic.menu.FlashSize.4M.build.spiffs_start=0x100000
8795
generic.menu.FlashSize.4M.build.spiffs_end=0x3FB000
88-
generic.menu.FlashSize.8M=8M (7M SPIFFS)
89-
generic.menu.FlashSize.8M.build.flash_size=1M
90-
generic.menu.FlashSize.8M.build.flash_ld=eagle.flash.8m.ld
91-
generic.menu.FlashSize.8M.build.spiffs_start=0x100000
92-
generic.menu.FlashSize.8M.build.spiffs_end=0x800000
93-
generic.menu.FlashSize.16M=16M (15M SPIFFS)
94-
generic.menu.FlashSize.16M.build.flash_size=1M
95-
generic.menu.FlashSize.16M.build.flash_ld=eagle.flash.16m.ld
96-
generic.menu.FlashSize.16M.build.spiffs_start=0x100000
97-
generic.menu.FlashSize.16M.build.spiffs_end=0x1000000
96+
generic.menu.FlashSize.4M.build.spiffs_blocksize=8192
97+
98+
# disabled because espressif's bootloader refuses to write above 4M
99+
# generic.menu.FlashSize.8M=8M (7M SPIFFS)
100+
# generic.menu.FlashSize.8M.build.flash_size=1M
101+
# generic.menu.FlashSize.8M.build.flash_ld=eagle.flash.8m.ld
102+
# generic.menu.FlashSize.8M.build.spiffs_start=0x100000
103+
# generic.menu.FlashSize.8M.build.spiffs_end=0x800000
104+
# generic.menu.FlashSize.8M.build.spiffs_blocksize=8192
105+
# generic.menu.FlashSize.16M=16M (15M SPIFFS)
106+
# generic.menu.FlashSize.16M.build.flash_size=1M
107+
# generic.menu.FlashSize.16M.build.flash_ld=eagle.flash.16m.ld
108+
# generic.menu.FlashSize.16M.build.spiffs_start=0x100000
109+
# generic.menu.FlashSize.16M.build.spiffs_end=0x1000000
110+
# generic.menu.FlashSize.16M.build.spiffs_blocksize=8192
98111

99112
# generic.menu.FlashFreq.40=40MHz
100113
# generic.menu.FlashFreq.40.build.flash_freq=40
@@ -124,6 +137,8 @@ modwifi.build.flash_freq=40
124137
modwifi.build.flash_ld=eagle.flash.2m.ld
125138
modwifi.build.spiffs_start=0x100000
126139
modwifi.build.spiffs_end=0x1FB000
140+
modwifi.build.spiffs_pagesize=256
141+
modwifi.build.spiffs_blocksize=8192
127142

128143
modwifi.menu.CpuFrequency.80=80 MHz
129144
modwifi.menu.CpuFrequency.80.build.f_cpu=80000000L
@@ -172,6 +187,8 @@ nodemcu.build.flash_freq=40
172187
nodemcu.build.flash_ld=eagle.flash.4m.ld
173188
nodemcu.build.spiffs_start=0x100000
174189
nodemcu.build.spiffs_end=0x3FB000
190+
nodemcu.build.spiffs_pagesize=256
191+
nodemcu.build.spiffs_blocksize=8192
175192

176193
nodemcu.menu.CpuFrequency.80=80 MHz
177194
nodemcu.menu.CpuFrequency.80.build.f_cpu=80000000L

hardware/esp8266com/esp8266/cores/esp8266/FileSystem.cpp

+13-11
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,25 @@
2222
#include "Arduino.h"
2323
#include "spiffs/spiffs_esp8266.h"
2424

25-
#define LOGICAL_PAGE_SIZE 256
26-
#define LOGICAL_BLOCK_SIZE (INTERNAL_FLASH_SECTOR_SIZE * 1)
27-
28-
29-
// These addresses are defined in the linker script.
25+
// These addresses and sizes are defined in the linker script.
3026
// For each flash memory size there is a linker script variant
3127
// which sets spiffs location and size.
3228
extern "C" uint32_t _SPIFFS_start;
3329
extern "C" uint32_t _SPIFFS_end;
30+
extern "C" uint32_t _SPIFFS_page;
31+
extern "C" uint32_t _SPIFFS_block;
3432

3533
static s32_t api_spiffs_read(u32_t addr, u32_t size, u8_t *dst);
3634
static s32_t api_spiffs_write(u32_t addr, u32_t size, u8_t *src);
3735
static s32_t api_spiffs_erase(u32_t addr, u32_t size);
3836

39-
FSClass FS((uint32_t) &_SPIFFS_start, (uint32_t) &_SPIFFS_end, 4);
37+
FSClass FS((uint32_t) &_SPIFFS_start, (uint32_t) &_SPIFFS_end, (uint32_t) &_SPIFFS_page, (uint32_t) &_SPIFFS_block, 4);
4038

41-
FSClass::FSClass(uint32_t beginAddress, uint32_t endAddress, uint32_t maxOpenFiles)
39+
FSClass::FSClass(uint32_t beginAddress, uint32_t endAddress, uint32_t pageSize, uint32_t blockSize, uint32_t maxOpenFiles)
4240
: _beginAddress(beginAddress)
4341
, _endAddress(endAddress)
42+
, _pageSize(pageSize)
43+
, _blockSize(blockSize)
4444
, _maxOpenFiles(maxOpenFiles)
4545
, _fs({0})
4646
{
@@ -51,23 +51,25 @@ int FSClass::_mountInternal(){
5151
SPIFFS_API_DBG_E("Can't start file system, wrong address\r\n");
5252
return SPIFFS_ERR_NOT_CONFIGURED;
5353
}
54+
if(_pageSize == 0) _pageSize = 256;
55+
if(_blockSize == 0) _blockSize = 4096;
5456

5557
spiffs_config cfg = {0};
5658
cfg.phys_addr = _beginAddress;
5759
cfg.phys_size = _endAddress - _beginAddress;
5860
cfg.phys_erase_block = INTERNAL_FLASH_SECTOR_SIZE;
59-
cfg.log_block_size = LOGICAL_BLOCK_SIZE;
60-
cfg.log_page_size = LOGICAL_PAGE_SIZE;
61+
cfg.log_block_size = _blockSize;
62+
cfg.log_page_size = _pageSize;
6163
cfg.hal_read_f = api_spiffs_read;
6264
cfg.hal_write_f = api_spiffs_write;
6365
cfg.hal_erase_f = api_spiffs_erase;
6466

6567
SPIFFS_API_DBG_V("FSClass::_mountInternal: start:%x, size:%d Kb\n", cfg.phys_addr, cfg.phys_size / 1024);
6668

67-
_work.reset(new uint8_t[2*LOGICAL_PAGE_SIZE]);
69+
_work.reset(new uint8_t[2*_pageSize]);
6870
_fdsSize = 32 * _maxOpenFiles;
6971
_fds.reset(new uint8_t[_fdsSize]);
70-
_cacheSize = (32 + LOGICAL_PAGE_SIZE) * _maxOpenFiles;
72+
_cacheSize = (32 + _pageSize) * _maxOpenFiles;
7173
_cache.reset(new uint8_t[_cacheSize]);
7274

7375
s32_t res = SPIFFS_mount(&_fs,

0 commit comments

Comments
 (0)