Skip to content

Commit 12a39b4

Browse files
John Doeigrr
authored andcommitted
Fixes and HTTP Post update example
Because eboot first erases the space required for the new sketch, and if the new sketch is larger then the old one, with the old way, part of the beginning of new sketch will be deleted. Therefore for now I opted to keep the max update size either half the available space for sketches or what's left from the first one, whichever is smaller. To be able to create a simple post mechanism for updates, I needed to have a way to write the new binary, without knowing it's final size, so I added an option to the end() method. Example in the WebServer examples.
1 parent 840c355 commit 12a39b4

File tree

4 files changed

+98
-13
lines changed

4 files changed

+98
-13
lines changed

hardware/esp8266com/esp8266/cores/esp8266/Esp.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ uint32_t EspClass::getFreeSketchSpace() {
350350
uint32_t usedSize = getSketchSize();
351351
// round one sector up
352352
uint32_t freeSpaceStart = (usedSize + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
353-
uint32_t freeSpaceEnd = (uint32_t)&_SPIFFS_start - 0x40200000;
353+
uint32_t freeSpaceEnd = (uint32_t)&_SPIFFS_start - 0x40200000 - (5 * FLASH_SECTOR_SIZE);
354354

355355
#ifdef DEBUG_SERIAL
356356
DEBUG_SERIAL.printf("usedSize=%u freeSpaceStart=%u freeSpaceEnd=%u\r\n", usedSize, freeSpaceStart, freeSpaceEnd);

hardware/esp8266com/esp8266/cores/esp8266/Updater.cpp

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,14 @@ bool UpdaterClass::begin(size_t size){
3535
_error = 0;
3636

3737
uint32_t usedSize = ESP.getSketchSize();
38-
uint32_t freeSpaceStart = (usedSize + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
39-
uint32_t freeSpaceEnd = (uint32_t)&_SPIFFS_start - 0x40200000;
38+
uint32_t freeSpaceEnd = (uint32_t)&_SPIFFS_start - 0x40200000 - (5 * FLASH_SECTOR_SIZE);
4039
uint32_t roundedSize = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
40+
uint32_t freeSpaceStart = freeSpaceEnd - roundedSize;
4141

42-
if(roundedSize > (freeSpaceEnd - freeSpaceStart)){
42+
//new sketch can not be more then half the size or more than the free space
43+
//this means that max sketch size is (1MB - 20KB) / 2 for flash 2MB and above
44+
//and the current sketch should not be more than that either
45+
if(freeSpaceStart < usedSize || roundedSize > (freeSpaceEnd/2)){
4346
_error = UPDATE_ERROR_SPACE;
4447
#ifdef DEBUG_UPDATER
4548
printError(DEBUG_UPDATER);
@@ -64,35 +67,47 @@ bool UpdaterClass::begin(size_t size){
6467
return true;
6568
}
6669

67-
bool UpdaterClass::end(){
70+
bool UpdaterClass::end(bool evenIfRemaining){
6871
if(_size == 0){
6972
#ifdef DEBUG_UPDATER
7073
DEBUG_UPDATER.println("no update");
7174
#endif
7275
return false;
7376
}
7477

75-
if(_buffer) os_free(_buffer);
76-
_bufferLen = 0;
77-
78-
if(hasError() || !isFinished()){
78+
if(hasError() || (!isFinished() && !evenIfRemaining)){
7979
#ifdef DEBUG_UPDATER
8080
DEBUG_UPDATER.printf("premature end: res:%u, pos:%u/%u\n", getError(), progress(), _size);
8181
#endif
82+
if(_buffer) os_free(_buffer);
83+
_bufferLen = 0;
8284
_currentAddress = 0;
8385
_startAddress = 0;
8486
_size = 0;
8587
return false;
8688
}
8789

90+
if(evenIfRemaining){
91+
if(_bufferLen > 0){
92+
_writeBuffer();
93+
}
94+
_size = progress();
95+
}
96+
if(_buffer) os_free(_buffer);
97+
_bufferLen = 0;
98+
_currentAddress = 0;
99+
88100
eboot_command ebcmd;
89101
ebcmd.action = ACTION_COPY_RAW;
90102
ebcmd.args[0] = _startAddress;
91103
ebcmd.args[1] = 0x00000;
92104
ebcmd.args[2] = _size;
93105
eboot_command_write(&ebcmd);
94-
95-
_currentAddress = 0;
106+
107+
#ifdef DEBUG_UPDATER
108+
DEBUG_UPDATER.printf("Staged: address:0x%08X, size:0x%08X\n", _startAddress, _size);
109+
#endif
110+
96111
_startAddress = 0;
97112
_size = 0;
98113
_error = UPDATE_ERROR_OK;

hardware/esp8266com/esp8266/cores/esp8266/Updater.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ class UpdaterClass {
4040
If all bytes are written
4141
this call will write the config to eboot
4242
and return true
43-
If there is already an update running but is not finished
43+
If there is already an update running but is not finished and !evenIfRemainanig
4444
or there is an error
4545
this will clear everything and return false
4646
the last error is available through getError()
4747
*/
48-
bool end();
48+
bool end(bool evenIfRemaining = false);
4949

5050
/*
5151
Prints the last error to an output stream
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#include <ESP8266WiFi.h>
2+
#include <WiFiClient.h>
3+
#include <ESP8266WebServer.h>
4+
#include <ESP8266mDNS.h>
5+
6+
const char* host = "esp8266-webupdate";
7+
const char* ssid = "........";
8+
const char* password = "........";
9+
10+
ESP8266WebServer server(80);
11+
const char* serverIndex = "<form method='POST' action='/update' enctype='multipart/form-data'><input type='file' name='update'><input type='submit' value='Update'></form>";
12+
13+
void setup(void){
14+
Serial.begin(115200);
15+
Serial.println();
16+
Serial.println("Booting Sketch...");
17+
WiFi.mode(WIFI_AP_STA);
18+
WiFi.begin(ssid, password);
19+
if(WiFi.waitForConnectResult() == WL_CONNECTED){
20+
MDNS.begin(host);
21+
server.on("/", HTTP_GET, [](){
22+
server.sendHeader("Connection", "close");
23+
server.sendHeader("Access-Control-Allow-Origin", "*");
24+
server.send(200, "text/html", serverIndex);
25+
});
26+
server.onFileUpload([](){
27+
if(server.uri() != "/update") return;
28+
HTTPUpload& upload = server.upload();
29+
if(upload.status == UPLOAD_FILE_START){
30+
Serial.setDebugOutput(true);
31+
Serial.printf("Update: %s\n", upload.filename.c_str());
32+
uint32_t maxSketchSpace = ((ESP.getFreeSketchSpace() + ESP.getSketchSize()) / 2) & 0xFFFFF000;
33+
if(!Update.begin(maxSketchSpace)){//start with max available size
34+
Update.printError(Serial);
35+
return;
36+
}
37+
} else if(upload.status == UPLOAD_FILE_WRITE){
38+
if(Update.write(upload.buf, upload.currentSize) != upload.currentSize){
39+
Update.printError(Serial);
40+
return;
41+
}
42+
} else if(upload.status == UPLOAD_FILE_END){
43+
if(Update.end(true)){ //true to set the size to the current progress
44+
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
45+
} else {
46+
Update.printError(Serial);
47+
}
48+
Serial.setDebugOutput(false);
49+
}
50+
yield();
51+
});
52+
server.on("/update", HTTP_POST, [](){
53+
server.sendHeader("Connection", "close");
54+
server.sendHeader("Access-Control-Allow-Origin", "*");
55+
server.send(200, "text/plain", (Update.hasError())?"FAIL":"OK");
56+
ESP.restart();
57+
});
58+
server.begin();
59+
MDNS.addService("http", "tcp", 80);
60+
61+
Serial.println("Ready! Open http:\/\/%s.local in your browser\n", host);
62+
} else {
63+
Serial.println("WiFi Failed");
64+
}
65+
}
66+
67+
void loop(void){
68+
server.handleClient();
69+
delay(1);
70+
}

0 commit comments

Comments
 (0)