1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-21 10:26:06 +03:00

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.
This commit is contained in:
John Doe 2015-07-03 22:03:01 +03:00 committed by Ivan Grokhotkov
parent 3427299065
commit 0d969e9760
4 changed files with 98 additions and 13 deletions

View File

@ -350,7 +350,7 @@ uint32_t EspClass::getFreeSketchSpace() {
uint32_t usedSize = getSketchSize();
// round one sector up
uint32_t freeSpaceStart = (usedSize + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
uint32_t freeSpaceEnd = (uint32_t)&_SPIFFS_start - 0x40200000;
uint32_t freeSpaceEnd = (uint32_t)&_SPIFFS_start - 0x40200000 - (5 * FLASH_SECTOR_SIZE);
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.printf("usedSize=%u freeSpaceStart=%u freeSpaceEnd=%u\r\n", usedSize, freeSpaceStart, freeSpaceEnd);

View File

@ -35,11 +35,14 @@ bool UpdaterClass::begin(size_t size){
_error = 0;
uint32_t usedSize = ESP.getSketchSize();
uint32_t freeSpaceStart = (usedSize + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
uint32_t freeSpaceEnd = (uint32_t)&_SPIFFS_start - 0x40200000;
uint32_t freeSpaceEnd = (uint32_t)&_SPIFFS_start - 0x40200000 - (5 * FLASH_SECTOR_SIZE);
uint32_t roundedSize = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
uint32_t freeSpaceStart = freeSpaceEnd - roundedSize;
if(roundedSize > (freeSpaceEnd - freeSpaceStart)){
//new sketch can not be more then half the size or more than the free space
//this means that max sketch size is (1MB - 20KB) / 2 for flash 2MB and above
//and the current sketch should not be more than that either
if(freeSpaceStart < usedSize || roundedSize > (freeSpaceEnd/2)){
_error = UPDATE_ERROR_SPACE;
#ifdef DEBUG_UPDATER
printError(DEBUG_UPDATER);
@ -64,7 +67,7 @@ bool UpdaterClass::begin(size_t size){
return true;
}
bool UpdaterClass::end(){
bool UpdaterClass::end(bool evenIfRemaining){
if(_size == 0){
#ifdef DEBUG_UPDATER
DEBUG_UPDATER.println("no update");
@ -72,27 +75,39 @@ bool UpdaterClass::end(){
return false;
}
if(_buffer) os_free(_buffer);
_bufferLen = 0;
if(hasError() || !isFinished()){
if(hasError() || (!isFinished() && !evenIfRemaining)){
#ifdef DEBUG_UPDATER
DEBUG_UPDATER.printf("premature end: res:%u, pos:%u/%u\n", getError(), progress(), _size);
#endif
if(_buffer) os_free(_buffer);
_bufferLen = 0;
_currentAddress = 0;
_startAddress = 0;
_size = 0;
return false;
}
if(evenIfRemaining){
if(_bufferLen > 0){
_writeBuffer();
}
_size = progress();
}
if(_buffer) os_free(_buffer);
_bufferLen = 0;
_currentAddress = 0;
eboot_command ebcmd;
ebcmd.action = ACTION_COPY_RAW;
ebcmd.args[0] = _startAddress;
ebcmd.args[1] = 0x00000;
ebcmd.args[2] = _size;
eboot_command_write(&ebcmd);
_currentAddress = 0;
#ifdef DEBUG_UPDATER
DEBUG_UPDATER.printf("Staged: address:0x%08X, size:0x%08X\n", _startAddress, _size);
#endif
_startAddress = 0;
_size = 0;
_error = UPDATE_ERROR_OK;

View File

@ -40,12 +40,12 @@ class UpdaterClass {
If all bytes are written
this call will write the config to eboot
and return true
If there is already an update running but is not finished
If there is already an update running but is not finished and !evenIfRemainanig
or there is an error
this will clear everything and return false
the last error is available through getError()
*/
bool end();
bool end(bool evenIfRemaining = false);
/*
Prints the last error to an output stream

View File

@ -0,0 +1,70 @@
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
const char* host = "esp8266-webupdate";
const char* ssid = "........";
const char* password = "........";
ESP8266WebServer server(80);
const char* serverIndex = "<form method='POST' action='/update' enctype='multipart/form-data'><input type='file' name='update'><input type='submit' value='Update'></form>";
void setup(void){
Serial.begin(115200);
Serial.println();
Serial.println("Booting Sketch...");
WiFi.mode(WIFI_AP_STA);
WiFi.begin(ssid, password);
if(WiFi.waitForConnectResult() == WL_CONNECTED){
MDNS.begin(host);
server.on("/", HTTP_GET, [](){
server.sendHeader("Connection", "close");
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/html", serverIndex);
});
server.onFileUpload([](){
if(server.uri() != "/update") return;
HTTPUpload& upload = server.upload();
if(upload.status == UPLOAD_FILE_START){
Serial.setDebugOutput(true);
Serial.printf("Update: %s\n", upload.filename.c_str());
uint32_t maxSketchSpace = ((ESP.getFreeSketchSpace() + ESP.getSketchSize()) / 2) & 0xFFFFF000;
if(!Update.begin(maxSketchSpace)){//start with max available size
Update.printError(Serial);
return;
}
} else if(upload.status == UPLOAD_FILE_WRITE){
if(Update.write(upload.buf, upload.currentSize) != upload.currentSize){
Update.printError(Serial);
return;
}
} else if(upload.status == UPLOAD_FILE_END){
if(Update.end(true)){ //true to set the size to the current progress
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
} else {
Update.printError(Serial);
}
Serial.setDebugOutput(false);
}
yield();
});
server.on("/update", HTTP_POST, [](){
server.sendHeader("Connection", "close");
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/plain", (Update.hasError())?"FAIL":"OK");
ESP.restart();
});
server.begin();
MDNS.addService("http", "tcp", 80);
Serial.println("Ready! Open http:\/\/%s.local in your browser\n", host);
} else {
Serial.println("WiFi Failed");
}
}
void loop(void){
server.handleClient();
delay(1);
}